From 29e6a370f62cb8acd4eae41b5f6eaee0c11a3cb7 Mon Sep 17 00:00:00 2001 From: Richard Wang Date: Tue, 18 Mar 2025 12:31:51 -0700 Subject: [PATCH 01/59] Add comments for feature id locations --- .../aws-sdk-core/lib/aws-sdk-core/credential_provider_chain.rb | 3 +++ gems/aws-sdk-core/lib/aws-sdk-core/shared_config.rb | 2 ++ 2 files changed, 5 insertions(+) diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/credential_provider_chain.rb b/gems/aws-sdk-core/lib/aws-sdk-core/credential_provider_chain.rb index 8f41f12219f..348c67aedf7 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/credential_provider_chain.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/credential_provider_chain.rb @@ -91,6 +91,8 @@ def static_profile_process_credentials(options) nil end + + # TODO: CREDENTIALS_ENV_VARS (g)?? def env_credentials(_options) key = %w[AWS_ACCESS_KEY_ID AMAZON_ACCESS_KEY_ID AWS_ACCESS_KEY] secret = %w[AWS_SECRET_ACCESS_KEY AMAZON_SECRET_ACCESS_KEY AWS_SECRET_KEY] @@ -150,6 +152,7 @@ def assume_role_credentials(options) def assume_role_web_identity_credentials(options) region = options[:config].region if options[:config] if (role_arn = ENV['AWS_ROLE_ARN']) && (token_file = ENV['AWS_WEB_IDENTITY_TOKEN_FILE']) + # TODO: CREDENTIALS_ENV_VARS_STS_WEB_ID_TOKEN (h)?? cfg = { role_arn: role_arn, web_identity_token_file: token_file, diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/shared_config.rb b/gems/aws-sdk-core/lib/aws-sdk-core/shared_config.rb index 1fea8bdbccd..b2dbabd3693 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/shared_config.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/shared_config.rb @@ -254,9 +254,11 @@ def assume_role_from_profile(cfg, profile, opts, chain_config) 'a credential_source. For assume role credentials, must '\ 'provide only source_profile or credential_source, not both.' elsif opts[:source_profile] + # TODO: CREDENTIALS_PROFILE_SOURCE_PROFILE (o) opts[:visited_profiles] ||= Set.new opts[:credentials] = resolve_source_profile(opts[:source_profile], opts) if opts[:credentials] + # TODO: CREDENTIALS_PROFILE (n) opts[:role_session_name] ||= prof_cfg['role_session_name'] opts[:role_session_name] ||= 'default_session' opts[:role_arn] ||= prof_cfg['role_arn'] From 16c86ccce85e16c0601701b0b11da21fd7a1eb22 Mon Sep 17 00:00:00 2001 From: Richard Wang Date: Tue, 18 Mar 2025 14:13:15 -0700 Subject: [PATCH 02/59] Add new feature ids to METRICS --- .../lib/aws-sdk-core/plugins/user_agent.rb | 28 ++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/plugins/user_agent.rb b/gems/aws-sdk-core/lib/aws-sdk-core/plugins/user_agent.rb index 2d1e6e8ee5a..d09769703c3 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/plugins/user_agent.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/plugins/user_agent.rb @@ -34,7 +34,33 @@ class UserAgent < Seahorse::Client::Plugin "FLEXIBLE_CHECKSUMS_REQ_WHEN_SUPPORTED" : "Z", "FLEXIBLE_CHECKSUMS_REQ_WHEN_REQUIRED" : "a", "FLEXIBLE_CHECKSUMS_RES_WHEN_SUPPORTED" : "b", - "FLEXIBLE_CHECKSUMS_RES_WHEN_REQUIRED" : "c" + "FLEXIBLE_CHECKSUMS_RES_WHEN_REQUIRED" : "c", + "DDB_MAPPER": "d", + "CREDENTIALS_CODE" : "e", + "CREDENTIALS_JVM_SYSTEM_PROPERTIES" : "f", + "CREDENTIALS_ENV_VARS" : "g", + "CREDENTIALS_ENV_VARS_STS_WEB_ID_TOKEN" : "h", + "CREDENTIALS_STS_ASSUME_ROLE" : "i", + "CREDENTIALS_STS_ASSUME_ROLE_SAML" : "j", + "CREDENTIALS_STS_ASSUME_ROLE_WEB_ID" : "k", + "CREDENTIALS_STS_FEDERATION_TOKEN" : "l", + "CREDENTIALS_STS_SESSION_TOKEN" : "m", + "CREDENTIALS_PROFILE" : "n", + "CREDENTIALS_PROFILE_SOURCE_PROFILE" : "o", + "CREDENTIALS_PROFILE_NAMED_PROVIDER" : "p", + "CREDENTIALS_PROFILE_STS_WEB_ID_TOKEN" : "q", + "CREDENTIALS_PROFILE_SSO" : "r", + "CREDENTIALS_SSO" : "s", + "CREDENTIALS_PROFILE_SSO_LEGACY" : "t", + "CREDENTIALS_SSO_LEGACY" : "u", + "CREDENTIALS_PROFILE_PROCESS" : "v", + "CREDENTIALS_PROCESS" : "w", + "CREDENTIALS_BOTO2_CONFIG_FILE" : "x", + "CREDENTIALS_AWS_SDK_STORE" : "y", + "CREDENTIALS_HTTP" : "z", + "CREDENTIALS_IMDS" : "0", + "SSO_LOGIN_DEVICE" : "1", + "SSO_LOGIN_AUTH" : "2" } METRICS From 2938a7c55dbe07ef3df0d73c58b0503a00ef2df3 Mon Sep 17 00:00:00 2001 From: Richard Wang Date: Thu, 20 Mar 2025 08:44:08 -0700 Subject: [PATCH 03/59] Add comments and change priority of user agent --- .../aws-sdk-core/assume_role_credentials.rb | 3 + .../assume_role_web_identity_credentials.rb | 3 + .../aws-sdk-core/credential_provider_chain.rb | 91 ++++++++++++++++++- .../lib/aws-sdk-core/plugins/sign.rb | 33 ++++++- .../lib/aws-sdk-core/plugins/user_agent.rb | 10 +- .../lib/aws-sdk-core/process_credentials.rb | 2 + .../lib/aws-sdk-core/shared_config.rb | 9 +- .../lib/aws-sdk-core/sso_credentials.rb | 8 ++ 8 files changed, 154 insertions(+), 5 deletions(-) diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_credentials.rb b/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_credentials.rb index ad9e6a4df6f..183b35a6b80 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_credentials.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_credentials.rb @@ -64,6 +64,9 @@ def initialize(options = {}) def refresh resp = @client.assume_role(@assume_role_params) creds = resp.credentials + # TODO: CREDENTIALS_STS_ASSUME_ROLE + # Call will include "o" (from #assume_role_from_profile) and "n"/"qk"/"vw"/"rs"/"tu" (from #resolve_source_profile) + # OR call will include "p" (from #assume_role_from_profile) and "0"/"z" (from #credentials_from_source) @credentials = Credentials.new( creds.access_key_id, creds.secret_access_key, diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_web_identity_credentials.rb b/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_web_identity_credentials.rb index c07828f32a1..d45866c2368 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_web_identity_credentials.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_web_identity_credentials.rb @@ -73,6 +73,9 @@ def refresh # read from token file everytime it refreshes @assume_role_web_identity_params[:web_identity_token] = _token_from_file(@token_file) + # TODO: CREDENTIALS_STS_ASSUME_ROLE_WEB_ID (k) + # Call will include "q" (from #assume_role_web_identity_credentials_from_config) + # OR call will include "h" (from #assume_role_web_identity_credentials) resp = @client.assume_role_with_web_identity(@assume_role_web_identity_params) creds = resp.credentials @credentials = Credentials.new( diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/credential_provider_chain.rb b/gems/aws-sdk-core/lib/aws-sdk-core/credential_provider_chain.rb index 348c67aedf7..5cc5f826bf2 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/credential_provider_chain.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/credential_provider_chain.rb @@ -11,7 +11,76 @@ def initialize(config = nil) def resolve providers.each do |method_name, options| provider = send(method_name, options.merge(config: @config)) - return provider if provider && provider.set? + if provider && provider.set? + puts method_name + puts provider + case method_name.to_s + when "static_credentials" + puts "CREDENTIALS_PROFILE: n" + when "static_profile_assume_role_web_identity_credentials" + puts "CREDENTIALS_PROFILE_STS_WEB_ID_TOKEN and CREDENTIALS_STS_ASSUME_ROLE_WEB_ID: qk" + when "static_profile_sso_credentials" + puts "CREDENTIALS_PROFILE_SSO and CREDENTIALS_SSO: rs (NEW)" + puts "OR" + puts "CREDENTIALS_PROFILE_SSO_LEGACY and CREDENTIALS_SSO_LEGACY: tu (LEGACY)" + when "static_profile_assume_role_credentials" + puts "CREDENTIALS_PROFILE_SOURCE_PROFILE: o and ( \ + CREDENTIALS_PROFILE: n or \ + CREDENTIALS_PROFILE_STS_WEB_ID_TOKEN and CREDENTIALS_STS_ASSUME_ROLE_WEB_ID: qk or \ + CREDENTIALS_PROFILE_PROCESS and CREDENTIALS_PROCESS: vw or \ + CREDENTIALS_PROFILE_SSO and CREDENTIALS_SSO: rs (NEW) or \ + CREDENTIALS_PROFILE_SSO_LEGACY and CREDENTIALS_SSO_LEGACY: tu (LEGACY) \ + ) \ + and CREDENTIALS_STS_ASSUME_ROLE: i" + puts "OR" + puts "CREDENTIALS_PROFILE_NAMED_PROVIDER: p and ( \ + CREDENTIALS_IMDS: 0 or \ + CREDENTIALS_HTTP: z \ + ) \ + and CREDENTIALS_STS_ASSUME_ROLE: i" + when "static_profile_credentials" + puts "CREDENTIALS_PROFILE: n" + when "static_profile_process_credentials" + puts "CREDENTIALS_PROFILE_PROCESS and CREDENTIALS_PROCESS: vw" + when "env_credentials" + puts "CREDENTIALS_ENV_VARS: g" + when "assume_role_web_identity_credentials" + puts "CREDENTIALS_ENV_VARS_STS_WEB_ID_TOKEN and CREDENTIALS_STS_ASSUME_ROLE_WEB_ID: hk" + puts "OR" + puts "CREDENTIALS_PROFILE_STS_WEB_ID_TOKEN and CREDENTIALS_STS_ASSUME_ROLE_WEB_ID: qk" + when "sso_credentials" + puts "CREDENTIALS_PROFILE_SSO and CREDENTIALS_SSO: rs (NEW)" + puts "OR" + puts "CREDENTIALS_PROFILE_SSO_LEGACY and CREDENTIALS_SSO_LEGACY: tu (LEGACY)" + when "assume_role_credentials" + puts "CREDENTIALS_PROFILE_SOURCE_PROFILE: o and ( \ + CREDENTIALS_PROFILE: n or \ + CREDENTIALS_PROFILE_STS_WEB_ID_TOKEN and CREDENTIALS_STS_ASSUME_ROLE_WEB_ID: qk or \ + CREDENTIALS_PROFILE_PROCESS and CREDENTIALS_PROCESS: vw or \ + CREDENTIALS_PROFILE_SSO and CREDENTIALS_SSO: rs (NEW) or \ + CREDENTIALS_PROFILE_SSO_LEGACY and CREDENTIALS_SSO_LEGACY: tu (LEGACY) \ + ) \ + and CREDENTIALS_STS_ASSUME_ROLE: i" + puts "OR" + puts "CREDENTIALS_PROFILE_NAMED_PROVIDER: p and ( \ + CREDENTIALS_IMDS: 0 or \ + CREDENTIALS_HTTP: z \ + ) \ + and CREDENTIALS_STS_ASSUME_ROLE: i" + when "shared_credentials" + puts "CREDENTIALS_PROFILE: n" + when "process_credentials" + puts "CREDENTIALS_PROFILE_PROCESS and CREDENTIALS_PROCESS: vw" + when "instance_profile_credentials" + puts "CREDENTIALS_HTTP (z)" + puts "OR" + puts "CREDENTIALS_IMDS (0)" + else + puts method_name + puts "!! UNKNOWN !!" + end + return provider + end end nil end @@ -40,7 +109,9 @@ def providers ] end + # TODO: CREDENTIALS_PROFILE (n)?? def static_credentials(options) + puts "!! STATIC_CREDENTIALS !!" if options[:config] Credentials.new( options[:config].access_key_id, @@ -52,6 +123,7 @@ def static_credentials(options) end def static_profile_assume_role_web_identity_credentials(options) + puts "!! STATIC_PROFILE_ASSUME_ROLE_WEB_IDENTITY_CREDENTIALS !!" if Aws.shared_config.config_enabled? && options[:config] && options[:config].profile Aws.shared_config.assume_role_web_identity_credentials_from_config( profile: options[:config].profile, @@ -61,6 +133,7 @@ def static_profile_assume_role_web_identity_credentials(options) end def static_profile_sso_credentials(options) + puts "!! STATIC_PROFILE_SSO_CREDENTIALS !!" if Aws.shared_config.config_enabled? && options[:config] && options[:config].profile Aws.shared_config.sso_credentials_from_config( profile: options[:config].profile @@ -69,12 +142,14 @@ def static_profile_sso_credentials(options) end def static_profile_assume_role_credentials(options) + puts "!! STATIC_PROFILE_ASSUME_ROLE_CREDENTIALS !!" if Aws.shared_config.config_enabled? && options[:config] && options[:config].profile assume_role_with_profile(options, options[:config].profile) end end def static_profile_credentials(options) + puts "!! STATIC_PROFILE_CREDENTIALS !!" if options[:config] && options[:config].profile SharedCredentials.new(profile_name: options[:config].profile) end @@ -83,6 +158,7 @@ def static_profile_credentials(options) end def static_profile_process_credentials(options) + puts "!! STATIC_PROFILE_PROCESS_CREDENTIALS !!" if Aws.shared_config.config_enabled? && options[:config] && options[:config].profile process_provider = Aws.shared_config.credential_process(profile: options[:config].profile) ProcessCredentials.new([process_provider]) if process_provider @@ -94,6 +170,7 @@ def static_profile_process_credentials(options) # TODO: CREDENTIALS_ENV_VARS (g)?? def env_credentials(_options) + puts "!! ENV_CREDENTIALS !!" key = %w[AWS_ACCESS_KEY_ID AMAZON_ACCESS_KEY_ID AWS_ACCESS_KEY] secret = %w[AWS_SECRET_ACCESS_KEY AMAZON_SECRET_ACCESS_KEY AWS_SECRET_KEY] token = %w[AWS_SESSION_TOKEN AMAZON_SESSION_TOKEN] @@ -118,6 +195,7 @@ def determine_profile_name(options) end def shared_credentials(options) + puts "!! SHARED_CREDENTIALS !!" profile_name = determine_profile_name(options) SharedCredentials.new(profile_name: profile_name) rescue Errors::NoSuchProfileError @@ -125,9 +203,12 @@ def shared_credentials(options) end def process_credentials(options) + puts "!! PROCESS_CREDENTIALS !!" profile_name = determine_profile_name(options) + puts profile_name if Aws.shared_config.config_enabled? process_provider = Aws.shared_config.credential_process(profile: profile_name) + puts process_provider ProcessCredentials.new([process_provider]) if process_provider end rescue Errors::NoSuchProfileError @@ -135,6 +216,7 @@ def process_credentials(options) end def sso_credentials(options) + puts "!! SSO_CREDENTIALS !!" profile_name = determine_profile_name(options) if Aws.shared_config.config_enabled? Aws.shared_config.sso_credentials_from_config(profile: profile_name) @@ -144,15 +226,17 @@ def sso_credentials(options) end def assume_role_credentials(options) + puts "!! ASSUME_ROLE_CREDENTIALS !!" if Aws.shared_config.config_enabled? assume_role_with_profile(options, determine_profile_name(options)) end end def assume_role_web_identity_credentials(options) + puts "!! ASSUME_ROLE_WEB_IDENTITY_CREDENTIALS !!" region = options[:config].region if options[:config] if (role_arn = ENV['AWS_ROLE_ARN']) && (token_file = ENV['AWS_WEB_IDENTITY_TOKEN_FILE']) - # TODO: CREDENTIALS_ENV_VARS_STS_WEB_ID_TOKEN (h)?? + # TODO: CREDENTIALS_ENV_VARS_STS_WEB_ID_TOKEN (h) cfg = { role_arn: role_arn, web_identity_token_file: token_file, @@ -170,11 +254,14 @@ def assume_role_web_identity_credentials(options) end def instance_profile_credentials(options) + puts "!! INSTANCE_PROFILE_CREDENTIALS !!" profile_name = determine_profile_name(options) if ENV['AWS_CONTAINER_CREDENTIALS_RELATIVE_URI'] || ENV['AWS_CONTAINER_CREDENTIALS_FULL_URI'] + # TODO: CREDENTIALS_HTTP (z) ECSCredentials.new(options) else + # TODO: CREDENTIALS_IMDS (0) InstanceProfileCredentials.new(options.merge(profile: profile_name)) end end diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/plugins/sign.rb b/gems/aws-sdk-core/lib/aws-sdk-core/plugins/sign.rb index 80d98bca931..9610a4627fc 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/plugins/sign.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/plugins/sign.rb @@ -41,6 +41,9 @@ def self.signer_for(auth_scheme, config, sigv4_region_override = nil, sigv4_cred class Handler < Seahorse::Client::Handler def call(context) # Skip signing if using sigv2 signing from s3_signer in S3 + puts "sign Caller" + puts caller + credentials = nil unless v2_signing?(context.config) signer = Sign.signer_for( context[:auth_scheme], @@ -48,13 +51,28 @@ def call(context) context[:sigv4_region], context[:sigv4_credentials] ) + pp "SIGNER HERE" + pp signer + credentials = signer.signer.credentials_provider signer.sign(context) end - @handler.call(context) + puts "With metric now" + with_metric(credentials) { @handler.call(context) } end private + def with_metric(credentials, &block) + puts "in with metric" + if credentials.is_a? Aws::Credentials + puts "Is a credentials" + Aws::Plugins::UserAgent.metric('CREDENTIALS_CODE', &block) + else + puts "Is not a credentials" + Aws::Plugins::UserAgent.metric('CREDENTIALS_HTTP', &block) + end + end + def v2_signing?(config) # 's3' is legacy signing, 'v4' is default config.respond_to?(:signature_version) && @@ -92,6 +110,8 @@ def sign_event(*args) # @api private class SignatureV4 + attr_reader :signer + def initialize(auth_scheme, config, sigv4_overrides = {}) scheme_name = auth_scheme['name'] @@ -147,6 +167,17 @@ def sign(context) context[:string_to_sign] = signature.string_to_sign end + # def with_metrics(&block) + # puts "Printing signer" + # pp @signer + # credentials = @signer.credentials_provider + # if credentials.is_a? Aws::Credentials + # Aws::Plugins::UserAgent.metric('CREDENTIALS_CODE', &block) + # else + # Aws::Plugins::UserAgent.metric('CREDENTIALS_HTTP', &block) + # end + # end + def presign_url(*args) @signer.presign_url(*args) end diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/plugins/user_agent.rb b/gems/aws-sdk-core/lib/aws-sdk-core/plugins/user_agent.rb index d09769703c3..72fe15e073f 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/plugins/user_agent.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/plugins/user_agent.rb @@ -92,7 +92,10 @@ def self.metric(*metrics, &block) Thread.current[:aws_sdk_core_user_agent_metric] ||= [] metrics = metrics.map { |metric| METRICS[metric] }.compact Thread.current[:aws_sdk_core_user_agent_metric].concat(metrics) + # puts "METRICS HERE" + # pp Thread.current[:aws_sdk_core_user_agent_metric] block.call + # puts "Block called \n" ensure Thread.current[:aws_sdk_core_user_agent_metric].pop(metrics.size) end @@ -131,6 +134,8 @@ def to_s ua += " #{framework_m}" end if (metric_m = metric_metadata) + puts "Yes metric metadata" + puts caller ua += " #{metric_m}" end if @context.config.user_agent_suffix @@ -213,6 +218,9 @@ def metric_metadata end metrics = Thread.current[:aws_sdk_core_user_agent_metric].join(',') + + puts "Metrics metadata" + pp metrics # Metric metadata is limited to 1024 bytes return "m/#{metrics}" if metrics.bytesize <= 1024 @@ -222,7 +230,7 @@ def metric_metadata end end - handler(Handler, step: :sign, priority: 97) + handler(Handler, step: :sign, priority: 49) end end end diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/process_credentials.rb b/gems/aws-sdk-core/lib/aws-sdk-core/process_credentials.rb index 55cc42ba8e5..5f2c27fece6 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/process_credentials.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/process_credentials.rb @@ -33,6 +33,7 @@ def initialize(process) warn('Passing a single string to Aws::ProcessCredentials.new '\ 'is insecure, please use use an array of system arguments instead') end + # TODO: CREDENTIALS_PROFILE_PROCESS (v) @process = process @credentials = credentials_from_process @async_refresh = false @@ -56,6 +57,7 @@ def credentials_from_process ) end + # TODO: CREDENTIALS_PROCESS (w) begin creds_json = Aws::Json.load(raw_out) rescue Aws::Json::ParseError diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/shared_config.rb b/gems/aws-sdk-core/lib/aws-sdk-core/shared_config.rb index b2dbabd3693..3cf7a143eeb 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/shared_config.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/shared_config.rb @@ -132,6 +132,7 @@ def assume_role_web_identity_credentials_from_config(opts = {}) if @config_enabled && @parsed_config entry = @parsed_config.fetch(p, {}) if entry['web_identity_token_file'] && entry['role_arn'] + # TODO: CREDENTIALS_PROFILE_STS_WEB_ID_TOKEN (q) cfg = { role_arn: entry['role_arn'], web_identity_token_file: entry['web_identity_token_file'], @@ -258,7 +259,6 @@ def assume_role_from_profile(cfg, profile, opts, chain_config) opts[:visited_profiles] ||= Set.new opts[:credentials] = resolve_source_profile(opts[:source_profile], opts) if opts[:credentials] - # TODO: CREDENTIALS_PROFILE (n) opts[:role_session_name] ||= prof_cfg['role_session_name'] opts[:role_session_name] ||= 'default_session' opts[:role_arn] ||= prof_cfg['role_arn'] @@ -274,6 +274,7 @@ def assume_role_from_profile(cfg, profile, opts, chain_config) ' source_profile does not have credentials.' end elsif credential_source + # TODO: CREDENTIALS_PROFILE_NAMED_PROVIDER (p) opts[:credentials] = credentials_from_source( credential_source, chain_config @@ -310,15 +311,19 @@ def resolve_source_profile(profile, opts = {}) end if (creds = credentials(profile: profile)) + # TODO: CREDENTIALS_PROFILE (n) creds # static credentials elsif profile_config && profile_config['source_profile'] opts.delete(:source_profile) assume_role_credentials_from_config(opts.merge(profile: profile)) elsif (provider = assume_role_web_identity_credentials_from_config(opts.merge(profile: profile))) + # TODO: CREDENTIALS_PROFILE_STS_WEB_ID_TOKEN and CREDENTIALS_STS_ASSUME_ROLE_WEB_ID (qk) provider.credentials if provider.credentials.set? elsif (provider = assume_role_process_credentials_from_config(profile)) + # TODO: CREDENTIALS_PROFILE_PROCESS and CREDENTIALS_PROCESS (vw) provider.credentials if provider.credentials.set? elsif (provider = sso_credentials_from_config(profile: profile)) + # TODO: CREDENTIALS_PROFILE_SSO and CREDENTIALS_SSO (rs) or CREDENTIALS_PROFILE_SSO_LEGACY and CREDENTIALS_SSO_LEGACY (tu) provider.credentials if provider.credentials.set? end end @@ -326,12 +331,14 @@ def resolve_source_profile(profile, opts = {}) def credentials_from_source(credential_source, config) case credential_source when 'Ec2InstanceMetadata' + # TODO: CREDENTIALS_IMDS (0) InstanceProfileCredentials.new( retries: config ? config.instance_profile_credentials_retries : 0, http_open_timeout: config ? config.instance_profile_credentials_timeout : 1, http_read_timeout: config ? config.instance_profile_credentials_timeout : 1 ) when 'EcsContainer' + # TODO: CREDENTIALS_HTTP (z) ECSCredentials.new else raise Errors::InvalidCredentialSourceError, "Unsupported credential_source: #{credential_source}" diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/sso_credentials.rb b/gems/aws-sdk-core/lib/aws-sdk-core/sso_credentials.rb index 3c4785f5c8c..739d2da84f1 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/sso_credentials.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/sso_credentials.rb @@ -69,6 +69,8 @@ class SSOCredentials def initialize(options = {}) options = options.select {|k, v| !v.nil? } if (options[:sso_session]) + puts "New SSO" + # TODO: CREDENTIALS_PROFILE_SSO (r) missing_keys = TOKEN_PROVIDER_REQUIRED_OPTS.select { |k| options[k].nil? } unless missing_keys.empty? raise ArgumentError, "Missing required keys: #{missing_keys}" @@ -92,6 +94,8 @@ def initialize(options = {}) @client = Aws::SSO::Client.new(client_opts) end else # legacy behavior + puts "Legacy SSO" + # TODO: CREDENTIALS_PROFILE_SSO_LEGACY (t) missing_keys = LEGACY_REQUIRED_OPTS.select { |k| options[k].nil? } unless missing_keys.empty? raise ArgumentError, "Missing required keys: #{missing_keys}" @@ -140,12 +144,16 @@ def read_cached_token def refresh c = if @legacy cached_token = read_cached_token + # TODO: CREDENTIALS_SSO_LEGACY (u) + # Call will include "t" (from #initialize) @client.get_role_credentials( account_id: @sso_account_id, role_name: @sso_role_name, access_token: cached_token['accessToken'] ).role_credentials else + # TODO: CREDENTIALS_SSO (s) + # Call will include "r" (from #initialize) @client.get_role_credentials( account_id: @sso_account_id, role_name: @sso_role_name, From 696e1a6d0c812932c2ed8d86faaf897dff4d5c20 Mon Sep 17 00:00:00 2001 From: Richard Wang Date: Thu, 20 Mar 2025 09:22:05 -0700 Subject: [PATCH 04/59] Add skeleton check --- .../lib/aws-sdk-core/plugins/sign.rb | 26 +++++++++++++++++-- .../lib/aws-sdk-core/plugins/user_agent.rb | 5 ++-- 2 files changed, 26 insertions(+), 5 deletions(-) diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/plugins/sign.rb b/gems/aws-sdk-core/lib/aws-sdk-core/plugins/sign.rb index 9610a4627fc..7cfe2a15e8f 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/plugins/sign.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/plugins/sign.rb @@ -64,12 +64,34 @@ def call(context) def with_metric(credentials, &block) puts "in with metric" + metrics = [] if credentials.is_a? Aws::Credentials puts "Is a credentials" - Aws::Plugins::UserAgent.metric('CREDENTIALS_CODE', &block) + Aws::Plugins::UserAgent.metric('CREDENTIALS_ENV_VARS', &block) + elsif credentials.is_a? Aws::AssumeRoleWebIdentityCredentials + puts "Is a assume role credentials" + Aws::Plugins::UserAgent.metric('CREDENTIALS_STS_ASSUME_ROLE_WEB_ID', &block) + elsif credentials.is_a? Aws::SSOCredentials + puts "Is a sso credentials" + Aws::Plugins::UserAgent.metric('CREDENTIALS_PROFILE_SSO', &block) + elsif credentials.is_a? Aws::AssumeRoleCredentials + puts "Is a assume role credentials" + Aws::Plugins::UserAgent.metric('CREDENTIALS_PROFILE_SOURCE_PROFILE', &block) + elsif credentials.is_a? Aws::SharedCredentials + puts "Is a shared credentials" + Aws::Plugins::UserAgent.metric('CREDENTIALS_PROFILE', &block) + elsif credentials.is_a? Aws::ProcessCredentials + puts "Is a process credentials" + Aws::Plugins::UserAgent.metric('CREDENTIALS_PROFILE_PROCESS', &block) + elsif credentials.is_a? Aws::ECSCredentials + puts "Is a ecs credentials" + Aws::Plugins::UserAgent.metric('CREDENTIALS_HTTP', &block) + elsif credentials.is_a? Aws::InstanceProfileCredentials + puts "Is a instance profile credentials" + Aws::Plugins::UserAgent.metric('CREDENTIALS_IMDS', &block) else puts "Is not a credentials" - Aws::Plugins::UserAgent.metric('CREDENTIALS_HTTP', &block) + block.call end end diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/plugins/user_agent.rb b/gems/aws-sdk-core/lib/aws-sdk-core/plugins/user_agent.rb index 72fe15e073f..3d23c9aeed2 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/plugins/user_agent.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/plugins/user_agent.rb @@ -92,10 +92,9 @@ def self.metric(*metrics, &block) Thread.current[:aws_sdk_core_user_agent_metric] ||= [] metrics = metrics.map { |metric| METRICS[metric] }.compact Thread.current[:aws_sdk_core_user_agent_metric].concat(metrics) - # puts "METRICS HERE" - # pp Thread.current[:aws_sdk_core_user_agent_metric] + puts "METRICS HERE" + pp Thread.current[:aws_sdk_core_user_agent_metric] block.call - # puts "Block called \n" ensure Thread.current[:aws_sdk_core_user_agent_metric].pop(metrics.size) end From ed8a0fcaeb94c8b276c640e396024865424e8ea1 Mon Sep 17 00:00:00 2001 From: Richard Wang Date: Fri, 21 Mar 2025 08:50:10 -0700 Subject: [PATCH 05/59] Add skeleton for all except assume role --- .../assume_role_web_identity_credentials.rb | 2 + .../aws-sdk-core/credential_provider_chain.rb | 31 +++++++--- .../lib/aws-sdk-core/credentials.rb | 4 ++ .../lib/aws-sdk-core/ecs_credentials.rb | 3 + .../instance_profile_credentials.rb | 3 + .../lib/aws-sdk-core/plugins/sign.rb | 59 ++++++++++--------- .../lib/aws-sdk-core/plugins/user_agent.rb | 16 ++++- .../lib/aws-sdk-core/process_credentials.rb | 5 ++ .../lib/aws-sdk-core/shared_config.rb | 6 +- .../lib/aws-sdk-core/shared_credentials.rb | 3 + .../lib/aws-sdk-core/sso_credentials.rb | 2 + 11 files changed, 92 insertions(+), 42 deletions(-) diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_web_identity_credentials.rb b/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_web_identity_credentials.rb index d45866c2368..1c5c470f1af 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_web_identity_credentials.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_web_identity_credentials.rb @@ -61,7 +61,9 @@ def initialize(options = {}) @assume_role_web_identity_params[:role_session_name] = _session_name end @client = client_opts[:client] || STS::Client.new(client_opts.merge(credentials: nil)) + @metrics = options[:metrics] super + @metrics << 'CREDENTIALS_STS_ASSUME_ROLE_WEB_ID' if @metrics end # @return [STS::Client] diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/credential_provider_chain.rb b/gems/aws-sdk-core/lib/aws-sdk-core/credential_provider_chain.rb index 5cc5f826bf2..b16d633bf63 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/credential_provider_chain.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/credential_provider_chain.rb @@ -9,6 +9,7 @@ def initialize(config = nil) # @return [CredentialProvider, nil] def resolve + puts "RESOLVING CREDENTIALS" providers.each do |method_name, options| provider = send(method_name, options.merge(config: @config)) if provider && provider.set? @@ -117,7 +118,8 @@ def static_credentials(options) options[:config].access_key_id, options[:config].secret_access_key, options[:config].session_token, - account_id: options[:config].account_id + account_id: options[:config].account_id, + metrics: ['CREDENTIALS_PROFILE'] ) end end @@ -151,7 +153,7 @@ def static_profile_assume_role_credentials(options) def static_profile_credentials(options) puts "!! STATIC_PROFILE_CREDENTIALS !!" if options[:config] && options[:config].profile - SharedCredentials.new(profile_name: options[:config].profile) + SharedCredentials.new(profile_name: options[:config].profile, metrics: ['CREDENTIALS_PROFILE']) end rescue Errors::NoSuchProfileError nil @@ -161,7 +163,11 @@ def static_profile_process_credentials(options) puts "!! STATIC_PROFILE_PROCESS_CREDENTIALS !!" if Aws.shared_config.config_enabled? && options[:config] && options[:config].profile process_provider = Aws.shared_config.credential_process(profile: options[:config].profile) - ProcessCredentials.new([process_provider]) if process_provider + if process_provider + credentials = ProcessCredentials.new([process_provider]) + credentials.metrics = ['CREDENTIALS_PROFILE_PROCESS', 'CREDENTIALS_PROCESS'] + return credentials + end end rescue Errors::NoSuchProfileError nil @@ -179,7 +185,8 @@ def env_credentials(_options) envar(key), envar(secret), envar(token), - account_id: envar(account_id) + account_id: envar(account_id), + metrics: ['CREDENTIALS_ENV_VARS'] ) end @@ -197,7 +204,7 @@ def determine_profile_name(options) def shared_credentials(options) puts "!! SHARED_CREDENTIALS !!" profile_name = determine_profile_name(options) - SharedCredentials.new(profile_name: profile_name) + SharedCredentials.new(profile_name: profile_name, metrics: ['CREDENTIALS_PROFILE']) rescue Errors::NoSuchProfileError nil end @@ -209,7 +216,11 @@ def process_credentials(options) if Aws.shared_config.config_enabled? process_provider = Aws.shared_config.credential_process(profile: profile_name) puts process_provider - ProcessCredentials.new([process_provider]) if process_provider + if process_provider + credentials = ProcessCredentials.new([process_provider]) + credentials.metrics = ['CREDENTIALS_PROFILE_PROCESS', 'CREDENTIALS_PROCESS'] + return credentials + end end rescue Errors::NoSuchProfileError nil @@ -240,7 +251,8 @@ def assume_role_web_identity_credentials(options) cfg = { role_arn: role_arn, web_identity_token_file: token_file, - role_session_name: ENV['AWS_ROLE_SESSION_NAME'] + role_session_name: ENV['AWS_ROLE_SESSION_NAME'], + metrics: ['CREDENTIALS_ENV_VARS_STS_WEB_ID_TOKEN'] } cfg[:region] = region if region AssumeRoleWebIdentityCredentials.new(cfg) @@ -259,10 +271,11 @@ def instance_profile_credentials(options) if ENV['AWS_CONTAINER_CREDENTIALS_RELATIVE_URI'] || ENV['AWS_CONTAINER_CREDENTIALS_FULL_URI'] # TODO: CREDENTIALS_HTTP (z) - ECSCredentials.new(options) + options[:metrics] = 'CREDENTIALS_HTTP' + ECSCredentials.new(options.merge(metrics: ['CREDENTIALS_HTTP'])) else # TODO: CREDENTIALS_IMDS (0) - InstanceProfileCredentials.new(options.merge(profile: profile_name)) + InstanceProfileCredentials.new(options.merge(profile: profile_name, metrics: ['CREDENTIALS_IMDS'])) end end diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/credentials.rb b/gems/aws-sdk-core/lib/aws-sdk-core/credentials.rb index 93bf3a0026f..8961e8fd804 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/credentials.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/credentials.rb @@ -14,6 +14,7 @@ def initialize(access_key_id, secret_access_key, session_token = nil, @secret_access_key = secret_access_key @session_token = session_token @account_id = kwargs[:account_id] + @metrics = kwargs[:metrics] end # @return [String] @@ -28,6 +29,9 @@ def initialize(access_key_id, secret_access_key, session_token = nil, # @return [String, nil] attr_reader :account_id + # @return [String, nil] + attr_reader :metrics + # @return [Credentials] def credentials self diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/ecs_credentials.rb b/gems/aws-sdk-core/lib/aws-sdk-core/ecs_credentials.rb index 002ee55c067..5bced7119fe 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/ecs_credentials.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/ecs_credentials.rb @@ -77,6 +77,7 @@ def initialize(options = {}) @http_debug_output = options[:http_debug_output] @backoff = backoff(options[:backoff]) @async_refresh = false + @metrics = options[:metrics] super end @@ -84,6 +85,8 @@ def initialize(options = {}) # fetch credentials from the instance metadata service. Defaults to 0. attr_reader :retries + attr_reader :metrics + private def initialize_uri(options, credential_path, endpoint) diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/instance_profile_credentials.rb b/gems/aws-sdk-core/lib/aws-sdk-core/instance_profile_credentials.rb index d1b7d337ed8..373de3810b8 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/instance_profile_credentials.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/instance_profile_credentials.rb @@ -90,6 +90,7 @@ def initialize(options = {}) @token = nil @no_refresh_until = nil @async_refresh = false + @metrics = options[:metrics] super end @@ -98,6 +99,8 @@ def initialize(options = {}) # the default credential chain ({Aws::CredentialProviderChain}). attr_reader :retries + attr_reader :metrics + private def resolve_endpoint_mode(options) diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/plugins/sign.rb b/gems/aws-sdk-core/lib/aws-sdk-core/plugins/sign.rb index 7cfe2a15e8f..f6d2cba3c45 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/plugins/sign.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/plugins/sign.rb @@ -41,8 +41,6 @@ def self.signer_for(auth_scheme, config, sigv4_region_override = nil, sigv4_cred class Handler < Seahorse::Client::Handler def call(context) # Skip signing if using sigv2 signing from s3_signer in S3 - puts "sign Caller" - puts caller credentials = nil unless v2_signing?(context.config) signer = Sign.signer_for( @@ -65,34 +63,39 @@ def call(context) def with_metric(credentials, &block) puts "in with metric" metrics = [] - if credentials.is_a? Aws::Credentials - puts "Is a credentials" - Aws::Plugins::UserAgent.metric('CREDENTIALS_ENV_VARS', &block) - elsif credentials.is_a? Aws::AssumeRoleWebIdentityCredentials - puts "Is a assume role credentials" - Aws::Plugins::UserAgent.metric('CREDENTIALS_STS_ASSUME_ROLE_WEB_ID', &block) - elsif credentials.is_a? Aws::SSOCredentials - puts "Is a sso credentials" - Aws::Plugins::UserAgent.metric('CREDENTIALS_PROFILE_SSO', &block) - elsif credentials.is_a? Aws::AssumeRoleCredentials - puts "Is a assume role credentials" - Aws::Plugins::UserAgent.metric('CREDENTIALS_PROFILE_SOURCE_PROFILE', &block) - elsif credentials.is_a? Aws::SharedCredentials - puts "Is a shared credentials" - Aws::Plugins::UserAgent.metric('CREDENTIALS_PROFILE', &block) - elsif credentials.is_a? Aws::ProcessCredentials - puts "Is a process credentials" - Aws::Plugins::UserAgent.metric('CREDENTIALS_PROFILE_PROCESS', &block) - elsif credentials.is_a? Aws::ECSCredentials - puts "Is a ecs credentials" - Aws::Plugins::UserAgent.metric('CREDENTIALS_HTTP', &block) - elsif credentials.is_a? Aws::InstanceProfileCredentials - puts "Is a instance profile credentials" - Aws::Plugins::UserAgent.metric('CREDENTIALS_IMDS', &block) + # Add check if flag isn't set, then emit Credentials CODE + if !credentials.metrics + puts "Credentials from code" + metrics << 'CREDENTIALS_CODE' else - puts "Is not a credentials" - block.call + if credentials.is_a? Aws::Credentials + puts "Is a credentials" + (metrics << credentials.metrics).flatten! + elsif credentials.is_a? Aws::AssumeRoleWebIdentityCredentials + puts "Is a assume role credentials" + (metrics << credentials.metrics).flatten! + elsif credentials.is_a? Aws::SSOCredentials + puts "Is a sso credentials" + (metrics << credentials.metrics).flatten! + elsif credentials.is_a? Aws::AssumeRoleCredentials + puts "Is a assume role credentials" + elsif credentials.is_a? Aws::SharedCredentials + puts "Is a shared credentials" + (metrics << credentials.metrics).flatten! + elsif credentials.is_a? Aws::ProcessCredentials + puts "Is a process credentials" + (metrics << credentials.metrics).flatten! + elsif credentials.is_a? Aws::ECSCredentials + puts "Is a ecs credentials" + (metrics << credentials.metrics).flatten! + elsif credentials.is_a? Aws::InstanceProfileCredentials + puts "Is a instance profile credentials" + (metrics << credentials.metrics).flatten! + end end + puts "Sending these new metrics" + puts metrics + Aws::Plugins::UserAgent.metric(*metrics, &block) end def v2_signing?(config) diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/plugins/user_agent.rb b/gems/aws-sdk-core/lib/aws-sdk-core/plugins/user_agent.rb index 3d23c9aeed2..8cf0064b732 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/plugins/user_agent.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/plugins/user_agent.rb @@ -89,8 +89,20 @@ def self.feature(_feature, &block) end def self.metric(*metrics, &block) + puts "In metric call" + pp metrics + puts METRICS[metrics[0]] Thread.current[:aws_sdk_core_user_agent_metric] ||= [] - metrics = metrics.map { |metric| METRICS[metric] }.compact + puts METRICS["CREDENTIALS_PROCESS"] + metrics = metrics.map do |metric| + puts "In metric loop" + puts metric + puts METRICS[metric] + METRICS[metric] + end + metrics = metrics.compact + puts "Metric" + puts metrics Thread.current[:aws_sdk_core_user_agent_metric].concat(metrics) puts "METRICS HERE" pp Thread.current[:aws_sdk_core_user_agent_metric] @@ -133,8 +145,6 @@ def to_s ua += " #{framework_m}" end if (metric_m = metric_metadata) - puts "Yes metric metadata" - puts caller ua += " #{metric_m}" end if @context.config.user_agent_suffix diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/process_credentials.rb b/gems/aws-sdk-core/lib/aws-sdk-core/process_credentials.rb index 5f2c27fece6..fefe6c51791 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/process_credentials.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/process_credentials.rb @@ -33,14 +33,19 @@ def initialize(process) warn('Passing a single string to Aws::ProcessCredentials.new '\ 'is insecure, please use use an array of system arguments instead') end + puts "Process is " + pp process # TODO: CREDENTIALS_PROFILE_PROCESS (v) @process = process @credentials = credentials_from_process @async_refresh = false + @metrics = nil super end + attr_accessor :metrics + private def credentials_from_process diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/shared_config.rb b/gems/aws-sdk-core/lib/aws-sdk-core/shared_config.rb index 3cf7a143eeb..96f4e085b0c 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/shared_config.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/shared_config.rb @@ -136,7 +136,8 @@ def assume_role_web_identity_credentials_from_config(opts = {}) cfg = { role_arn: entry['role_arn'], web_identity_token_file: entry['web_identity_token_file'], - role_session_name: entry['role_session_name'] + role_session_name: entry['role_session_name'], + metrics: ['CREDENTIALS_PROFILE_STS_WEB_ID_TOKEN'] } cfg[:region] = opts[:region] if opts[:region] AssumeRoleWebIdentityCredentials.new(cfg) @@ -400,7 +401,8 @@ def sso_credentials_from_profile(cfg, profile) sso_role_name: prof_config['sso_role_name'], sso_session: prof_config['sso_session'], sso_region: sso_region, - sso_start_url: sso_start_url + sso_start_url: sso_start_url, + metrics: prof_config['sso_session'].nil? ? ['CREDENTIALS_PROFILE_SSO_LEGACY'] : ['CREDENTIALS_PROFILE_SSO'] ) end end diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/shared_credentials.rb b/gems/aws-sdk-core/lib/aws-sdk-core/shared_credentials.rb index 9508080f19f..a62b9d87e76 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/shared_credentials.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/shared_credentials.rb @@ -40,6 +40,7 @@ def initialize(options = {}) ) @credentials = config.credentials(profile: @profile_name) end + @metrics = options[:metrics] end # @return [String] @@ -51,6 +52,8 @@ def initialize(options = {}) # @return [Credentials] attr_reader :credentials + attr_reader :metrics + # @api private def inspect parts = [ diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/sso_credentials.rb b/gems/aws-sdk-core/lib/aws-sdk-core/sso_credentials.rb index 739d2da84f1..17afbb424cb 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/sso_credentials.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/sso_credentials.rb @@ -118,7 +118,9 @@ def initialize(options = {}) end @async_refresh = true + @metrics = options[:metrics] super + @legacy ? @metrics << 'CREDENTIALS_SSO_LEGACY' : @metrics << 'CREDENTIALS_SSO' if @metrics end # @return [SSO::Client] From 14db8f937f554da7da4220755df8d952442945a4 Mon Sep 17 00:00:00 2001 From: Richard Wang Date: Fri, 21 Mar 2025 08:57:44 -0700 Subject: [PATCH 06/59] Delete metrics from opts once read --- .../lib/aws-sdk-core/assume_role_web_identity_credentials.rb | 2 +- gems/aws-sdk-core/lib/aws-sdk-core/credentials.rb | 2 +- gems/aws-sdk-core/lib/aws-sdk-core/ecs_credentials.rb | 2 +- .../lib/aws-sdk-core/instance_profile_credentials.rb | 2 +- gems/aws-sdk-core/lib/aws-sdk-core/shared_credentials.rb | 2 +- gems/aws-sdk-core/lib/aws-sdk-core/sso_credentials.rb | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_web_identity_credentials.rb b/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_web_identity_credentials.rb index 1c5c470f1af..7e6d34eab65 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_web_identity_credentials.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_web_identity_credentials.rb @@ -61,7 +61,7 @@ def initialize(options = {}) @assume_role_web_identity_params[:role_session_name] = _session_name end @client = client_opts[:client] || STS::Client.new(client_opts.merge(credentials: nil)) - @metrics = options[:metrics] + @metrics = options.delete(:metrics) super @metrics << 'CREDENTIALS_STS_ASSUME_ROLE_WEB_ID' if @metrics end diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/credentials.rb b/gems/aws-sdk-core/lib/aws-sdk-core/credentials.rb index 8961e8fd804..1238c36f8e6 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/credentials.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/credentials.rb @@ -14,7 +14,7 @@ def initialize(access_key_id, secret_access_key, session_token = nil, @secret_access_key = secret_access_key @session_token = session_token @account_id = kwargs[:account_id] - @metrics = kwargs[:metrics] + @metrics = kwargs.delete(:metrics) end # @return [String] diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/ecs_credentials.rb b/gems/aws-sdk-core/lib/aws-sdk-core/ecs_credentials.rb index 5bced7119fe..8d0824b1220 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/ecs_credentials.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/ecs_credentials.rb @@ -77,7 +77,7 @@ def initialize(options = {}) @http_debug_output = options[:http_debug_output] @backoff = backoff(options[:backoff]) @async_refresh = false - @metrics = options[:metrics] + @metrics = options.delete(:metrics) super end diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/instance_profile_credentials.rb b/gems/aws-sdk-core/lib/aws-sdk-core/instance_profile_credentials.rb index 373de3810b8..01f205fd491 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/instance_profile_credentials.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/instance_profile_credentials.rb @@ -90,7 +90,7 @@ def initialize(options = {}) @token = nil @no_refresh_until = nil @async_refresh = false - @metrics = options[:metrics] + @metrics = options.delete(:metrics) super end diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/shared_credentials.rb b/gems/aws-sdk-core/lib/aws-sdk-core/shared_credentials.rb index a62b9d87e76..f3d7693f79c 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/shared_credentials.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/shared_credentials.rb @@ -40,7 +40,7 @@ def initialize(options = {}) ) @credentials = config.credentials(profile: @profile_name) end - @metrics = options[:metrics] + @metrics = options.delete(:metrics) end # @return [String] diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/sso_credentials.rb b/gems/aws-sdk-core/lib/aws-sdk-core/sso_credentials.rb index 17afbb424cb..bde84f4ff56 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/sso_credentials.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/sso_credentials.rb @@ -118,7 +118,7 @@ def initialize(options = {}) end @async_refresh = true - @metrics = options[:metrics] + @metrics = options.delete(:metrics) super @legacy ? @metrics << 'CREDENTIALS_SSO_LEGACY' : @metrics << 'CREDENTIALS_SSO' if @metrics end From e9a5fe0108bac0e15235c37f5424c8ad577ff944 Mon Sep 17 00:00:00 2001 From: Richard Wang Date: Fri, 21 Mar 2025 09:39:42 -0700 Subject: [PATCH 07/59] Add assume role skeleton --- .../aws-sdk-core/assume_role_credentials.rb | 2 + .../assume_role_web_identity_credentials.rb | 4 +- .../lib/aws-sdk-core/credentials.rb | 1 - .../lib/aws-sdk-core/shared_config.rb | 52 +++++++++++++------ .../lib/aws-sdk-core/sso_credentials.rb | 4 +- 5 files changed, 41 insertions(+), 22 deletions(-) diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_credentials.rb b/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_credentials.rb index 183b35a6b80..c359c4beb6f 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_credentials.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_credentials.rb @@ -50,7 +50,9 @@ def initialize(options = {}) end @client = client_opts[:client] || STS::Client.new(client_opts) @async_refresh = true + @metrics = options.delete(:metrics) super + @metrics << 'CREDENTIALS_STS_ASSUME_ROLE' if @metrics end # @return [STS::Client] diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_web_identity_credentials.rb b/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_web_identity_credentials.rb index 7e6d34eab65..510ef207138 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_web_identity_credentials.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_web_identity_credentials.rb @@ -76,8 +76,8 @@ def refresh @assume_role_web_identity_params[:web_identity_token] = _token_from_file(@token_file) # TODO: CREDENTIALS_STS_ASSUME_ROLE_WEB_ID (k) - # Call will include "q" (from #assume_role_web_identity_credentials_from_config) - # OR call will include "h" (from #assume_role_web_identity_credentials) + # Call will include at least "q" (from #assume_role_web_identity_credentials_from_config) + # OR call will include at least "h" (from #assume_role_web_identity_credentials) resp = @client.assume_role_with_web_identity(@assume_role_web_identity_params) creds = resp.credentials @credentials = Credentials.new( diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/credentials.rb b/gems/aws-sdk-core/lib/aws-sdk-core/credentials.rb index 1238c36f8e6..ee3267929bb 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/credentials.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/credentials.rb @@ -29,7 +29,6 @@ def initialize(access_key_id, secret_access_key, session_token = nil, # @return [String, nil] attr_reader :account_id - # @return [String, nil] attr_reader :metrics # @return [Credentials] diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/shared_config.rb b/gems/aws-sdk-core/lib/aws-sdk-core/shared_config.rb index 96f4e085b0c..af57aa0719a 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/shared_config.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/shared_config.rb @@ -133,11 +133,18 @@ def assume_role_web_identity_credentials_from_config(opts = {}) entry = @parsed_config.fetch(p, {}) if entry['web_identity_token_file'] && entry['role_arn'] # TODO: CREDENTIALS_PROFILE_STS_WEB_ID_TOKEN (q) + + # Needed because of AssumeRole flow + if opts[:metrics] + opts[:metrics] << 'CREDENTIALS_PROFILE_STS_WEB_ID_TOKEN' + else + opts[:metrics] = ['CREDENTIALS_PROFILE_STS_WEB_ID_TOKEN'] + end cfg = { role_arn: entry['role_arn'], web_identity_token_file: entry['web_identity_token_file'], role_session_name: entry['role_session_name'], - metrics: ['CREDENTIALS_PROFILE_STS_WEB_ID_TOKEN'] + metrics: opts.delete(:metrics) } cfg[:region] = opts[:region] if opts[:region] AssumeRoleWebIdentityCredentials.new(cfg) @@ -150,9 +157,10 @@ def assume_role_web_identity_credentials_from_config(opts = {}) # file, if present. def sso_credentials_from_config(opts = {}) p = opts[:profile] || @profile_name - credentials = sso_credentials_from_profile(@parsed_credentials, p) + metrics = opts.delete(:metrics) + credentials = sso_credentials_from_profile(@parsed_credentials, p, metrics) if @parsed_config - credentials ||= sso_credentials_from_profile(@parsed_config, p) + credentials ||= sso_credentials_from_profile(@parsed_config, p, metrics) end credentials end @@ -258,7 +266,7 @@ def assume_role_from_profile(cfg, profile, opts, chain_config) elsif opts[:source_profile] # TODO: CREDENTIALS_PROFILE_SOURCE_PROFILE (o) opts[:visited_profiles] ||= Set.new - opts[:credentials] = resolve_source_profile(opts[:source_profile], opts) + opts[:credentials], metrics = resolve_source_profile(opts[:source_profile], opts) if opts[:credentials] opts[:role_session_name] ||= prof_cfg['role_session_name'] opts[:role_session_name] ||= 'default_session' @@ -267,6 +275,7 @@ def assume_role_from_profile(cfg, profile, opts, chain_config) opts[:external_id] ||= prof_cfg['external_id'] opts[:serial_number] ||= prof_cfg['mfa_serial'] opts[:profile] = opts.delete(:source_profile) + opts[:metrics] = metrics opts.delete(:visited_profiles) AssumeRoleCredentials.new(opts) else @@ -276,7 +285,7 @@ def assume_role_from_profile(cfg, profile, opts, chain_config) end elsif credential_source # TODO: CREDENTIALS_PROFILE_NAMED_PROVIDER (p) - opts[:credentials] = credentials_from_source( + opts[:credentials], metrics = credentials_from_source( credential_source, chain_config ) @@ -287,6 +296,7 @@ def assume_role_from_profile(cfg, profile, opts, chain_config) opts[:duration_seconds] ||= prof_cfg['duration_seconds'] opts[:external_id] ||= prof_cfg['external_id'] opts[:serial_number] ||= prof_cfg['mfa_serial'] + opts[:metrics] = metrics opts.delete(:source_profile) # Cleanup AssumeRoleCredentials.new(opts) else @@ -313,19 +323,19 @@ def resolve_source_profile(profile, opts = {}) if (creds = credentials(profile: profile)) # TODO: CREDENTIALS_PROFILE (n) - creds # static credentials + [creds, %w[CREDENTIALS_PROFILE_SOURCE_PROFILE CREDENTIALS_PROFILE]] # static credentials elsif profile_config && profile_config['source_profile'] opts.delete(:source_profile) assume_role_credentials_from_config(opts.merge(profile: profile)) - elsif (provider = assume_role_web_identity_credentials_from_config(opts.merge(profile: profile))) + elsif (provider = assume_role_web_identity_credentials_from_config(opts.merge(profile: profile, metrics: ['CREDENTIALS_PROFILE_SOURCE_PROFILE']))) # TODO: CREDENTIALS_PROFILE_STS_WEB_ID_TOKEN and CREDENTIALS_STS_ASSUME_ROLE_WEB_ID (qk) - provider.credentials if provider.credentials.set? + [provider.credentials, provider.metrics] if provider.credentials.set? elsif (provider = assume_role_process_credentials_from_config(profile)) # TODO: CREDENTIALS_PROFILE_PROCESS and CREDENTIALS_PROCESS (vw) - provider.credentials if provider.credentials.set? - elsif (provider = sso_credentials_from_config(profile: profile)) + [provider.credentials, %w[CREDENTIALS_PROFILE_SOURCE_PROFILE CREDENTIALS_PROFILE_PROCESS CREDENTIALS_PROCESS]] if provider.credentials.set? + elsif (provider = sso_credentials_from_config(profile: profile, metrics: ['CREDENTIALS_PROFILE_SOURCE_PROFILE'])) # TODO: CREDENTIALS_PROFILE_SSO and CREDENTIALS_SSO (rs) or CREDENTIALS_PROFILE_SSO_LEGACY and CREDENTIALS_SSO_LEGACY (tu) - provider.credentials if provider.credentials.set? + [provider.credentials, provider.metrics] if provider.credentials.set? end end @@ -333,14 +343,15 @@ def credentials_from_source(credential_source, config) case credential_source when 'Ec2InstanceMetadata' # TODO: CREDENTIALS_IMDS (0) - InstanceProfileCredentials.new( + [InstanceProfileCredentials.new( retries: config ? config.instance_profile_credentials_retries : 0, http_open_timeout: config ? config.instance_profile_credentials_timeout : 1, - http_read_timeout: config ? config.instance_profile_credentials_timeout : 1 - ) + http_read_timeout: config ? config.instance_profile_credentials_timeout : 1, + ), + %w[CREDENTIALS_PROFILE_NAMED_PROVIDER CREDENTIALS_IMDS]] when 'EcsContainer' # TODO: CREDENTIALS_HTTP (z) - ECSCredentials.new + [ECSCredentials.new, %w[CREDENTIALS_PROFILE_NAMED_PROVIDER CREDENTIALS_HTTP]] else raise Errors::InvalidCredentialSourceError, "Unsupported credential_source: #{credential_source}" end @@ -369,7 +380,7 @@ def credentials_from_config(profile, _opts) # If any of the sso_ profile values are present, attempt to construct # SSOCredentials - def sso_credentials_from_profile(cfg, profile) + def sso_credentials_from_profile(cfg, profile, metrics) if @parsed_config && (prof_config = cfg[profile]) && !(prof_config.keys & SSO_CREDENTIAL_PROFILE_KEYS).empty? @@ -396,13 +407,20 @@ def sso_credentials_from_profile(cfg, profile) sso_start_url = prof_config['sso_start_url'] end + # Needed for AssumeRole + if metrics + metrics << prof_config['sso_session'].nil? ? 'CREDENTIALS_PROFILE_SSO_LEGACY' : 'CREDENTIALS_PROFILE_SSO' + else + metrics = prof_config['sso_session'].nil? ? ['CREDENTIALS_PROFILE_SSO_LEGACY'] : ['CREDENTIALS_PROFILE_SSO'] + end + SSOCredentials.new( sso_account_id: prof_config['sso_account_id'], sso_role_name: prof_config['sso_role_name'], sso_session: prof_config['sso_session'], sso_region: sso_region, sso_start_url: sso_start_url, - metrics: prof_config['sso_session'].nil? ? ['CREDENTIALS_PROFILE_SSO_LEGACY'] : ['CREDENTIALS_PROFILE_SSO'] + metrics: metrics ) end end diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/sso_credentials.rb b/gems/aws-sdk-core/lib/aws-sdk-core/sso_credentials.rb index bde84f4ff56..d63f18a5591 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/sso_credentials.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/sso_credentials.rb @@ -147,7 +147,7 @@ def refresh c = if @legacy cached_token = read_cached_token # TODO: CREDENTIALS_SSO_LEGACY (u) - # Call will include "t" (from #initialize) + # Call will include at least "t" (from #initialize) @client.get_role_credentials( account_id: @sso_account_id, role_name: @sso_role_name, @@ -155,7 +155,7 @@ def refresh ).role_credentials else # TODO: CREDENTIALS_SSO (s) - # Call will include "r" (from #initialize) + # Call will include at least "r" (from #initialize) @client.get_role_credentials( account_id: @sso_account_id, role_name: @sso_role_name, From 04fe61ddd49e18746d3439138fdddcc88a5f6008 Mon Sep 17 00:00:00 2001 From: Richard Wang Date: Fri, 21 Mar 2025 12:13:18 -0700 Subject: [PATCH 08/59] Fix some test failures --- .../aws-sdk-core/assume_role_credentials.rb | 2 +- .../assume_role_web_identity_credentials.rb | 2 +- .../aws-sdk-core/credential_provider_chain.rb | 15 ----- .../lib/aws-sdk-core/credentials.rb | 2 +- .../lib/aws-sdk-core/ecs_credentials.rb | 2 +- .../instance_profile_credentials.rb | 2 +- .../lib/aws-sdk-core/plugins/sign.rb | 55 +++++-------------- .../lib/aws-sdk-core/plugins/user_agent.rb | 15 +---- .../lib/aws-sdk-core/process_credentials.rb | 4 +- .../lib/aws-sdk-core/shared_credentials.rb | 2 +- .../lib/aws-sdk-core/sso_credentials.rb | 2 +- .../lib/aws-sdk-securityhub/client.rb | 2 +- 12 files changed, 24 insertions(+), 81 deletions(-) diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_credentials.rb b/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_credentials.rb index c359c4beb6f..4e7dc7a60a3 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_credentials.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_credentials.rb @@ -39,6 +39,7 @@ class AssumeRoleCredentials # end # def initialize(options = {}) + @metrics = options.delete(:metrics) client_opts = {} @assume_role_params = {} options.each_pair do |key, value| @@ -50,7 +51,6 @@ def initialize(options = {}) end @client = client_opts[:client] || STS::Client.new(client_opts) @async_refresh = true - @metrics = options.delete(:metrics) super @metrics << 'CREDENTIALS_STS_ASSUME_ROLE' if @metrics end diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_web_identity_credentials.rb b/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_web_identity_credentials.rb index 510ef207138..aef00c16851 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_web_identity_credentials.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_web_identity_credentials.rb @@ -44,6 +44,7 @@ class AssumeRoleWebIdentityCredentials # with an instance of this object when # AWS credentials are required and need to be refreshed. def initialize(options = {}) + @metrics = options.delete(:metrics) client_opts = {} @assume_role_web_identity_params = {} @token_file = options.delete(:web_identity_token_file) @@ -61,7 +62,6 @@ def initialize(options = {}) @assume_role_web_identity_params[:role_session_name] = _session_name end @client = client_opts[:client] || STS::Client.new(client_opts.merge(credentials: nil)) - @metrics = options.delete(:metrics) super @metrics << 'CREDENTIALS_STS_ASSUME_ROLE_WEB_ID' if @metrics end diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/credential_provider_chain.rb b/gems/aws-sdk-core/lib/aws-sdk-core/credential_provider_chain.rb index b16d633bf63..0506daba741 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/credential_provider_chain.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/credential_provider_chain.rb @@ -112,7 +112,6 @@ def providers # TODO: CREDENTIALS_PROFILE (n)?? def static_credentials(options) - puts "!! STATIC_CREDENTIALS !!" if options[:config] Credentials.new( options[:config].access_key_id, @@ -125,7 +124,6 @@ def static_credentials(options) end def static_profile_assume_role_web_identity_credentials(options) - puts "!! STATIC_PROFILE_ASSUME_ROLE_WEB_IDENTITY_CREDENTIALS !!" if Aws.shared_config.config_enabled? && options[:config] && options[:config].profile Aws.shared_config.assume_role_web_identity_credentials_from_config( profile: options[:config].profile, @@ -135,7 +133,6 @@ def static_profile_assume_role_web_identity_credentials(options) end def static_profile_sso_credentials(options) - puts "!! STATIC_PROFILE_SSO_CREDENTIALS !!" if Aws.shared_config.config_enabled? && options[:config] && options[:config].profile Aws.shared_config.sso_credentials_from_config( profile: options[:config].profile @@ -144,14 +141,12 @@ def static_profile_sso_credentials(options) end def static_profile_assume_role_credentials(options) - puts "!! STATIC_PROFILE_ASSUME_ROLE_CREDENTIALS !!" if Aws.shared_config.config_enabled? && options[:config] && options[:config].profile assume_role_with_profile(options, options[:config].profile) end end def static_profile_credentials(options) - puts "!! STATIC_PROFILE_CREDENTIALS !!" if options[:config] && options[:config].profile SharedCredentials.new(profile_name: options[:config].profile, metrics: ['CREDENTIALS_PROFILE']) end @@ -160,7 +155,6 @@ def static_profile_credentials(options) end def static_profile_process_credentials(options) - puts "!! STATIC_PROFILE_PROCESS_CREDENTIALS !!" if Aws.shared_config.config_enabled? && options[:config] && options[:config].profile process_provider = Aws.shared_config.credential_process(profile: options[:config].profile) if process_provider @@ -176,7 +170,6 @@ def static_profile_process_credentials(options) # TODO: CREDENTIALS_ENV_VARS (g)?? def env_credentials(_options) - puts "!! ENV_CREDENTIALS !!" key = %w[AWS_ACCESS_KEY_ID AMAZON_ACCESS_KEY_ID AWS_ACCESS_KEY] secret = %w[AWS_SECRET_ACCESS_KEY AMAZON_SECRET_ACCESS_KEY AWS_SECRET_KEY] token = %w[AWS_SESSION_TOKEN AMAZON_SESSION_TOKEN] @@ -202,7 +195,6 @@ def determine_profile_name(options) end def shared_credentials(options) - puts "!! SHARED_CREDENTIALS !!" profile_name = determine_profile_name(options) SharedCredentials.new(profile_name: profile_name, metrics: ['CREDENTIALS_PROFILE']) rescue Errors::NoSuchProfileError @@ -210,12 +202,9 @@ def shared_credentials(options) end def process_credentials(options) - puts "!! PROCESS_CREDENTIALS !!" profile_name = determine_profile_name(options) - puts profile_name if Aws.shared_config.config_enabled? process_provider = Aws.shared_config.credential_process(profile: profile_name) - puts process_provider if process_provider credentials = ProcessCredentials.new([process_provider]) credentials.metrics = ['CREDENTIALS_PROFILE_PROCESS', 'CREDENTIALS_PROCESS'] @@ -227,7 +216,6 @@ def process_credentials(options) end def sso_credentials(options) - puts "!! SSO_CREDENTIALS !!" profile_name = determine_profile_name(options) if Aws.shared_config.config_enabled? Aws.shared_config.sso_credentials_from_config(profile: profile_name) @@ -237,14 +225,12 @@ def sso_credentials(options) end def assume_role_credentials(options) - puts "!! ASSUME_ROLE_CREDENTIALS !!" if Aws.shared_config.config_enabled? assume_role_with_profile(options, determine_profile_name(options)) end end def assume_role_web_identity_credentials(options) - puts "!! ASSUME_ROLE_WEB_IDENTITY_CREDENTIALS !!" region = options[:config].region if options[:config] if (role_arn = ENV['AWS_ROLE_ARN']) && (token_file = ENV['AWS_WEB_IDENTITY_TOKEN_FILE']) # TODO: CREDENTIALS_ENV_VARS_STS_WEB_ID_TOKEN (h) @@ -266,7 +252,6 @@ def assume_role_web_identity_credentials(options) end def instance_profile_credentials(options) - puts "!! INSTANCE_PROFILE_CREDENTIALS !!" profile_name = determine_profile_name(options) if ENV['AWS_CONTAINER_CREDENTIALS_RELATIVE_URI'] || ENV['AWS_CONTAINER_CREDENTIALS_FULL_URI'] diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/credentials.rb b/gems/aws-sdk-core/lib/aws-sdk-core/credentials.rb index ee3267929bb..23acaefab2c 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/credentials.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/credentials.rb @@ -10,11 +10,11 @@ class Credentials # @option kwargs [String] :credential_scope (nil) def initialize(access_key_id, secret_access_key, session_token = nil, **kwargs) + @metrics = kwargs.delete(:metrics) @access_key_id = access_key_id @secret_access_key = secret_access_key @session_token = session_token @account_id = kwargs[:account_id] - @metrics = kwargs.delete(:metrics) end # @return [String] diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/ecs_credentials.rb b/gems/aws-sdk-core/lib/aws-sdk-core/ecs_credentials.rb index 8d0824b1220..0829521e756 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/ecs_credentials.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/ecs_credentials.rb @@ -65,6 +65,7 @@ class InvalidTokenError < RuntimeError; end # with an instance of this object when # AWS credentials are required and need to be refreshed. def initialize(options = {}) + @metrics = options.delete(:metrics) credential_path = options[:credential_path] || ENV['AWS_CONTAINER_CREDENTIALS_RELATIVE_URI'] endpoint = options[:endpoint] || @@ -77,7 +78,6 @@ def initialize(options = {}) @http_debug_output = options[:http_debug_output] @backoff = backoff(options[:backoff]) @async_refresh = false - @metrics = options.delete(:metrics) super end diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/instance_profile_credentials.rb b/gems/aws-sdk-core/lib/aws-sdk-core/instance_profile_credentials.rb index 01f205fd491..befc4d9d27d 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/instance_profile_credentials.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/instance_profile_credentials.rb @@ -75,6 +75,7 @@ class TokenExpiredError < RuntimeError; end # with an instance of this object when # AWS credentials are required and need to be refreshed. def initialize(options = {}) + @metrics = options.delete(:metrics) @retries = options[:retries] || 1 endpoint_mode = resolve_endpoint_mode(options) @endpoint = resolve_endpoint(options, endpoint_mode) @@ -90,7 +91,6 @@ def initialize(options = {}) @token = nil @no_refresh_until = nil @async_refresh = false - @metrics = options.delete(:metrics) super end diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/plugins/sign.rb b/gems/aws-sdk-core/lib/aws-sdk-core/plugins/sign.rb index f6d2cba3c45..9705e97bd67 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/plugins/sign.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/plugins/sign.rb @@ -49,12 +49,12 @@ def call(context) context[:sigv4_region], context[:sigv4_credentials] ) - pp "SIGNER HERE" - pp signer - credentials = signer.signer.credentials_provider + # TODO: temp added this, double check + if signer.is_a?(SignatureV4) + credentials = signer.signer.credentials_provider + end signer.sign(context) end - puts "With metric now" with_metric(credentials) { @handler.call(context) } end @@ -62,39 +62,21 @@ def call(context) def with_metric(credentials, &block) puts "in with metric" + unless credentials && credentials.respond_to?(:metrics) + puts "No metrics" + return block.call + end + metrics = [] # Add check if flag isn't set, then emit Credentials CODE if !credentials.metrics - puts "Credentials from code" + puts "!!!!! Credentials from code !!!!!" metrics << 'CREDENTIALS_CODE' else - if credentials.is_a? Aws::Credentials - puts "Is a credentials" - (metrics << credentials.metrics).flatten! - elsif credentials.is_a? Aws::AssumeRoleWebIdentityCredentials - puts "Is a assume role credentials" - (metrics << credentials.metrics).flatten! - elsif credentials.is_a? Aws::SSOCredentials - puts "Is a sso credentials" - (metrics << credentials.metrics).flatten! - elsif credentials.is_a? Aws::AssumeRoleCredentials - puts "Is a assume role credentials" - elsif credentials.is_a? Aws::SharedCredentials - puts "Is a shared credentials" - (metrics << credentials.metrics).flatten! - elsif credentials.is_a? Aws::ProcessCredentials - puts "Is a process credentials" - (metrics << credentials.metrics).flatten! - elsif credentials.is_a? Aws::ECSCredentials - puts "Is a ecs credentials" - (metrics << credentials.metrics).flatten! - elsif credentials.is_a? Aws::InstanceProfileCredentials - puts "Is a instance profile credentials" - (metrics << credentials.metrics).flatten! - end + puts "!!!!! Credential type !!!!!" + puts credentials.class.name + (metrics << credentials.metrics).flatten! end - puts "Sending these new metrics" - puts metrics Aws::Plugins::UserAgent.metric(*metrics, &block) end @@ -192,17 +174,6 @@ def sign(context) context[:string_to_sign] = signature.string_to_sign end - # def with_metrics(&block) - # puts "Printing signer" - # pp @signer - # credentials = @signer.credentials_provider - # if credentials.is_a? Aws::Credentials - # Aws::Plugins::UserAgent.metric('CREDENTIALS_CODE', &block) - # else - # Aws::Plugins::UserAgent.metric('CREDENTIALS_HTTP', &block) - # end - # end - def presign_url(*args) @signer.presign_url(*args) end diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/plugins/user_agent.rb b/gems/aws-sdk-core/lib/aws-sdk-core/plugins/user_agent.rb index 8cf0064b732..b526e9eee5d 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/plugins/user_agent.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/plugins/user_agent.rb @@ -89,23 +89,12 @@ def self.feature(_feature, &block) end def self.metric(*metrics, &block) - puts "In metric call" - pp metrics - puts METRICS[metrics[0]] Thread.current[:aws_sdk_core_user_agent_metric] ||= [] - puts METRICS["CREDENTIALS_PROCESS"] metrics = metrics.map do |metric| - puts "In metric loop" - puts metric - puts METRICS[metric] METRICS[metric] end metrics = metrics.compact - puts "Metric" - puts metrics Thread.current[:aws_sdk_core_user_agent_metric].concat(metrics) - puts "METRICS HERE" - pp Thread.current[:aws_sdk_core_user_agent_metric] block.call ensure Thread.current[:aws_sdk_core_user_agent_metric].pop(metrics.size) @@ -228,8 +217,8 @@ def metric_metadata metrics = Thread.current[:aws_sdk_core_user_agent_metric].join(',') - puts "Metrics metadata" - pp metrics + # puts "Metrics metadata" + # pp metrics # Metric metadata is limited to 1024 bytes return "m/#{metrics}" if metrics.bytesize <= 1024 diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/process_credentials.rb b/gems/aws-sdk-core/lib/aws-sdk-core/process_credentials.rb index fefe6c51791..0163f66a7da 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/process_credentials.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/process_credentials.rb @@ -29,17 +29,15 @@ class ProcessCredentials # the process name and its arguments to execute, or a single string to be # executed by the shell (deprecated and insecure). def initialize(process) + @metrics = nil if process.is_a?(String) warn('Passing a single string to Aws::ProcessCredentials.new '\ 'is insecure, please use use an array of system arguments instead') end - puts "Process is " - pp process # TODO: CREDENTIALS_PROFILE_PROCESS (v) @process = process @credentials = credentials_from_process @async_refresh = false - @metrics = nil super end diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/shared_credentials.rb b/gems/aws-sdk-core/lib/aws-sdk-core/shared_credentials.rb index f3d7693f79c..a152d9cdfdb 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/shared_credentials.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/shared_credentials.rb @@ -25,6 +25,7 @@ class SharedCredentials # `ENV['AWS_PROFILE']`. # def initialize(options = {}) + @metrics = options.delete(:metrics) shared_config = Aws.shared_config @path = options[:path] @path ||= shared_config.credentials_path @@ -40,7 +41,6 @@ def initialize(options = {}) ) @credentials = config.credentials(profile: @profile_name) end - @metrics = options.delete(:metrics) end # @return [String] diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/sso_credentials.rb b/gems/aws-sdk-core/lib/aws-sdk-core/sso_credentials.rb index d63f18a5591..e14c7c8946e 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/sso_credentials.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/sso_credentials.rb @@ -67,6 +67,7 @@ class SSOCredentials # with an instance of this object when # AWS credentials are required and need to be refreshed. def initialize(options = {}) + @metrics = options.delete(:metrics) options = options.select {|k, v| !v.nil? } if (options[:sso_session]) puts "New SSO" @@ -118,7 +119,6 @@ def initialize(options = {}) end @async_refresh = true - @metrics = options.delete(:metrics) super @legacy ? @metrics << 'CREDENTIALS_SSO_LEGACY' : @metrics << 'CREDENTIALS_SSO' if @metrics end diff --git a/gems/aws-sdk-securityhub/lib/aws-sdk-securityhub/client.rb b/gems/aws-sdk-securityhub/lib/aws-sdk-securityhub/client.rb index 302cdd511af..52f45f53031 100644 --- a/gems/aws-sdk-securityhub/lib/aws-sdk-securityhub/client.rb +++ b/gems/aws-sdk-securityhub/lib/aws-sdk-securityhub/client.rb @@ -5278,7 +5278,7 @@ def get_configuration_policy(params = {}, options = {}) # resp.to_h outputs the following: # { # association_status: "FAILED", - # association_status_message: "Configuration Policy a1b2c3d4-5678-90ab-cdef-EXAMPLE11111 couldn\u2019t be applied to account 111122223333 in us-east-1 Region. Retry your request.", + # association_status_message: "Configuration Policy a1b2c3d4-5678-90ab-cdef-EXAMPLE11111 couldn’t be applied to account 111122223333 in us-east-1 Region. Retry your request.", # association_type: "INHERITED", # configuration_policy_id: "a1b2c3d4-5678-90ab-cdef-EXAMPLE11111", # target_id: "111122223333", From 374e46b11d22f142459437cdf3d16526bcab074a Mon Sep 17 00:00:00 2001 From: Richard Wang Date: Fri, 21 Mar 2025 12:42:30 -0700 Subject: [PATCH 09/59] Add attribute readers --- gems/aws-sdk-core/lib/aws-sdk-core/assume_role_credentials.rb | 2 ++ .../lib/aws-sdk-core/assume_role_web_identity_credentials.rb | 2 ++ gems/aws-sdk-core/lib/aws-sdk-core/plugins/sign.rb | 2 ++ gems/aws-sdk-core/lib/aws-sdk-core/sso_credentials.rb | 2 ++ 4 files changed, 8 insertions(+) diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_credentials.rb b/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_credentials.rb index 4e7dc7a60a3..b0bbc3fb4c4 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_credentials.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_credentials.rb @@ -61,6 +61,8 @@ def initialize(options = {}) # @return [Hash] attr_reader :assume_role_params + attr_reader :metrics + private def refresh diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_web_identity_credentials.rb b/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_web_identity_credentials.rb index aef00c16851..b8068e4ab3b 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_web_identity_credentials.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_web_identity_credentials.rb @@ -69,6 +69,8 @@ def initialize(options = {}) # @return [STS::Client] attr_reader :client + attr_reader :metrics + private def refresh diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/plugins/sign.rb b/gems/aws-sdk-core/lib/aws-sdk-core/plugins/sign.rb index 9705e97bd67..a9e74d6c76e 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/plugins/sign.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/plugins/sign.rb @@ -51,6 +51,8 @@ def call(context) ) # TODO: temp added this, double check if signer.is_a?(SignatureV4) + puts "Signer here" + pp signer credentials = signer.signer.credentials_provider end signer.sign(context) diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/sso_credentials.rb b/gems/aws-sdk-core/lib/aws-sdk-core/sso_credentials.rb index e14c7c8946e..900b2aef69f 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/sso_credentials.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/sso_credentials.rb @@ -126,6 +126,8 @@ def initialize(options = {}) # @return [SSO::Client] attr_reader :client + attr_reader :metrics + private def read_cached_token From 260ef005639e7d0d0f1a7bdf83dbd2c2d0fda0c2 Mon Sep 17 00:00:00 2001 From: Richard Wang Date: Fri, 21 Mar 2025 12:49:05 -0700 Subject: [PATCH 10/59] Revert built changes --- gems/aws-sdk-securityhub/lib/aws-sdk-securityhub/client.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gems/aws-sdk-securityhub/lib/aws-sdk-securityhub/client.rb b/gems/aws-sdk-securityhub/lib/aws-sdk-securityhub/client.rb index 52f45f53031..9183139aaef 100644 --- a/gems/aws-sdk-securityhub/lib/aws-sdk-securityhub/client.rb +++ b/gems/aws-sdk-securityhub/lib/aws-sdk-securityhub/client.rb @@ -5278,7 +5278,7 @@ def get_configuration_policy(params = {}, options = {}) # resp.to_h outputs the following: # { # association_status: "FAILED", - # association_status_message: "Configuration Policy a1b2c3d4-5678-90ab-cdef-EXAMPLE11111 couldn’t be applied to account 111122223333 in us-east-1 Region. Retry your request.", + # association_status_message: "Configuration Policy a1b2c3d4-5678-90ab-cdef-EXAMPLE11111 couldn\u2019t be applied to account 111122223333 in us-east-1 Region. Retry your request.", # association_type: "INHERITED", # configuration_policy_id: "a1b2c3d4-5678-90ab-cdef-EXAMPLE11111", # target_id: "111122223333", From 179901cc365c5cd5f00b3cb048549c54845177ce Mon Sep 17 00:00:00 2001 From: Richard Wang Date: Fri, 21 Mar 2025 12:54:04 -0700 Subject: [PATCH 11/59] Revert built changes --- .../lib/aws-sdk-securityhub/client.rb | 603 ++++++------------ 1 file changed, 187 insertions(+), 416 deletions(-) diff --git a/gems/aws-sdk-securityhub/lib/aws-sdk-securityhub/client.rb b/gems/aws-sdk-securityhub/lib/aws-sdk-securityhub/client.rb index 9183139aaef..12107419138 100644 --- a/gems/aws-sdk-securityhub/lib/aws-sdk-securityhub/client.rb +++ b/gems/aws-sdk-securityhub/lib/aws-sdk-securityhub/client.rb @@ -7,34 +7,34 @@ # # WARNING ABOUT GENERATED CODE -require 'seahorse/client/plugins/content_length' -require 'aws-sdk-core/plugins/credentials_configuration' -require 'aws-sdk-core/plugins/logging' -require 'aws-sdk-core/plugins/param_converter' -require 'aws-sdk-core/plugins/param_validator' -require 'aws-sdk-core/plugins/user_agent' -require 'aws-sdk-core/plugins/helpful_socket_errors' -require 'aws-sdk-core/plugins/retry_errors' -require 'aws-sdk-core/plugins/global_configuration' -require 'aws-sdk-core/plugins/regional_endpoint' -require 'aws-sdk-core/plugins/endpoint_discovery' -require 'aws-sdk-core/plugins/endpoint_pattern' -require 'aws-sdk-core/plugins/response_paging' -require 'aws-sdk-core/plugins/stub_responses' -require 'aws-sdk-core/plugins/idempotency_token' -require 'aws-sdk-core/plugins/invocation_id' -require 'aws-sdk-core/plugins/jsonvalue_converter' -require 'aws-sdk-core/plugins/client_metrics_plugin' -require 'aws-sdk-core/plugins/client_metrics_send_plugin' -require 'aws-sdk-core/plugins/transfer_encoding' -require 'aws-sdk-core/plugins/http_checksum' -require 'aws-sdk-core/plugins/checksum_algorithm' -require 'aws-sdk-core/plugins/request_compression' -require 'aws-sdk-core/plugins/defaults_mode' -require 'aws-sdk-core/plugins/recursion_detection' -require 'aws-sdk-core/plugins/telemetry' -require 'aws-sdk-core/plugins/sign' -require 'aws-sdk-core/plugins/protocols/rest_json' +require 'seahorse/client/plugins/content_length.rb' +require 'aws-sdk-core/plugins/credentials_configuration.rb' +require 'aws-sdk-core/plugins/logging.rb' +require 'aws-sdk-core/plugins/param_converter.rb' +require 'aws-sdk-core/plugins/param_validator.rb' +require 'aws-sdk-core/plugins/user_agent.rb' +require 'aws-sdk-core/plugins/helpful_socket_errors.rb' +require 'aws-sdk-core/plugins/retry_errors.rb' +require 'aws-sdk-core/plugins/global_configuration.rb' +require 'aws-sdk-core/plugins/regional_endpoint.rb' +require 'aws-sdk-core/plugins/endpoint_discovery.rb' +require 'aws-sdk-core/plugins/endpoint_pattern.rb' +require 'aws-sdk-core/plugins/response_paging.rb' +require 'aws-sdk-core/plugins/stub_responses.rb' +require 'aws-sdk-core/plugins/idempotency_token.rb' +require 'aws-sdk-core/plugins/jsonvalue_converter.rb' +require 'aws-sdk-core/plugins/client_metrics_plugin.rb' +require 'aws-sdk-core/plugins/client_metrics_send_plugin.rb' +require 'aws-sdk-core/plugins/transfer_encoding.rb' +require 'aws-sdk-core/plugins/http_checksum.rb' +require 'aws-sdk-core/plugins/checksum_algorithm.rb' +require 'aws-sdk-core/plugins/request_compression.rb' +require 'aws-sdk-core/plugins/defaults_mode.rb' +require 'aws-sdk-core/plugins/recursion_detection.rb' +require 'aws-sdk-core/plugins/sign.rb' +require 'aws-sdk-core/plugins/protocols/rest_json.rb' + +Aws::Plugins::GlobalConfiguration.add_identifier(:securityhub) module Aws::SecurityHub # An API client for SecurityHub. To construct a client, you need to configure a `:region` and `:credentials`. @@ -72,7 +72,6 @@ class Client < Seahorse::Client::Base add_plugin(Aws::Plugins::ResponsePaging) add_plugin(Aws::Plugins::StubResponses) add_plugin(Aws::Plugins::IdempotencyToken) - add_plugin(Aws::Plugins::InvocationId) add_plugin(Aws::Plugins::JsonvalueConverter) add_plugin(Aws::Plugins::ClientMetricsPlugin) add_plugin(Aws::Plugins::ClientMetricsSendPlugin) @@ -82,18 +81,12 @@ class Client < Seahorse::Client::Base add_plugin(Aws::Plugins::RequestCompression) add_plugin(Aws::Plugins::DefaultsMode) add_plugin(Aws::Plugins::RecursionDetection) - add_plugin(Aws::Plugins::Telemetry) add_plugin(Aws::Plugins::Sign) add_plugin(Aws::Plugins::Protocols::RestJson) add_plugin(Aws::SecurityHub::Plugins::Endpoints) # @overload initialize(options) # @param [Hash] options - # - # @option options [Array] :plugins ([]]) - # A list of plugins to apply to the client. Each plugin is either a - # class name or an instance of a plugin class. - # # @option options [required, Aws::CredentialProvider] :credentials # Your AWS credentials. This can be an instance of any one of the # following classes: @@ -128,15 +121,13 @@ class Client < Seahorse::Client::Base # locations will be searched for credentials: # # * `Aws.config[:credentials]` - # * The `:access_key_id`, `:secret_access_key`, `:session_token`, and - # `:account_id` options. - # * ENV['AWS_ACCESS_KEY_ID'], ENV['AWS_SECRET_ACCESS_KEY'], - # ENV['AWS_SESSION_TOKEN'], and ENV['AWS_ACCOUNT_ID'] + # * The `:access_key_id`, `:secret_access_key`, and `:session_token` options. + # * ENV['AWS_ACCESS_KEY_ID'], ENV['AWS_SECRET_ACCESS_KEY'] # * `~/.aws/credentials` # * `~/.aws/config` # * EC2/ECS IMDS instance profile - When used by default, the timeouts # are very aggressive. Construct and pass an instance of - # `Aws::InstanceProfileCredentials` or `Aws::ECSCredentials` to + # `Aws::InstanceProfileCredentails` or `Aws::ECSCredentials` to # enable retries and extended timeouts. Instance profile credential # fetching can be disabled by setting ENV['AWS_EC2_METADATA_DISABLED'] # to true. @@ -155,8 +146,6 @@ class Client < Seahorse::Client::Base # # @option options [String] :access_key_id # - # @option options [String] :account_id - # # @option options [Boolean] :active_endpoint_cache (false) # When set to `true`, a thread polling for endpoints will be running in # the background every 60 secs (default). Defaults to `false`. @@ -207,16 +196,10 @@ class Client < Seahorse::Client::Base # When set to 'true' the request body will not be compressed # for supported operations. # - # @option options [String, URI::HTTPS, URI::HTTP] :endpoint - # Normally you should not configure the `:endpoint` option - # directly. This is normally constructed from the `:region` - # option. Configuring `:endpoint` is normally reserved for - # connecting to test or custom endpoints. The endpoint should - # be a URI formatted like: - # - # 'http://example.com' - # 'https://example.com' - # 'http://example.com:123' + # @option options [String] :endpoint + # The client endpoint is normally constructed from the `:region` + # option. You should only configure an `:endpoint` when connecting + # to test or custom endpoints. This should be a valid HTTP(S) URI. # # @option options [Integer] :endpoint_cache_max_entries (1000) # Used for the maximum size limit of the LRU cache storing endpoints data @@ -257,34 +240,11 @@ class Client < Seahorse::Client::Base # Used when loading credentials from the shared credentials file # at HOME/.aws/credentials. When not specified, 'default' is used. # - # @option options [String] :request_checksum_calculation ("when_supported") - # Determines when a checksum will be calculated for request payloads. Values are: - # - # * `when_supported` - (default) When set, a checksum will be - # calculated for all request payloads of operations modeled with the - # `httpChecksum` trait where `requestChecksumRequired` is `true` and/or a - # `requestAlgorithmMember` is modeled. - # * `when_required` - When set, a checksum will only be calculated for - # request payloads of operations modeled with the `httpChecksum` trait where - # `requestChecksumRequired` is `true` or where a `requestAlgorithmMember` - # is modeled and supplied. - # # @option options [Integer] :request_min_compression_size_bytes (10240) # The minimum size in bytes that triggers compression for request # bodies. The value must be non-negative integer value between 0 # and 10485780 bytes inclusive. # - # @option options [String] :response_checksum_validation ("when_supported") - # Determines when checksum validation will be performed on response payloads. Values are: - # - # * `when_supported` - (default) When set, checksum validation is performed on all - # response payloads of operations modeled with the `httpChecksum` trait where - # `responseAlgorithms` is modeled, except when no modeled checksum algorithms - # are supported. - # * `when_required` - When set, checksum validation is not performed on - # response payloads of operations unless the checksum algorithm is supported and - # the `requestValidationModeMember` member is set to `ENABLED`. - # # @option options [Proc] :retry_backoff # A proc or lambda used for backoff. Defaults to 2**retries * retry_base_delay. # This option is only used in the `legacy` retry mode. @@ -329,25 +289,16 @@ class Client < Seahorse::Client::Base # throttling. This is a provisional mode that may change behavior # in the future. # + # # @option options [String] :sdk_ua_app_id # A unique and opaque application ID that is appended to the - # User-Agent header as app/sdk_ua_app_id. It should have a - # maximum length of 50. This variable is sourced from environment - # variable AWS_SDK_UA_APP_ID or the shared config profile attribute sdk_ua_app_id. + # User-Agent header as app/. It should have a + # maximum length of 50. # # @option options [String] :secret_access_key # # @option options [String] :session_token # - # @option options [Array] :sigv4a_signing_region_set - # A list of regions that should be signed with SigV4a signing. When - # not passed, a default `:sigv4a_signing_region_set` is searched for - # in the following locations: - # - # * `Aws.config[:sigv4a_signing_region_set]` - # * `ENV['AWS_SIGV4A_SIGNING_REGION_SET']` - # * `~/.aws/config` - # # @option options [Boolean] :stub_responses (false) # Causes the client to return stubbed responses. By default # fake responses are generated and returned. You can specify @@ -357,16 +308,6 @@ class Client < Seahorse::Client::Base # ** Please note ** When response stubbing is enabled, no HTTP # requests are made, and retries are disabled. # - # @option options [Aws::Telemetry::TelemetryProviderBase] :telemetry_provider (Aws::Telemetry::NoOpTelemetryProvider) - # Allows you to provide a telemetry provider, which is used to - # emit telemetry data. By default, uses `NoOpTelemetryProvider` which - # will not record or emit any telemetry data. The SDK supports the - # following telemetry providers: - # - # * OpenTelemetry (OTel) - To use the OTel provider, install and require the - # `opentelemetry-sdk` gem and then, pass in an instance of a - # `Aws::Telemetry::OTelProvider` for telemetry provider. - # # @option options [Aws::TokenProvider] :token_provider # A Bearer Token Provider. This can be an instance of any one of the # following classes: @@ -394,75 +335,52 @@ class Client < Seahorse::Client::Base # sending the request. # # @option options [Aws::SecurityHub::EndpointProvider] :endpoint_provider - # The endpoint provider used to resolve endpoints. Any object that responds to - # `#resolve_endpoint(parameters)` where `parameters` is a Struct similar to - # `Aws::SecurityHub::EndpointParameters`. - # - # @option options [Float] :http_continue_timeout (1) - # The number of seconds to wait for a 100-continue response before sending the - # request body. This option has no effect unless the request has "Expect" - # header set to "100-continue". Defaults to `nil` which disables this - # behaviour. This value can safely be set per request on the session. - # - # @option options [Float] :http_idle_timeout (5) - # The number of seconds a connection is allowed to sit idle before it - # is considered stale. Stale connections are closed and removed from the - # pool before making a request. - # - # @option options [Float] :http_open_timeout (15) - # The default number of seconds to wait for response data. - # This value can safely be set per-request on the session. - # - # @option options [URI::HTTP,String] :http_proxy - # A proxy to send requests through. Formatted like 'http://proxy.com:123'. - # - # @option options [Float] :http_read_timeout (60) - # The default number of seconds to wait for response data. - # This value can safely be set per-request on the session. - # - # @option options [Boolean] :http_wire_trace (false) - # When `true`, HTTP debug output will be sent to the `:logger`. - # - # @option options [Proc] :on_chunk_received - # When a Proc object is provided, it will be used as callback when each chunk - # of the response body is received. It provides three arguments: the chunk, - # the number of bytes received, and the total number of - # bytes in the response (or nil if the server did not send a `content-length`). - # - # @option options [Proc] :on_chunk_sent - # When a Proc object is provided, it will be used as callback when each chunk - # of the request body is sent. It provides three arguments: the chunk, - # the number of bytes read from the body, and the total number of - # bytes in the body. - # - # @option options [Boolean] :raise_response_errors (true) - # When `true`, response errors are raised. - # - # @option options [String] :ssl_ca_bundle - # Full path to the SSL certificate authority bundle file that should be used when - # verifying peer certificates. If you do not pass `:ssl_ca_bundle` or - # `:ssl_ca_directory` the the system default will be used if available. - # - # @option options [String] :ssl_ca_directory - # Full path of the directory that contains the unbundled SSL certificate - # authority files for verifying peer certificates. If you do - # not pass `:ssl_ca_bundle` or `:ssl_ca_directory` the the system - # default will be used if available. + # The endpoint provider used to resolve endpoints. Any object that responds to `#resolve_endpoint(parameters)` where `parameters` is a Struct similar to `Aws::SecurityHub::EndpointParameters` + # + # @option options [URI::HTTP,String] :http_proxy A proxy to send + # requests through. Formatted like 'http://proxy.com:123'. + # + # @option options [Float] :http_open_timeout (15) The number of + # seconds to wait when opening a HTTP session before raising a + # `Timeout::Error`. + # + # @option options [Float] :http_read_timeout (60) The default + # number of seconds to wait for response data. This value can + # safely be set per-request on the session. + # + # @option options [Float] :http_idle_timeout (5) The number of + # seconds a connection is allowed to sit idle before it is + # considered stale. Stale connections are closed and removed + # from the pool before making a request. # - # @option options [String] :ssl_ca_store - # Sets the X509::Store to verify peer certificate. + # @option options [Float] :http_continue_timeout (1) The number of + # seconds to wait for a 100-continue response before sending the + # request body. This option has no effect unless the request has + # "Expect" header set to "100-continue". Defaults to `nil` which + # disables this behaviour. This value can safely be set per + # request on the session. # - # @option options [OpenSSL::X509::Certificate] :ssl_cert - # Sets a client certificate when creating http connections. + # @option options [Float] :ssl_timeout (nil) Sets the SSL timeout + # in seconds. # - # @option options [OpenSSL::PKey] :ssl_key - # Sets a client key when creating http connections. + # @option options [Boolean] :http_wire_trace (false) When `true`, + # HTTP debug output will be sent to the `:logger`. # - # @option options [Float] :ssl_timeout - # Sets the SSL timeout in seconds + # @option options [Boolean] :ssl_verify_peer (true) When `true`, + # SSL peer certificates are verified when establishing a + # connection. # - # @option options [Boolean] :ssl_verify_peer (true) - # When `true`, SSL peer certificates are verified when establishing a connection. + # @option options [String] :ssl_ca_bundle Full path to the SSL + # certificate authority bundle file that should be used when + # verifying peer certificates. If you do not pass + # `:ssl_ca_bundle` or `:ssl_ca_directory` the the system default + # will be used if available. + # + # @option options [String] :ssl_ca_directory Full path of the + # directory that contains the unbundled SSL certificate + # authority files for verifying peer certificates. If you do + # not pass `:ssl_ca_bundle` or `:ssl_ca_directory` the the + # system default will be used if available. # def initialize(*args) super @@ -470,13 +388,6 @@ def initialize(*args) # @!group API Operations - # We recommend using Organizations instead of Security Hub invitations - # to manage your member accounts. For information, see [Managing - # Security Hub administrator and member accounts with Organizations][1] - # in the *Security Hub User Guide*. - # - # - # # Accepts the invitation to be a member account and be monitored by the # Security Hub administrator account that the invitation was sent from. # @@ -487,10 +398,6 @@ def initialize(*args) # to the administrator account to view findings generated in the member # account. # - # - # - # [1]: https://docs.aws.amazon.com/securityhub/latest/userguide/securityhub-accounts-orgs.html - # # @option params [required, String] :administrator_id # The account ID of the Security Hub administrator account that sent the # invitation. @@ -692,8 +599,7 @@ def batch_delete_automation_rules(params = {}, options = {}) # resp.standards_subscriptions[0].standards_input #=> Hash # resp.standards_subscriptions[0].standards_input["NonEmptyString"] #=> String # resp.standards_subscriptions[0].standards_status #=> String, one of "PENDING", "READY", "FAILED", "DELETING", "INCOMPLETE" - # resp.standards_subscriptions[0].standards_controls_updatable #=> String, one of "READY_FOR_UPDATES", "NOT_READY_FOR_UPDATES" - # resp.standards_subscriptions[0].standards_status_reason.status_reason_code #=> String, one of "NO_AVAILABLE_CONFIGURATION_RECORDER", "MAXIMUM_NUMBER_OF_CONFIG_RULES_EXCEEDED", "INTERNAL_ERROR" + # resp.standards_subscriptions[0].standards_status_reason.status_reason_code #=> String, one of "NO_AVAILABLE_CONFIGURATION_RECORDER", "INTERNAL_ERROR" # # @see http://docs.aws.amazon.com/goto/WebAPI/securityhub-2018-10-26/BatchDisableStandards AWS API Documentation # @@ -769,8 +675,7 @@ def batch_disable_standards(params = {}, options = {}) # resp.standards_subscriptions[0].standards_input #=> Hash # resp.standards_subscriptions[0].standards_input["NonEmptyString"] #=> String # resp.standards_subscriptions[0].standards_status #=> String, one of "PENDING", "READY", "FAILED", "DELETING", "INCOMPLETE" - # resp.standards_subscriptions[0].standards_controls_updatable #=> String, one of "READY_FOR_UPDATES", "NOT_READY_FOR_UPDATES" - # resp.standards_subscriptions[0].standards_status_reason.status_reason_code #=> String, one of "NO_AVAILABLE_CONFIGURATION_RECORDER", "MAXIMUM_NUMBER_OF_CONFIG_RULES_EXCEEDED", "INTERNAL_ERROR" + # resp.standards_subscriptions[0].standards_status_reason.status_reason_code #=> String, one of "NO_AVAILABLE_CONFIGURATION_RECORDER", "INTERNAL_ERROR" # # @see http://docs.aws.amazon.com/goto/WebAPI/securityhub-2018-10-26/BatchEnableStandards AWS API Documentation # @@ -1150,7 +1055,7 @@ def batch_get_automation_rules(params = {}, options = {}) # resp.configuration_policy_associations #=> Array # resp.configuration_policy_associations[0].configuration_policy_id #=> String # resp.configuration_policy_associations[0].target_id #=> String - # resp.configuration_policy_associations[0].target_type #=> String, one of "ACCOUNT", "ORGANIZATIONAL_UNIT", "ROOT" + # resp.configuration_policy_associations[0].target_type #=> String, one of "ACCOUNT", "ORGANIZATIONAL_UNIT" # resp.configuration_policy_associations[0].association_type #=> String, one of "INHERITED", "APPLIED" # resp.configuration_policy_associations[0].updated_at #=> Time # resp.configuration_policy_associations[0].association_status #=> String, one of "PENDING", "SUCCESS", "FAILED" @@ -1288,10 +1193,6 @@ def batch_get_security_controls(params = {}, options = {}) # For a batch of security controls and standards, identifies whether # each control is currently enabled or disabled in a standard. # - # Calls to this operation return a `RESOURCE_NOT_FOUND_EXCEPTION` error - # when the standard subscription for the association has a - # `NOT_READY_FOR_UPDATES` value for `StandardsControlsUpdatable`. - # # @option params [required, Array] :standards_control_association_ids # An array with one or more objects that includes a security control # (identified with `SecurityControlId`, `SecurityControlArn`, or a mix @@ -1895,7 +1796,7 @@ def batch_update_automation_rules(params = {}, options = {}) # account and their member accounts. Member accounts can update findings # for their account. # - # Updates from `BatchUpdateFindings` don't affect the value of + # Updates from `BatchUpdateFindings` do not affect the value of # `UpdatedAt` for a finding. # # Administrator and member accounts can use `BatchUpdateFindings` to @@ -2128,10 +2029,6 @@ def batch_update_findings(params = {}, options = {}) # Updates the enablement status of a security control in a specified # standard. # - # Calls to this operation return a `RESOURCE_NOT_FOUND_EXCEPTION` error - # when the standard subscription for the control has - # `StandardsControlsUpdatable` value `NOT_READY_FOR_UPDATES`. - # # @return [Types::BatchUpdateStandardsControlAssociationsResponse] Returns a {Seahorse::Client::Response response} object which responds to the following methods: # # * {Types::BatchUpdateStandardsControlAssociationsResponse#unprocessed_association_updates #unprocessed_association_updates} => Array<Types::UnprocessedStandardsControlAssociationUpdate> @@ -2702,8 +2599,7 @@ def create_automation_rule(params = {}, options = {}) # from the home Region. # # @option params [required, String] :name - # The name of the configuration policy. Alphanumeric characters and the - # following ASCII characters are permitted: `-, ., !, *, /`. + # The name of the configuration policy. # # @option params [String] :description # The description of the configuration policy. @@ -2892,16 +2788,11 @@ def create_configuration_policy(params = {}, options = {}) req.send_request(options) end - # The *aggregation Region* is now called the *home Region*. + # Used to enable finding aggregation. Must be called from the + # aggregation Region. # - # - # - # Used to enable cross-Region aggregation. This operation can be invoked - # from the home Region only. - # - # For information about how cross-Region aggregation works, see - # [Understanding cross-Region aggregation in Security Hub][1] in the - # *Security Hub User Guide*. + # For more details about cross-Region replication, see [Configuring + # finding aggregation][1] in the *Security Hub User Guide*. # # # @@ -2918,35 +2809,29 @@ def create_configuration_policy(params = {}, options = {}) # # The options are as follows: # - # * `ALL_REGIONS` - Aggregates findings from all of the Regions where - # Security Hub is enabled. When you choose this option, Security Hub - # also automatically aggregates findings from new Regions as Security - # Hub supports them and you opt into them. + # * `ALL_REGIONS` - Indicates to aggregate findings from all of the + # Regions where Security Hub is enabled. When you choose this option, + # Security Hub also automatically aggregates findings from new Regions + # as Security Hub supports them and you opt into them. # - # * `ALL_REGIONS_EXCEPT_SPECIFIED` - Aggregates findings from all of the - # Regions where Security Hub is enabled, except for the Regions listed - # in the `Regions` parameter. When you choose this option, Security - # Hub also automatically aggregates findings from new Regions as - # Security Hub supports them and you opt into them. + # * `ALL_REGIONS_EXCEPT_SPECIFIED` - Indicates to aggregate findings + # from all of the Regions where Security Hub is enabled, except for + # the Regions listed in the `Regions` parameter. When you choose this + # option, Security Hub also automatically aggregates findings from new + # Regions as Security Hub supports them and you opt into them. # - # * `SPECIFIED_REGIONS` - Aggregates findings only from the Regions - # listed in the `Regions` parameter. Security Hub does not + # * `SPECIFIED_REGIONS` - Indicates to aggregate findings only from the + # Regions listed in the `Regions` parameter. Security Hub does not # automatically aggregate findings from new Regions. # - # * `NO_REGIONS` - Aggregates no data because no Regions are selected as - # linked Regions. - # # @option params [Array] :regions # If `RegionLinkingMode` is `ALL_REGIONS_EXCEPT_SPECIFIED`, then this is - # a space-separated list of Regions that don't replicate and send - # findings to the home Region. + # a space-separated list of Regions that do not aggregate findings to + # the aggregation Region. # # If `RegionLinkingMode` is `SPECIFIED_REGIONS`, then this is a - # space-separated list of Regions that do replicate and send findings to - # the home Region. - # - # An `InvalidInputException` error results if you populate this field - # while `RegionLinkingMode` is `NO_REGIONS`. + # space-separated list of Regions that do aggregate findings to the + # aggregation Region. # # @return [Types::CreateFindingAggregatorResponse] Returns a {Seahorse::Client::Response response} object which responds to the following methods: # @@ -3801,7 +3686,7 @@ def create_insight(params = {}, options = {}) # owner accepts the invitation, the account becomes a member account in # Security Hub. # - # Accounts that are managed using Organizations don't receive an + # Accounts that are managed using Organizations do not receive an # invitation. They automatically become a member account in Security # Hub. # @@ -3881,25 +3766,13 @@ def create_members(params = {}, options = {}) req.send_request(options) end - # We recommend using Organizations instead of Security Hub invitations - # to manage your member accounts. For information, see [Managing - # Security Hub administrator and member accounts with Organizations][1] - # in the *Security Hub User Guide*. - # - # - # - # Declines invitations to become a Security Hub member account. + # Declines invitations to become a member account. # # A prospective member account uses this operation to decline an # invitation to become a member. # - # Only member accounts that aren't part of an Amazon Web Services - # organization should use this operation. Organization accounts don't - # receive invitations. - # - # - # - # [1]: https://docs.aws.amazon.com/securityhub/latest/userguide/securityhub-accounts-orgs.html + # This operation is only called by member accounts that aren't part of + # an organization. Organization accounts don't receive invitations. # # @option params [required, Array] :account_ids # The list of prospective member account IDs for which to decline an @@ -4033,18 +3906,13 @@ def delete_configuration_policy(params = {}, options = {}) req.send_request(options) end - # The *aggregation Region* is now called the *home Region*. - # - # - # # Deletes a finding aggregator. When you delete the finding aggregator, - # you stop cross-Region aggregation. Finding replication stops occurring - # from the linked Regions to the home Region. + # you stop finding aggregation. # - # When you stop cross-Region aggregation, findings that were already - # replicated and sent to the home Region are still visible from the home - # Region. However, new findings and finding updates are no longer - # replicated and sent to the home Region. + # When you stop finding aggregation, findings that were already + # aggregated to the aggregation Region are still visible from the + # aggregation Region. New findings and finding updates are not + # aggregated. # # @option params [required, String] :finding_aggregator_arn # The ARN of the finding aggregator to delete. To obtain the ARN, use @@ -4119,26 +3987,15 @@ def delete_insight(params = {}, options = {}) req.send_request(options) end - # We recommend using Organizations instead of Security Hub invitations - # to manage your member accounts. For information, see [Managing - # Security Hub administrator and member accounts with Organizations][1] - # in the *Security Hub User Guide*. - # - # - # - # Deletes invitations to become a Security Hub member account. + # Deletes invitations received by the Amazon Web Services account to + # become a member account. # # A Security Hub administrator account can use this operation to delete - # invitations sent to one or more prospective member accounts. + # invitations sent to one or more member accounts. # # This operation is only used to delete invitations that are sent to - # prospective member accounts that aren't part of an Amazon Web - # Services organization. Organization accounts don't receive - # invitations. - # - # - # - # [1]: https://docs.aws.amazon.com/securityhub/latest/userguide/securityhub-accounts-orgs.html + # member accounts that aren't part of an organization. Organization + # accounts don't receive invitations. # # @option params [required, Array] :account_ids # The list of member account IDs that received the invitations you want @@ -4422,7 +4279,7 @@ def describe_organization_configuration(params = {}, options = {}) # You can optionally provide an integration ARN. If you provide an # integration ARN, then the results only include that integration. # - # If you don't provide an integration ARN, then the results include all + # If you do not provide an integration ARN, then the results include all # of the available product integrations. # # @option params [String] :next_token @@ -4612,9 +4469,6 @@ def describe_standards(params = {}, options = {}) # currently enabled, the severity, and a link to remediation # information. # - # This operation returns an empty list for standard subscriptions where - # `StandardsControlsUpdatable` has value `NOT_READY_FOR_UPDATES`. - # # @option params [required, String] :standards_subscription_arn # The ARN of a resource that represents your subscription to a supported # standard. To get the subscription ARNs of the standards you have @@ -5032,7 +4886,7 @@ def enable_organization_admin_account(params = {}, options = {}) # # @option params [Boolean] :enable_default_standards # Whether to enable the security standards that Security Hub has - # designated as automatically enabled. If you don't provide a value for + # designated as automatically enabled. If you do not provide a value for # `EnableDefaultStandards`, it is set to `true`. To not enable the # automatically enabled standards, set `EnableDefaultStandards` to # `false`. @@ -5278,7 +5132,7 @@ def get_configuration_policy(params = {}, options = {}) # resp.to_h outputs the following: # { # association_status: "FAILED", - # association_status_message: "Configuration Policy a1b2c3d4-5678-90ab-cdef-EXAMPLE11111 couldn\u2019t be applied to account 111122223333 in us-east-1 Region. Retry your request.", + # association_status_message: "Configuration Policy a1b2c3d4-5678-90ab-cdef-EXAMPLE11111 couldn\u2019t be applied to account 111122223333 in us-east-1 Region. Retry your request.", # association_type: "INHERITED", # configuration_policy_id: "a1b2c3d4-5678-90ab-cdef-EXAMPLE11111", # target_id: "111122223333", @@ -5300,7 +5154,7 @@ def get_configuration_policy(params = {}, options = {}) # # resp.configuration_policy_id #=> String # resp.target_id #=> String - # resp.target_type #=> String, one of "ACCOUNT", "ORGANIZATIONAL_UNIT", "ROOT" + # resp.target_type #=> String, one of "ACCOUNT", "ORGANIZATIONAL_UNIT" # resp.association_type #=> String, one of "INHERITED", "APPLIED" # resp.updated_at #=> Time # resp.association_status #=> String, one of "PENDING", "SUCCESS", "FAILED" @@ -5380,8 +5234,7 @@ def get_configuration_policy_association(params = {}, options = {}) # resp.standards_subscriptions[0].standards_input #=> Hash # resp.standards_subscriptions[0].standards_input["NonEmptyString"] #=> String # resp.standards_subscriptions[0].standards_status #=> String, one of "PENDING", "READY", "FAILED", "DELETING", "INCOMPLETE" - # resp.standards_subscriptions[0].standards_controls_updatable #=> String, one of "READY_FOR_UPDATES", "NOT_READY_FOR_UPDATES" - # resp.standards_subscriptions[0].standards_status_reason.status_reason_code #=> String, one of "NO_AVAILABLE_CONFIGURATION_RECORDER", "MAXIMUM_NUMBER_OF_CONFIG_RULES_EXCEEDED", "INTERNAL_ERROR" + # resp.standards_subscriptions[0].standards_status_reason.status_reason_code #=> String, one of "NO_AVAILABLE_CONFIGURATION_RECORDER", "INTERNAL_ERROR" # resp.next_token #=> String # # @see http://docs.aws.amazon.com/goto/WebAPI/securityhub-2018-10-26/GetEnabledStandards AWS API Documentation @@ -5393,13 +5246,7 @@ def get_enabled_standards(params = {}, options = {}) req.send_request(options) end - # The *aggregation Region* is now called the *home Region*. - # - # - # - # Returns the current configuration in the calling account for - # cross-Region aggregation. A finding aggregator is a resource that - # establishes the home Region and any linked Regions. + # Returns the current finding aggregation configuration. # # @option params [required, String] :finding_aggregator_arn # The ARN of the finding aggregator to return details for. To obtain the @@ -5463,52 +5310,52 @@ def get_finding_aggregator(params = {}, options = {}) # Identifies which finding to get the finding history for. # # @option params [Time,DateTime,Date,Integer,String] :start_time - # A timestamp that indicates the start time of the requested finding - # history. + # An ISO 8601-formatted timestamp that indicates the start time of the + # requested finding history. A correctly formatted example is + # `2020-05-21T20:16:34.724Z`. The value cannot contain spaces, and date + # and time should be separated by `T`. For more information, see [RFC + # 3339 section 5.6, Internet Date/Time Format][1]. # # If you provide values for both `StartTime` and `EndTime`, Security Hub # returns finding history for the specified time period. If you provide # a value for `StartTime` but not for `EndTime`, Security Hub returns # finding history from the `StartTime` to the time at which the API is # called. If you provide a value for `EndTime` but not for `StartTime`, - # Security Hub returns finding history from the [CreatedAt][1] timestamp + # Security Hub returns finding history from the [CreatedAt][2] timestamp # of the finding to the `EndTime`. If you provide neither `StartTime` # nor `EndTime`, Security Hub returns finding history from the CreatedAt # timestamp of the finding to the time at which the API is called. In # all of these scenarios, the response is limited to 100 results, and # the maximum time period is limited to 90 days. # - # For more information about the validation and formatting of timestamp - # fields in Security Hub, see [Timestamps][2]. # # - # - # [1]: https://docs.aws.amazon.com/securityhub/1.0/APIReference/API_AwsSecurityFindingFilters.html#securityhub-Type-AwsSecurityFindingFilters-CreatedAt - # [2]: https://docs.aws.amazon.com/securityhub/1.0/APIReference/Welcome.html#timestamps + # [1]: https://www.rfc-editor.org/rfc/rfc3339#section-5.6 + # [2]: https://docs.aws.amazon.com/securityhub/1.0/APIReference/API_AwsSecurityFindingFilters.html#securityhub-Type-AwsSecurityFindingFilters-CreatedAt # # @option params [Time,DateTime,Date,Integer,String] :end_time # An ISO 8601-formatted timestamp that indicates the end time of the - # requested finding history. + # requested finding history. A correctly formatted example is + # `2020-05-21T20:16:34.724Z`. The value cannot contain spaces, and date + # and time should be separated by `T`. For more information, see [RFC + # 3339 section 5.6, Internet Date/Time Format][1]. # # If you provide values for both `StartTime` and `EndTime`, Security Hub # returns finding history for the specified time period. If you provide # a value for `StartTime` but not for `EndTime`, Security Hub returns # finding history from the `StartTime` to the time at which the API is # called. If you provide a value for `EndTime` but not for `StartTime`, - # Security Hub returns finding history from the [CreatedAt][1] timestamp + # Security Hub returns finding history from the [CreatedAt][2] timestamp # of the finding to the `EndTime`. If you provide neither `StartTime` # nor `EndTime`, Security Hub returns finding history from the CreatedAt # timestamp of the finding to the time at which the API is called. In # all of these scenarios, the response is limited to 100 results, and # the maximum time period is limited to 90 days. # - # For more information about the validation and formatting of timestamp - # fields in Security Hub, see [Timestamps][2]. - # # # - # [1]: https://docs.aws.amazon.com/securityhub/1.0/APIReference/API_AwsSecurityFindingFilters.html#securityhub-Type-AwsSecurityFindingFilters-CreatedAt - # [2]: https://docs.aws.amazon.com/securityhub/1.0/APIReference/Welcome.html#timestamps + # [1]: https://www.rfc-editor.org/rfc/rfc3339#section-5.6 + # [2]: https://docs.aws.amazon.com/securityhub/1.0/APIReference/API_AwsSecurityFindingFilters.html#securityhub-Type-AwsSecurityFindingFilters-CreatedAt # # @option params [String] :next_token # A token for pagination purposes. Provide `NULL` as the initial value. @@ -5609,9 +5456,9 @@ def get_finding_history(params = {}, options = {}) # Returns a list of findings that match the specified criteria. # - # If cross-Region aggregation is enabled, then when you call - # `GetFindings` from the home Region, the results include all of the - # matching findings from both the home Region and linked Regions. + # If finding aggregation is enabled, then when you call `GetFindings` + # from the aggregation Region, the results include all of the matching + # findings from both the aggregation Region and the linked Regions. # # @option params [Types::AwsSecurityFindingFilters] :filters # The finding attributes used to define a condition to filter the @@ -6535,7 +6382,7 @@ def get_insight_results(params = {}, options = {}) # Lists and describes insights for the specified insight ARNs. # # @option params [Array] :insight_arns - # The ARNs of the insights to describe. If you don't provide any + # The ARNs of the insights to describe. If you do not provide any # insight ARNs, then `GetInsights` returns all of your custom insights. # It does not return any managed insights. # @@ -6978,21 +6825,10 @@ def get_insights(params = {}, options = {}) req.send_request(options) end - # We recommend using Organizations instead of Security Hub invitations - # to manage your member accounts. For information, see [Managing - # Security Hub administrator and member accounts with Organizations][1] - # in the *Security Hub User Guide*. - # - # - # # Returns the count of all Security Hub membership invitations that were - # sent to the calling member account, not including the currently + # sent to the current member account, not including the currently # accepted invitation. # - # - # - # [1]: https://docs.aws.amazon.com/securityhub/latest/userguide/securityhub-accounts-orgs.html - # # @return [Types::GetInvitationsCountResponse] Returns a {Seahorse::Client::Response response} object which responds to the following methods: # # * {Types::GetInvitationsCountResponse#invitations_count #invitations_count} => Integer @@ -7246,20 +7082,12 @@ def get_security_control_definition(params = {}, options = {}) req.send_request(options) end - # We recommend using Organizations instead of Security Hub invitations - # to manage your member accounts. For information, see [Managing - # Security Hub administrator and member accounts with Organizations][1] - # in the *Security Hub User Guide*. - # - # - # # Invites other Amazon Web Services accounts to become member accounts # for the Security Hub administrator account that the invitation is sent # from. # - # This operation is only used to invite accounts that don't belong to - # an Amazon Web Services organization. Organization accounts don't - # receive invitations. + # This operation is only used to invite accounts that do not belong to + # an organization. Organization accounts do not receive invitations. # # Before you can use this action to invite a member, you must first use # the `CreateMembers` action to create the member account in Security @@ -7267,11 +7095,7 @@ def get_security_control_definition(params = {}, options = {}) # # When the account owner enables Security Hub and accepts the invitation # to become a member account, the administrator account can view the - # findings generated in the member account. - # - # - # - # [1]: https://docs.aws.amazon.com/securityhub/latest/userguide/securityhub-accounts-orgs.html + # findings generated from the member account. # # @option params [required, Array] :account_ids # The list of account IDs of the Amazon Web Services accounts to invite @@ -7569,7 +7393,7 @@ def list_configuration_policies(params = {}, options = {}) # resp.configuration_policy_association_summaries #=> Array # resp.configuration_policy_association_summaries[0].configuration_policy_id #=> String # resp.configuration_policy_association_summaries[0].target_id #=> String - # resp.configuration_policy_association_summaries[0].target_type #=> String, one of "ACCOUNT", "ORGANIZATIONAL_UNIT", "ROOT" + # resp.configuration_policy_association_summaries[0].target_type #=> String, one of "ACCOUNT", "ORGANIZATIONAL_UNIT" # resp.configuration_policy_association_summaries[0].association_type #=> String, one of "INHERITED", "APPLIED" # resp.configuration_policy_association_summaries[0].updated_at #=> Time # resp.configuration_policy_association_summaries[0].association_status #=> String, one of "PENDING", "SUCCESS", "FAILED" @@ -7646,9 +7470,9 @@ def list_enabled_products_for_import(params = {}, options = {}) req.send_request(options) end - # If cross-Region aggregation is enabled, then `ListFindingAggregators` - # returns the Amazon Resource Name (ARN) of the finding aggregator. You - # can run this operation from any Amazon Web Services Region. + # If finding aggregation is enabled, then `ListFindingAggregators` + # returns the ARN of the finding aggregator. You can run this operation + # from any Region. # # @option params [String] :next_token # The token returned with the previous set of results. Identifies the @@ -7704,23 +7528,12 @@ def list_finding_aggregators(params = {}, options = {}) req.send_request(options) end - # We recommend using Organizations instead of Security Hub invitations - # to manage your member accounts. For information, see [Managing - # Security Hub administrator and member accounts with Organizations][1] - # in the *Security Hub User Guide*. - # - # - # # Lists all Security Hub membership invitations that were sent to the - # calling account. - # - # Only accounts that are managed by invitation can use this operation. - # Accounts that are managed using the integration with Organizations - # don't receive invitations. + # current Amazon Web Services account. # - # - # - # [1]: https://docs.aws.amazon.com/securityhub/latest/userguide/securityhub-accounts-orgs.html + # This operation is only used by accounts that are managed by + # invitation. Accounts that are managed using the integration with + # Organizations do not receive invitations. # # @option params [Integer] :max_results # The maximum number of items to return in the response. @@ -8083,10 +7896,6 @@ def list_security_control_definitions(params = {}, options = {}) # Specifies whether a control is currently enabled or disabled in each # enabled standard in the calling account. # - # This operation omits standards control associations for standard - # subscriptions where `StandardsControlsUpdatable` has value - # `NOT_READY_FOR_UPDATES`. - # # @option params [required, String] :security_control_id # The identifier of the control (identified with `SecurityControlId`, # `SecurityControlArn`, or a mix of both parameters) that you want to @@ -8241,9 +8050,8 @@ def list_tags_for_resource(params = {}, options = {}) # Region. # # @option params [required, String] :configuration_policy_identifier - # The Amazon Resource Name (ARN) of a configuration policy, the - # universally unique identifier (UUID) of a configuration policy, or a - # value of `SELF_MANAGED_SECURITY_HUB` for a self-managed configuration. + # The Amazon Resource Name (ARN) or universally unique identifier (UUID) + # of the configuration policy. # # @option params [required, Types::Target] :target # The identifier of the target account, organizational unit, or the root @@ -8298,7 +8106,7 @@ def list_tags_for_resource(params = {}, options = {}) # # resp.configuration_policy_id #=> String # resp.target_id #=> String - # resp.target_type #=> String, one of "ACCOUNT", "ORGANIZATIONAL_UNIT", "ROOT" + # resp.target_type #=> String, one of "ACCOUNT", "ORGANIZATIONAL_UNIT" # resp.association_type #=> String, one of "INHERITED", "APPLIED" # resp.updated_at #=> Time # resp.association_status #=> String, one of "PENDING", "SUCCESS", "FAILED" @@ -8327,9 +8135,8 @@ def start_configuration_policy_association(params = {}, options = {}) # to disassociate from the specified configuration. # # @option params [required, String] :configuration_policy_identifier - # The Amazon Resource Name (ARN) of a configuration policy, the - # universally unique identifier (UUID) of a configuration policy, or a - # value of `SELF_MANAGED_SECURITY_HUB` for a self-managed configuration. + # The Amazon Resource Name (ARN) or universally unique identifier (UUID) + # of the configuration policy. # # @return [Struct] Returns an empty {Seahorse::Client::Response response}. # @@ -8499,8 +8306,7 @@ def update_action_target(params = {}, options = {}) # of the configuration policy. # # @option params [String] :name - # The name of the configuration policy. Alphanumeric characters and the - # following ASCII characters are permitted: `-, ., !, *, /`. + # The name of the configuration policy. # # @option params [String] :description # The description of the configuration policy. @@ -8691,16 +8497,12 @@ def update_configuration_policy(params = {}, options = {}) req.send_request(options) end - # The *aggregation Region* is now called the *home Region*. - # - # + # Updates the finding aggregation configuration. Used to update the + # Region linking mode and the list of included or excluded Regions. You + # cannot use `UpdateFindingAggregator` to change the aggregation Region. # - # Updates cross-Region aggregation settings. You can use this operation - # to update the Region linking mode and the list of included or excluded - # Amazon Web Services Regions. However, you can't use this operation to - # change the home Region. - # - # You can invoke this operation from the current home Region only. + # You must run `UpdateFindingAggregator` from the current aggregation + # Region. # # @option params [required, String] :finding_aggregator_arn # The ARN of the finding aggregator. To obtain the ARN, use @@ -8717,35 +8519,29 @@ def update_configuration_policy(params = {}, options = {}) # # The options are as follows: # - # * `ALL_REGIONS` - Aggregates findings from all of the Regions where - # Security Hub is enabled. When you choose this option, Security Hub - # also automatically aggregates findings from new Regions as Security - # Hub supports them and you opt into them. + # * `ALL_REGIONS` - Indicates to aggregate findings from all of the + # Regions where Security Hub is enabled. When you choose this option, + # Security Hub also automatically aggregates findings from new Regions + # as Security Hub supports them and you opt into them. # - # * `ALL_REGIONS_EXCEPT_SPECIFIED` - Aggregates findings from all of the - # Regions where Security Hub is enabled, except for the Regions listed - # in the `Regions` parameter. When you choose this option, Security - # Hub also automatically aggregates findings from new Regions as - # Security Hub supports them and you opt into them. + # * `ALL_REGIONS_EXCEPT_SPECIFIED` - Indicates to aggregate findings + # from all of the Regions where Security Hub is enabled, except for + # the Regions listed in the `Regions` parameter. When you choose this + # option, Security Hub also automatically aggregates findings from new + # Regions as Security Hub supports them and you opt into them. # - # * `SPECIFIED_REGIONS` - Aggregates findings only from the Regions - # listed in the `Regions` parameter. Security Hub does not + # * `SPECIFIED_REGIONS` - Indicates to aggregate findings only from the + # Regions listed in the `Regions` parameter. Security Hub does not # automatically aggregate findings from new Regions. # - # * `NO_REGIONS` - Aggregates no data because no Regions are selected as - # linked Regions. - # # @option params [Array] :regions # If `RegionLinkingMode` is `ALL_REGIONS_EXCEPT_SPECIFIED`, then this is - # a space-separated list of Regions that don't replicate and send - # findings to the home Region. + # a space-separated list of Regions that do not aggregate findings to + # the aggregation Region. # # If `RegionLinkingMode` is `SPECIFIED_REGIONS`, then this is a - # space-separated list of Regions that do replicate and send findings to - # the home Region. - # - # An `InvalidInputException` error results if you populate this field - # while `RegionLinkingMode` is `NO_REGIONS`. + # space-separated list of Regions that do aggregate findings to the + # aggregation Region. # # @return [Types::UpdateFindingAggregatorResponse] Returns a {Seahorse::Client::Response response} object which responds to the following methods: # @@ -8806,18 +8602,12 @@ def update_finding_aggregator(params = {}, options = {}) req.send_request(options) end - # `UpdateFindings` is a deprecated operation. Instead of - # `UpdateFindings`, use the `BatchUpdateFindings` operation. - # - # The `UpdateFindings` operation updates the `Note` and `RecordState` of - # the Security Hub aggregated findings that the filter attributes - # specify. Any member account that can view the finding can also see the - # update to the finding. + # `UpdateFindings` is deprecated. Instead of `UpdateFindings`, use + # `BatchUpdateFindings`. # - # Finding updates made with `UpdateFindings` aren't persisted if the - # same finding is later updated by the finding provider through the - # `BatchImportFindings` operation. In addition, Security Hub doesn't - # record updates made with `UpdateFindings` in the finding history. + # Updates the `Note` and `RecordState` of the Security Hub-aggregated + # findings that the filter attributes specify. Any member account that + # can view the finding also sees the update to the finding. # # @option params [required, Types::AwsSecurityFindingFilters] :filters # A collection of attributes that specify which findings you want to @@ -10458,16 +10248,6 @@ def update_security_control(params = {}, options = {}) # automatically. To not automatically enable new controls, set this to # `false`. # - # When you automatically enable new controls, you can interact with the - # controls in the console and programmatically immediately after - # release. However, automatically enabled controls have a temporary - # default status of `DISABLED`. It can take up to several days for - # Security Hub to process the control release and designate the control - # as `ENABLED` in your account. During the processing period, you can - # manually enable or disable a control, and Security Hub will maintain - # that designation regardless of whether you have `AutoEnableControls` - # set to `true`. - # # @option params [String] :control_finding_generator # Updates whether the calling account has consolidated control findings # turned on. If the value for this field is set to `SECURITY_CONTROL`, @@ -10513,10 +10293,6 @@ def update_security_hub_configuration(params = {}, options = {}) # Used to control whether an individual security standard control is # enabled or disabled. # - # Calls to this operation return a `RESOURCE_NOT_FOUND_EXCEPTION` error - # when the standard subscription for the control has - # `StandardsControlsUpdatable` value `NOT_READY_FOR_UPDATES`. - # # @option params [required, String] :standards_control_arn # The ARN of the security standard control to enable or disable. # @@ -10563,19 +10339,14 @@ def update_standards_control(params = {}, options = {}) # @api private def build_request(operation_name, params = {}) handlers = @handlers.for(operation_name) - tracer = config.telemetry_provider.tracer_provider.tracer( - Aws::Telemetry.module_to_tracer_name('Aws::SecurityHub') - ) context = Seahorse::Client::RequestContext.new( operation_name: operation_name, operation: config.api.operation(operation_name), client: self, params: params, - config: config, - tracer: tracer - ) + config: config) context[:gem_name] = 'aws-sdk-securityhub' - context[:gem_version] = '1.130.0' + context[:gem_version] = '1.97.0' Seahorse::Client::Request.new(handlers, context) end From fc0528e228576ac249d5197f304adbe41e18163c Mon Sep 17 00:00:00 2001 From: Richard Wang Date: Fri, 21 Mar 2025 12:55:08 -0700 Subject: [PATCH 12/59] Revert built changes --- .../lib/aws-sdk-securityhub/client.rb | 601 ++++++++++++------ 1 file changed, 415 insertions(+), 186 deletions(-) diff --git a/gems/aws-sdk-securityhub/lib/aws-sdk-securityhub/client.rb b/gems/aws-sdk-securityhub/lib/aws-sdk-securityhub/client.rb index 12107419138..302cdd511af 100644 --- a/gems/aws-sdk-securityhub/lib/aws-sdk-securityhub/client.rb +++ b/gems/aws-sdk-securityhub/lib/aws-sdk-securityhub/client.rb @@ -7,34 +7,34 @@ # # WARNING ABOUT GENERATED CODE -require 'seahorse/client/plugins/content_length.rb' -require 'aws-sdk-core/plugins/credentials_configuration.rb' -require 'aws-sdk-core/plugins/logging.rb' -require 'aws-sdk-core/plugins/param_converter.rb' -require 'aws-sdk-core/plugins/param_validator.rb' -require 'aws-sdk-core/plugins/user_agent.rb' -require 'aws-sdk-core/plugins/helpful_socket_errors.rb' -require 'aws-sdk-core/plugins/retry_errors.rb' -require 'aws-sdk-core/plugins/global_configuration.rb' -require 'aws-sdk-core/plugins/regional_endpoint.rb' -require 'aws-sdk-core/plugins/endpoint_discovery.rb' -require 'aws-sdk-core/plugins/endpoint_pattern.rb' -require 'aws-sdk-core/plugins/response_paging.rb' -require 'aws-sdk-core/plugins/stub_responses.rb' -require 'aws-sdk-core/plugins/idempotency_token.rb' -require 'aws-sdk-core/plugins/jsonvalue_converter.rb' -require 'aws-sdk-core/plugins/client_metrics_plugin.rb' -require 'aws-sdk-core/plugins/client_metrics_send_plugin.rb' -require 'aws-sdk-core/plugins/transfer_encoding.rb' -require 'aws-sdk-core/plugins/http_checksum.rb' -require 'aws-sdk-core/plugins/checksum_algorithm.rb' -require 'aws-sdk-core/plugins/request_compression.rb' -require 'aws-sdk-core/plugins/defaults_mode.rb' -require 'aws-sdk-core/plugins/recursion_detection.rb' -require 'aws-sdk-core/plugins/sign.rb' -require 'aws-sdk-core/plugins/protocols/rest_json.rb' - -Aws::Plugins::GlobalConfiguration.add_identifier(:securityhub) +require 'seahorse/client/plugins/content_length' +require 'aws-sdk-core/plugins/credentials_configuration' +require 'aws-sdk-core/plugins/logging' +require 'aws-sdk-core/plugins/param_converter' +require 'aws-sdk-core/plugins/param_validator' +require 'aws-sdk-core/plugins/user_agent' +require 'aws-sdk-core/plugins/helpful_socket_errors' +require 'aws-sdk-core/plugins/retry_errors' +require 'aws-sdk-core/plugins/global_configuration' +require 'aws-sdk-core/plugins/regional_endpoint' +require 'aws-sdk-core/plugins/endpoint_discovery' +require 'aws-sdk-core/plugins/endpoint_pattern' +require 'aws-sdk-core/plugins/response_paging' +require 'aws-sdk-core/plugins/stub_responses' +require 'aws-sdk-core/plugins/idempotency_token' +require 'aws-sdk-core/plugins/invocation_id' +require 'aws-sdk-core/plugins/jsonvalue_converter' +require 'aws-sdk-core/plugins/client_metrics_plugin' +require 'aws-sdk-core/plugins/client_metrics_send_plugin' +require 'aws-sdk-core/plugins/transfer_encoding' +require 'aws-sdk-core/plugins/http_checksum' +require 'aws-sdk-core/plugins/checksum_algorithm' +require 'aws-sdk-core/plugins/request_compression' +require 'aws-sdk-core/plugins/defaults_mode' +require 'aws-sdk-core/plugins/recursion_detection' +require 'aws-sdk-core/plugins/telemetry' +require 'aws-sdk-core/plugins/sign' +require 'aws-sdk-core/plugins/protocols/rest_json' module Aws::SecurityHub # An API client for SecurityHub. To construct a client, you need to configure a `:region` and `:credentials`. @@ -72,6 +72,7 @@ class Client < Seahorse::Client::Base add_plugin(Aws::Plugins::ResponsePaging) add_plugin(Aws::Plugins::StubResponses) add_plugin(Aws::Plugins::IdempotencyToken) + add_plugin(Aws::Plugins::InvocationId) add_plugin(Aws::Plugins::JsonvalueConverter) add_plugin(Aws::Plugins::ClientMetricsPlugin) add_plugin(Aws::Plugins::ClientMetricsSendPlugin) @@ -81,12 +82,18 @@ class Client < Seahorse::Client::Base add_plugin(Aws::Plugins::RequestCompression) add_plugin(Aws::Plugins::DefaultsMode) add_plugin(Aws::Plugins::RecursionDetection) + add_plugin(Aws::Plugins::Telemetry) add_plugin(Aws::Plugins::Sign) add_plugin(Aws::Plugins::Protocols::RestJson) add_plugin(Aws::SecurityHub::Plugins::Endpoints) # @overload initialize(options) # @param [Hash] options + # + # @option options [Array] :plugins ([]]) + # A list of plugins to apply to the client. Each plugin is either a + # class name or an instance of a plugin class. + # # @option options [required, Aws::CredentialProvider] :credentials # Your AWS credentials. This can be an instance of any one of the # following classes: @@ -121,13 +128,15 @@ class Client < Seahorse::Client::Base # locations will be searched for credentials: # # * `Aws.config[:credentials]` - # * The `:access_key_id`, `:secret_access_key`, and `:session_token` options. - # * ENV['AWS_ACCESS_KEY_ID'], ENV['AWS_SECRET_ACCESS_KEY'] + # * The `:access_key_id`, `:secret_access_key`, `:session_token`, and + # `:account_id` options. + # * ENV['AWS_ACCESS_KEY_ID'], ENV['AWS_SECRET_ACCESS_KEY'], + # ENV['AWS_SESSION_TOKEN'], and ENV['AWS_ACCOUNT_ID'] # * `~/.aws/credentials` # * `~/.aws/config` # * EC2/ECS IMDS instance profile - When used by default, the timeouts # are very aggressive. Construct and pass an instance of - # `Aws::InstanceProfileCredentails` or `Aws::ECSCredentials` to + # `Aws::InstanceProfileCredentials` or `Aws::ECSCredentials` to # enable retries and extended timeouts. Instance profile credential # fetching can be disabled by setting ENV['AWS_EC2_METADATA_DISABLED'] # to true. @@ -146,6 +155,8 @@ class Client < Seahorse::Client::Base # # @option options [String] :access_key_id # + # @option options [String] :account_id + # # @option options [Boolean] :active_endpoint_cache (false) # When set to `true`, a thread polling for endpoints will be running in # the background every 60 secs (default). Defaults to `false`. @@ -196,10 +207,16 @@ class Client < Seahorse::Client::Base # When set to 'true' the request body will not be compressed # for supported operations. # - # @option options [String] :endpoint - # The client endpoint is normally constructed from the `:region` - # option. You should only configure an `:endpoint` when connecting - # to test or custom endpoints. This should be a valid HTTP(S) URI. + # @option options [String, URI::HTTPS, URI::HTTP] :endpoint + # Normally you should not configure the `:endpoint` option + # directly. This is normally constructed from the `:region` + # option. Configuring `:endpoint` is normally reserved for + # connecting to test or custom endpoints. The endpoint should + # be a URI formatted like: + # + # 'http://example.com' + # 'https://example.com' + # 'http://example.com:123' # # @option options [Integer] :endpoint_cache_max_entries (1000) # Used for the maximum size limit of the LRU cache storing endpoints data @@ -240,11 +257,34 @@ class Client < Seahorse::Client::Base # Used when loading credentials from the shared credentials file # at HOME/.aws/credentials. When not specified, 'default' is used. # + # @option options [String] :request_checksum_calculation ("when_supported") + # Determines when a checksum will be calculated for request payloads. Values are: + # + # * `when_supported` - (default) When set, a checksum will be + # calculated for all request payloads of operations modeled with the + # `httpChecksum` trait where `requestChecksumRequired` is `true` and/or a + # `requestAlgorithmMember` is modeled. + # * `when_required` - When set, a checksum will only be calculated for + # request payloads of operations modeled with the `httpChecksum` trait where + # `requestChecksumRequired` is `true` or where a `requestAlgorithmMember` + # is modeled and supplied. + # # @option options [Integer] :request_min_compression_size_bytes (10240) # The minimum size in bytes that triggers compression for request # bodies. The value must be non-negative integer value between 0 # and 10485780 bytes inclusive. # + # @option options [String] :response_checksum_validation ("when_supported") + # Determines when checksum validation will be performed on response payloads. Values are: + # + # * `when_supported` - (default) When set, checksum validation is performed on all + # response payloads of operations modeled with the `httpChecksum` trait where + # `responseAlgorithms` is modeled, except when no modeled checksum algorithms + # are supported. + # * `when_required` - When set, checksum validation is not performed on + # response payloads of operations unless the checksum algorithm is supported and + # the `requestValidationModeMember` member is set to `ENABLED`. + # # @option options [Proc] :retry_backoff # A proc or lambda used for backoff. Defaults to 2**retries * retry_base_delay. # This option is only used in the `legacy` retry mode. @@ -289,16 +329,25 @@ class Client < Seahorse::Client::Base # throttling. This is a provisional mode that may change behavior # in the future. # - # # @option options [String] :sdk_ua_app_id # A unique and opaque application ID that is appended to the - # User-Agent header as app/. It should have a - # maximum length of 50. + # User-Agent header as app/sdk_ua_app_id. It should have a + # maximum length of 50. This variable is sourced from environment + # variable AWS_SDK_UA_APP_ID or the shared config profile attribute sdk_ua_app_id. # # @option options [String] :secret_access_key # # @option options [String] :session_token # + # @option options [Array] :sigv4a_signing_region_set + # A list of regions that should be signed with SigV4a signing. When + # not passed, a default `:sigv4a_signing_region_set` is searched for + # in the following locations: + # + # * `Aws.config[:sigv4a_signing_region_set]` + # * `ENV['AWS_SIGV4A_SIGNING_REGION_SET']` + # * `~/.aws/config` + # # @option options [Boolean] :stub_responses (false) # Causes the client to return stubbed responses. By default # fake responses are generated and returned. You can specify @@ -308,6 +357,16 @@ class Client < Seahorse::Client::Base # ** Please note ** When response stubbing is enabled, no HTTP # requests are made, and retries are disabled. # + # @option options [Aws::Telemetry::TelemetryProviderBase] :telemetry_provider (Aws::Telemetry::NoOpTelemetryProvider) + # Allows you to provide a telemetry provider, which is used to + # emit telemetry data. By default, uses `NoOpTelemetryProvider` which + # will not record or emit any telemetry data. The SDK supports the + # following telemetry providers: + # + # * OpenTelemetry (OTel) - To use the OTel provider, install and require the + # `opentelemetry-sdk` gem and then, pass in an instance of a + # `Aws::Telemetry::OTelProvider` for telemetry provider. + # # @option options [Aws::TokenProvider] :token_provider # A Bearer Token Provider. This can be an instance of any one of the # following classes: @@ -335,52 +394,75 @@ class Client < Seahorse::Client::Base # sending the request. # # @option options [Aws::SecurityHub::EndpointProvider] :endpoint_provider - # The endpoint provider used to resolve endpoints. Any object that responds to `#resolve_endpoint(parameters)` where `parameters` is a Struct similar to `Aws::SecurityHub::EndpointParameters` - # - # @option options [URI::HTTP,String] :http_proxy A proxy to send - # requests through. Formatted like 'http://proxy.com:123'. - # - # @option options [Float] :http_open_timeout (15) The number of - # seconds to wait when opening a HTTP session before raising a - # `Timeout::Error`. - # - # @option options [Float] :http_read_timeout (60) The default - # number of seconds to wait for response data. This value can - # safely be set per-request on the session. - # - # @option options [Float] :http_idle_timeout (5) The number of - # seconds a connection is allowed to sit idle before it is - # considered stale. Stale connections are closed and removed - # from the pool before making a request. - # - # @option options [Float] :http_continue_timeout (1) The number of - # seconds to wait for a 100-continue response before sending the - # request body. This option has no effect unless the request has - # "Expect" header set to "100-continue". Defaults to `nil` which - # disables this behaviour. This value can safely be set per - # request on the session. + # The endpoint provider used to resolve endpoints. Any object that responds to + # `#resolve_endpoint(parameters)` where `parameters` is a Struct similar to + # `Aws::SecurityHub::EndpointParameters`. + # + # @option options [Float] :http_continue_timeout (1) + # The number of seconds to wait for a 100-continue response before sending the + # request body. This option has no effect unless the request has "Expect" + # header set to "100-continue". Defaults to `nil` which disables this + # behaviour. This value can safely be set per request on the session. + # + # @option options [Float] :http_idle_timeout (5) + # The number of seconds a connection is allowed to sit idle before it + # is considered stale. Stale connections are closed and removed from the + # pool before making a request. + # + # @option options [Float] :http_open_timeout (15) + # The default number of seconds to wait for response data. + # This value can safely be set per-request on the session. + # + # @option options [URI::HTTP,String] :http_proxy + # A proxy to send requests through. Formatted like 'http://proxy.com:123'. + # + # @option options [Float] :http_read_timeout (60) + # The default number of seconds to wait for response data. + # This value can safely be set per-request on the session. + # + # @option options [Boolean] :http_wire_trace (false) + # When `true`, HTTP debug output will be sent to the `:logger`. + # + # @option options [Proc] :on_chunk_received + # When a Proc object is provided, it will be used as callback when each chunk + # of the response body is received. It provides three arguments: the chunk, + # the number of bytes received, and the total number of + # bytes in the response (or nil if the server did not send a `content-length`). + # + # @option options [Proc] :on_chunk_sent + # When a Proc object is provided, it will be used as callback when each chunk + # of the request body is sent. It provides three arguments: the chunk, + # the number of bytes read from the body, and the total number of + # bytes in the body. + # + # @option options [Boolean] :raise_response_errors (true) + # When `true`, response errors are raised. + # + # @option options [String] :ssl_ca_bundle + # Full path to the SSL certificate authority bundle file that should be used when + # verifying peer certificates. If you do not pass `:ssl_ca_bundle` or + # `:ssl_ca_directory` the the system default will be used if available. + # + # @option options [String] :ssl_ca_directory + # Full path of the directory that contains the unbundled SSL certificate + # authority files for verifying peer certificates. If you do + # not pass `:ssl_ca_bundle` or `:ssl_ca_directory` the the system + # default will be used if available. # - # @option options [Float] :ssl_timeout (nil) Sets the SSL timeout - # in seconds. + # @option options [String] :ssl_ca_store + # Sets the X509::Store to verify peer certificate. # - # @option options [Boolean] :http_wire_trace (false) When `true`, - # HTTP debug output will be sent to the `:logger`. + # @option options [OpenSSL::X509::Certificate] :ssl_cert + # Sets a client certificate when creating http connections. # - # @option options [Boolean] :ssl_verify_peer (true) When `true`, - # SSL peer certificates are verified when establishing a - # connection. + # @option options [OpenSSL::PKey] :ssl_key + # Sets a client key when creating http connections. # - # @option options [String] :ssl_ca_bundle Full path to the SSL - # certificate authority bundle file that should be used when - # verifying peer certificates. If you do not pass - # `:ssl_ca_bundle` or `:ssl_ca_directory` the the system default - # will be used if available. + # @option options [Float] :ssl_timeout + # Sets the SSL timeout in seconds # - # @option options [String] :ssl_ca_directory Full path of the - # directory that contains the unbundled SSL certificate - # authority files for verifying peer certificates. If you do - # not pass `:ssl_ca_bundle` or `:ssl_ca_directory` the the - # system default will be used if available. + # @option options [Boolean] :ssl_verify_peer (true) + # When `true`, SSL peer certificates are verified when establishing a connection. # def initialize(*args) super @@ -388,6 +470,13 @@ def initialize(*args) # @!group API Operations + # We recommend using Organizations instead of Security Hub invitations + # to manage your member accounts. For information, see [Managing + # Security Hub administrator and member accounts with Organizations][1] + # in the *Security Hub User Guide*. + # + # + # # Accepts the invitation to be a member account and be monitored by the # Security Hub administrator account that the invitation was sent from. # @@ -398,6 +487,10 @@ def initialize(*args) # to the administrator account to view findings generated in the member # account. # + # + # + # [1]: https://docs.aws.amazon.com/securityhub/latest/userguide/securityhub-accounts-orgs.html + # # @option params [required, String] :administrator_id # The account ID of the Security Hub administrator account that sent the # invitation. @@ -599,7 +692,8 @@ def batch_delete_automation_rules(params = {}, options = {}) # resp.standards_subscriptions[0].standards_input #=> Hash # resp.standards_subscriptions[0].standards_input["NonEmptyString"] #=> String # resp.standards_subscriptions[0].standards_status #=> String, one of "PENDING", "READY", "FAILED", "DELETING", "INCOMPLETE" - # resp.standards_subscriptions[0].standards_status_reason.status_reason_code #=> String, one of "NO_AVAILABLE_CONFIGURATION_RECORDER", "INTERNAL_ERROR" + # resp.standards_subscriptions[0].standards_controls_updatable #=> String, one of "READY_FOR_UPDATES", "NOT_READY_FOR_UPDATES" + # resp.standards_subscriptions[0].standards_status_reason.status_reason_code #=> String, one of "NO_AVAILABLE_CONFIGURATION_RECORDER", "MAXIMUM_NUMBER_OF_CONFIG_RULES_EXCEEDED", "INTERNAL_ERROR" # # @see http://docs.aws.amazon.com/goto/WebAPI/securityhub-2018-10-26/BatchDisableStandards AWS API Documentation # @@ -675,7 +769,8 @@ def batch_disable_standards(params = {}, options = {}) # resp.standards_subscriptions[0].standards_input #=> Hash # resp.standards_subscriptions[0].standards_input["NonEmptyString"] #=> String # resp.standards_subscriptions[0].standards_status #=> String, one of "PENDING", "READY", "FAILED", "DELETING", "INCOMPLETE" - # resp.standards_subscriptions[0].standards_status_reason.status_reason_code #=> String, one of "NO_AVAILABLE_CONFIGURATION_RECORDER", "INTERNAL_ERROR" + # resp.standards_subscriptions[0].standards_controls_updatable #=> String, one of "READY_FOR_UPDATES", "NOT_READY_FOR_UPDATES" + # resp.standards_subscriptions[0].standards_status_reason.status_reason_code #=> String, one of "NO_AVAILABLE_CONFIGURATION_RECORDER", "MAXIMUM_NUMBER_OF_CONFIG_RULES_EXCEEDED", "INTERNAL_ERROR" # # @see http://docs.aws.amazon.com/goto/WebAPI/securityhub-2018-10-26/BatchEnableStandards AWS API Documentation # @@ -1055,7 +1150,7 @@ def batch_get_automation_rules(params = {}, options = {}) # resp.configuration_policy_associations #=> Array # resp.configuration_policy_associations[0].configuration_policy_id #=> String # resp.configuration_policy_associations[0].target_id #=> String - # resp.configuration_policy_associations[0].target_type #=> String, one of "ACCOUNT", "ORGANIZATIONAL_UNIT" + # resp.configuration_policy_associations[0].target_type #=> String, one of "ACCOUNT", "ORGANIZATIONAL_UNIT", "ROOT" # resp.configuration_policy_associations[0].association_type #=> String, one of "INHERITED", "APPLIED" # resp.configuration_policy_associations[0].updated_at #=> Time # resp.configuration_policy_associations[0].association_status #=> String, one of "PENDING", "SUCCESS", "FAILED" @@ -1193,6 +1288,10 @@ def batch_get_security_controls(params = {}, options = {}) # For a batch of security controls and standards, identifies whether # each control is currently enabled or disabled in a standard. # + # Calls to this operation return a `RESOURCE_NOT_FOUND_EXCEPTION` error + # when the standard subscription for the association has a + # `NOT_READY_FOR_UPDATES` value for `StandardsControlsUpdatable`. + # # @option params [required, Array] :standards_control_association_ids # An array with one or more objects that includes a security control # (identified with `SecurityControlId`, `SecurityControlArn`, or a mix @@ -1796,7 +1895,7 @@ def batch_update_automation_rules(params = {}, options = {}) # account and their member accounts. Member accounts can update findings # for their account. # - # Updates from `BatchUpdateFindings` do not affect the value of + # Updates from `BatchUpdateFindings` don't affect the value of # `UpdatedAt` for a finding. # # Administrator and member accounts can use `BatchUpdateFindings` to @@ -2029,6 +2128,10 @@ def batch_update_findings(params = {}, options = {}) # Updates the enablement status of a security control in a specified # standard. # + # Calls to this operation return a `RESOURCE_NOT_FOUND_EXCEPTION` error + # when the standard subscription for the control has + # `StandardsControlsUpdatable` value `NOT_READY_FOR_UPDATES`. + # # @return [Types::BatchUpdateStandardsControlAssociationsResponse] Returns a {Seahorse::Client::Response response} object which responds to the following methods: # # * {Types::BatchUpdateStandardsControlAssociationsResponse#unprocessed_association_updates #unprocessed_association_updates} => Array<Types::UnprocessedStandardsControlAssociationUpdate> @@ -2599,7 +2702,8 @@ def create_automation_rule(params = {}, options = {}) # from the home Region. # # @option params [required, String] :name - # The name of the configuration policy. + # The name of the configuration policy. Alphanumeric characters and the + # following ASCII characters are permitted: `-, ., !, *, /`. # # @option params [String] :description # The description of the configuration policy. @@ -2788,11 +2892,16 @@ def create_configuration_policy(params = {}, options = {}) req.send_request(options) end - # Used to enable finding aggregation. Must be called from the - # aggregation Region. + # The *aggregation Region* is now called the *home Region*. # - # For more details about cross-Region replication, see [Configuring - # finding aggregation][1] in the *Security Hub User Guide*. + # + # + # Used to enable cross-Region aggregation. This operation can be invoked + # from the home Region only. + # + # For information about how cross-Region aggregation works, see + # [Understanding cross-Region aggregation in Security Hub][1] in the + # *Security Hub User Guide*. # # # @@ -2809,29 +2918,35 @@ def create_configuration_policy(params = {}, options = {}) # # The options are as follows: # - # * `ALL_REGIONS` - Indicates to aggregate findings from all of the - # Regions where Security Hub is enabled. When you choose this option, - # Security Hub also automatically aggregates findings from new Regions - # as Security Hub supports them and you opt into them. + # * `ALL_REGIONS` - Aggregates findings from all of the Regions where + # Security Hub is enabled. When you choose this option, Security Hub + # also automatically aggregates findings from new Regions as Security + # Hub supports them and you opt into them. # - # * `ALL_REGIONS_EXCEPT_SPECIFIED` - Indicates to aggregate findings - # from all of the Regions where Security Hub is enabled, except for - # the Regions listed in the `Regions` parameter. When you choose this - # option, Security Hub also automatically aggregates findings from new - # Regions as Security Hub supports them and you opt into them. + # * `ALL_REGIONS_EXCEPT_SPECIFIED` - Aggregates findings from all of the + # Regions where Security Hub is enabled, except for the Regions listed + # in the `Regions` parameter. When you choose this option, Security + # Hub also automatically aggregates findings from new Regions as + # Security Hub supports them and you opt into them. # - # * `SPECIFIED_REGIONS` - Indicates to aggregate findings only from the - # Regions listed in the `Regions` parameter. Security Hub does not + # * `SPECIFIED_REGIONS` - Aggregates findings only from the Regions + # listed in the `Regions` parameter. Security Hub does not # automatically aggregate findings from new Regions. # + # * `NO_REGIONS` - Aggregates no data because no Regions are selected as + # linked Regions. + # # @option params [Array] :regions # If `RegionLinkingMode` is `ALL_REGIONS_EXCEPT_SPECIFIED`, then this is - # a space-separated list of Regions that do not aggregate findings to - # the aggregation Region. + # a space-separated list of Regions that don't replicate and send + # findings to the home Region. # # If `RegionLinkingMode` is `SPECIFIED_REGIONS`, then this is a - # space-separated list of Regions that do aggregate findings to the - # aggregation Region. + # space-separated list of Regions that do replicate and send findings to + # the home Region. + # + # An `InvalidInputException` error results if you populate this field + # while `RegionLinkingMode` is `NO_REGIONS`. # # @return [Types::CreateFindingAggregatorResponse] Returns a {Seahorse::Client::Response response} object which responds to the following methods: # @@ -3686,7 +3801,7 @@ def create_insight(params = {}, options = {}) # owner accepts the invitation, the account becomes a member account in # Security Hub. # - # Accounts that are managed using Organizations do not receive an + # Accounts that are managed using Organizations don't receive an # invitation. They automatically become a member account in Security # Hub. # @@ -3766,13 +3881,25 @@ def create_members(params = {}, options = {}) req.send_request(options) end - # Declines invitations to become a member account. + # We recommend using Organizations instead of Security Hub invitations + # to manage your member accounts. For information, see [Managing + # Security Hub administrator and member accounts with Organizations][1] + # in the *Security Hub User Guide*. + # + # + # + # Declines invitations to become a Security Hub member account. # # A prospective member account uses this operation to decline an # invitation to become a member. # - # This operation is only called by member accounts that aren't part of - # an organization. Organization accounts don't receive invitations. + # Only member accounts that aren't part of an Amazon Web Services + # organization should use this operation. Organization accounts don't + # receive invitations. + # + # + # + # [1]: https://docs.aws.amazon.com/securityhub/latest/userguide/securityhub-accounts-orgs.html # # @option params [required, Array] :account_ids # The list of prospective member account IDs for which to decline an @@ -3906,13 +4033,18 @@ def delete_configuration_policy(params = {}, options = {}) req.send_request(options) end + # The *aggregation Region* is now called the *home Region*. + # + # + # # Deletes a finding aggregator. When you delete the finding aggregator, - # you stop finding aggregation. + # you stop cross-Region aggregation. Finding replication stops occurring + # from the linked Regions to the home Region. # - # When you stop finding aggregation, findings that were already - # aggregated to the aggregation Region are still visible from the - # aggregation Region. New findings and finding updates are not - # aggregated. + # When you stop cross-Region aggregation, findings that were already + # replicated and sent to the home Region are still visible from the home + # Region. However, new findings and finding updates are no longer + # replicated and sent to the home Region. # # @option params [required, String] :finding_aggregator_arn # The ARN of the finding aggregator to delete. To obtain the ARN, use @@ -3987,15 +4119,26 @@ def delete_insight(params = {}, options = {}) req.send_request(options) end - # Deletes invitations received by the Amazon Web Services account to - # become a member account. + # We recommend using Organizations instead of Security Hub invitations + # to manage your member accounts. For information, see [Managing + # Security Hub administrator and member accounts with Organizations][1] + # in the *Security Hub User Guide*. + # + # + # + # Deletes invitations to become a Security Hub member account. # # A Security Hub administrator account can use this operation to delete - # invitations sent to one or more member accounts. + # invitations sent to one or more prospective member accounts. # # This operation is only used to delete invitations that are sent to - # member accounts that aren't part of an organization. Organization - # accounts don't receive invitations. + # prospective member accounts that aren't part of an Amazon Web + # Services organization. Organization accounts don't receive + # invitations. + # + # + # + # [1]: https://docs.aws.amazon.com/securityhub/latest/userguide/securityhub-accounts-orgs.html # # @option params [required, Array] :account_ids # The list of member account IDs that received the invitations you want @@ -4279,7 +4422,7 @@ def describe_organization_configuration(params = {}, options = {}) # You can optionally provide an integration ARN. If you provide an # integration ARN, then the results only include that integration. # - # If you do not provide an integration ARN, then the results include all + # If you don't provide an integration ARN, then the results include all # of the available product integrations. # # @option params [String] :next_token @@ -4469,6 +4612,9 @@ def describe_standards(params = {}, options = {}) # currently enabled, the severity, and a link to remediation # information. # + # This operation returns an empty list for standard subscriptions where + # `StandardsControlsUpdatable` has value `NOT_READY_FOR_UPDATES`. + # # @option params [required, String] :standards_subscription_arn # The ARN of a resource that represents your subscription to a supported # standard. To get the subscription ARNs of the standards you have @@ -4886,7 +5032,7 @@ def enable_organization_admin_account(params = {}, options = {}) # # @option params [Boolean] :enable_default_standards # Whether to enable the security standards that Security Hub has - # designated as automatically enabled. If you do not provide a value for + # designated as automatically enabled. If you don't provide a value for # `EnableDefaultStandards`, it is set to `true`. To not enable the # automatically enabled standards, set `EnableDefaultStandards` to # `false`. @@ -5154,7 +5300,7 @@ def get_configuration_policy(params = {}, options = {}) # # resp.configuration_policy_id #=> String # resp.target_id #=> String - # resp.target_type #=> String, one of "ACCOUNT", "ORGANIZATIONAL_UNIT" + # resp.target_type #=> String, one of "ACCOUNT", "ORGANIZATIONAL_UNIT", "ROOT" # resp.association_type #=> String, one of "INHERITED", "APPLIED" # resp.updated_at #=> Time # resp.association_status #=> String, one of "PENDING", "SUCCESS", "FAILED" @@ -5234,7 +5380,8 @@ def get_configuration_policy_association(params = {}, options = {}) # resp.standards_subscriptions[0].standards_input #=> Hash # resp.standards_subscriptions[0].standards_input["NonEmptyString"] #=> String # resp.standards_subscriptions[0].standards_status #=> String, one of "PENDING", "READY", "FAILED", "DELETING", "INCOMPLETE" - # resp.standards_subscriptions[0].standards_status_reason.status_reason_code #=> String, one of "NO_AVAILABLE_CONFIGURATION_RECORDER", "INTERNAL_ERROR" + # resp.standards_subscriptions[0].standards_controls_updatable #=> String, one of "READY_FOR_UPDATES", "NOT_READY_FOR_UPDATES" + # resp.standards_subscriptions[0].standards_status_reason.status_reason_code #=> String, one of "NO_AVAILABLE_CONFIGURATION_RECORDER", "MAXIMUM_NUMBER_OF_CONFIG_RULES_EXCEEDED", "INTERNAL_ERROR" # resp.next_token #=> String # # @see http://docs.aws.amazon.com/goto/WebAPI/securityhub-2018-10-26/GetEnabledStandards AWS API Documentation @@ -5246,7 +5393,13 @@ def get_enabled_standards(params = {}, options = {}) req.send_request(options) end - # Returns the current finding aggregation configuration. + # The *aggregation Region* is now called the *home Region*. + # + # + # + # Returns the current configuration in the calling account for + # cross-Region aggregation. A finding aggregator is a resource that + # establishes the home Region and any linked Regions. # # @option params [required, String] :finding_aggregator_arn # The ARN of the finding aggregator to return details for. To obtain the @@ -5310,52 +5463,52 @@ def get_finding_aggregator(params = {}, options = {}) # Identifies which finding to get the finding history for. # # @option params [Time,DateTime,Date,Integer,String] :start_time - # An ISO 8601-formatted timestamp that indicates the start time of the - # requested finding history. A correctly formatted example is - # `2020-05-21T20:16:34.724Z`. The value cannot contain spaces, and date - # and time should be separated by `T`. For more information, see [RFC - # 3339 section 5.6, Internet Date/Time Format][1]. + # A timestamp that indicates the start time of the requested finding + # history. # # If you provide values for both `StartTime` and `EndTime`, Security Hub # returns finding history for the specified time period. If you provide # a value for `StartTime` but not for `EndTime`, Security Hub returns # finding history from the `StartTime` to the time at which the API is # called. If you provide a value for `EndTime` but not for `StartTime`, - # Security Hub returns finding history from the [CreatedAt][2] timestamp + # Security Hub returns finding history from the [CreatedAt][1] timestamp # of the finding to the `EndTime`. If you provide neither `StartTime` # nor `EndTime`, Security Hub returns finding history from the CreatedAt # timestamp of the finding to the time at which the API is called. In # all of these scenarios, the response is limited to 100 results, and # the maximum time period is limited to 90 days. # + # For more information about the validation and formatting of timestamp + # fields in Security Hub, see [Timestamps][2]. # # - # [1]: https://www.rfc-editor.org/rfc/rfc3339#section-5.6 - # [2]: https://docs.aws.amazon.com/securityhub/1.0/APIReference/API_AwsSecurityFindingFilters.html#securityhub-Type-AwsSecurityFindingFilters-CreatedAt + # + # [1]: https://docs.aws.amazon.com/securityhub/1.0/APIReference/API_AwsSecurityFindingFilters.html#securityhub-Type-AwsSecurityFindingFilters-CreatedAt + # [2]: https://docs.aws.amazon.com/securityhub/1.0/APIReference/Welcome.html#timestamps # # @option params [Time,DateTime,Date,Integer,String] :end_time # An ISO 8601-formatted timestamp that indicates the end time of the - # requested finding history. A correctly formatted example is - # `2020-05-21T20:16:34.724Z`. The value cannot contain spaces, and date - # and time should be separated by `T`. For more information, see [RFC - # 3339 section 5.6, Internet Date/Time Format][1]. + # requested finding history. # # If you provide values for both `StartTime` and `EndTime`, Security Hub # returns finding history for the specified time period. If you provide # a value for `StartTime` but not for `EndTime`, Security Hub returns # finding history from the `StartTime` to the time at which the API is # called. If you provide a value for `EndTime` but not for `StartTime`, - # Security Hub returns finding history from the [CreatedAt][2] timestamp + # Security Hub returns finding history from the [CreatedAt][1] timestamp # of the finding to the `EndTime`. If you provide neither `StartTime` # nor `EndTime`, Security Hub returns finding history from the CreatedAt # timestamp of the finding to the time at which the API is called. In # all of these scenarios, the response is limited to 100 results, and # the maximum time period is limited to 90 days. # + # For more information about the validation and formatting of timestamp + # fields in Security Hub, see [Timestamps][2]. + # # # - # [1]: https://www.rfc-editor.org/rfc/rfc3339#section-5.6 - # [2]: https://docs.aws.amazon.com/securityhub/1.0/APIReference/API_AwsSecurityFindingFilters.html#securityhub-Type-AwsSecurityFindingFilters-CreatedAt + # [1]: https://docs.aws.amazon.com/securityhub/1.0/APIReference/API_AwsSecurityFindingFilters.html#securityhub-Type-AwsSecurityFindingFilters-CreatedAt + # [2]: https://docs.aws.amazon.com/securityhub/1.0/APIReference/Welcome.html#timestamps # # @option params [String] :next_token # A token for pagination purposes. Provide `NULL` as the initial value. @@ -5456,9 +5609,9 @@ def get_finding_history(params = {}, options = {}) # Returns a list of findings that match the specified criteria. # - # If finding aggregation is enabled, then when you call `GetFindings` - # from the aggregation Region, the results include all of the matching - # findings from both the aggregation Region and the linked Regions. + # If cross-Region aggregation is enabled, then when you call + # `GetFindings` from the home Region, the results include all of the + # matching findings from both the home Region and linked Regions. # # @option params [Types::AwsSecurityFindingFilters] :filters # The finding attributes used to define a condition to filter the @@ -6382,7 +6535,7 @@ def get_insight_results(params = {}, options = {}) # Lists and describes insights for the specified insight ARNs. # # @option params [Array] :insight_arns - # The ARNs of the insights to describe. If you do not provide any + # The ARNs of the insights to describe. If you don't provide any # insight ARNs, then `GetInsights` returns all of your custom insights. # It does not return any managed insights. # @@ -6825,10 +6978,21 @@ def get_insights(params = {}, options = {}) req.send_request(options) end + # We recommend using Organizations instead of Security Hub invitations + # to manage your member accounts. For information, see [Managing + # Security Hub administrator and member accounts with Organizations][1] + # in the *Security Hub User Guide*. + # + # + # # Returns the count of all Security Hub membership invitations that were - # sent to the current member account, not including the currently + # sent to the calling member account, not including the currently # accepted invitation. # + # + # + # [1]: https://docs.aws.amazon.com/securityhub/latest/userguide/securityhub-accounts-orgs.html + # # @return [Types::GetInvitationsCountResponse] Returns a {Seahorse::Client::Response response} object which responds to the following methods: # # * {Types::GetInvitationsCountResponse#invitations_count #invitations_count} => Integer @@ -7082,12 +7246,20 @@ def get_security_control_definition(params = {}, options = {}) req.send_request(options) end + # We recommend using Organizations instead of Security Hub invitations + # to manage your member accounts. For information, see [Managing + # Security Hub administrator and member accounts with Organizations][1] + # in the *Security Hub User Guide*. + # + # + # # Invites other Amazon Web Services accounts to become member accounts # for the Security Hub administrator account that the invitation is sent # from. # - # This operation is only used to invite accounts that do not belong to - # an organization. Organization accounts do not receive invitations. + # This operation is only used to invite accounts that don't belong to + # an Amazon Web Services organization. Organization accounts don't + # receive invitations. # # Before you can use this action to invite a member, you must first use # the `CreateMembers` action to create the member account in Security @@ -7095,7 +7267,11 @@ def get_security_control_definition(params = {}, options = {}) # # When the account owner enables Security Hub and accepts the invitation # to become a member account, the administrator account can view the - # findings generated from the member account. + # findings generated in the member account. + # + # + # + # [1]: https://docs.aws.amazon.com/securityhub/latest/userguide/securityhub-accounts-orgs.html # # @option params [required, Array] :account_ids # The list of account IDs of the Amazon Web Services accounts to invite @@ -7393,7 +7569,7 @@ def list_configuration_policies(params = {}, options = {}) # resp.configuration_policy_association_summaries #=> Array # resp.configuration_policy_association_summaries[0].configuration_policy_id #=> String # resp.configuration_policy_association_summaries[0].target_id #=> String - # resp.configuration_policy_association_summaries[0].target_type #=> String, one of "ACCOUNT", "ORGANIZATIONAL_UNIT" + # resp.configuration_policy_association_summaries[0].target_type #=> String, one of "ACCOUNT", "ORGANIZATIONAL_UNIT", "ROOT" # resp.configuration_policy_association_summaries[0].association_type #=> String, one of "INHERITED", "APPLIED" # resp.configuration_policy_association_summaries[0].updated_at #=> Time # resp.configuration_policy_association_summaries[0].association_status #=> String, one of "PENDING", "SUCCESS", "FAILED" @@ -7470,9 +7646,9 @@ def list_enabled_products_for_import(params = {}, options = {}) req.send_request(options) end - # If finding aggregation is enabled, then `ListFindingAggregators` - # returns the ARN of the finding aggregator. You can run this operation - # from any Region. + # If cross-Region aggregation is enabled, then `ListFindingAggregators` + # returns the Amazon Resource Name (ARN) of the finding aggregator. You + # can run this operation from any Amazon Web Services Region. # # @option params [String] :next_token # The token returned with the previous set of results. Identifies the @@ -7528,12 +7704,23 @@ def list_finding_aggregators(params = {}, options = {}) req.send_request(options) end + # We recommend using Organizations instead of Security Hub invitations + # to manage your member accounts. For information, see [Managing + # Security Hub administrator and member accounts with Organizations][1] + # in the *Security Hub User Guide*. + # + # + # # Lists all Security Hub membership invitations that were sent to the - # current Amazon Web Services account. + # calling account. + # + # Only accounts that are managed by invitation can use this operation. + # Accounts that are managed using the integration with Organizations + # don't receive invitations. # - # This operation is only used by accounts that are managed by - # invitation. Accounts that are managed using the integration with - # Organizations do not receive invitations. + # + # + # [1]: https://docs.aws.amazon.com/securityhub/latest/userguide/securityhub-accounts-orgs.html # # @option params [Integer] :max_results # The maximum number of items to return in the response. @@ -7896,6 +8083,10 @@ def list_security_control_definitions(params = {}, options = {}) # Specifies whether a control is currently enabled or disabled in each # enabled standard in the calling account. # + # This operation omits standards control associations for standard + # subscriptions where `StandardsControlsUpdatable` has value + # `NOT_READY_FOR_UPDATES`. + # # @option params [required, String] :security_control_id # The identifier of the control (identified with `SecurityControlId`, # `SecurityControlArn`, or a mix of both parameters) that you want to @@ -8050,8 +8241,9 @@ def list_tags_for_resource(params = {}, options = {}) # Region. # # @option params [required, String] :configuration_policy_identifier - # The Amazon Resource Name (ARN) or universally unique identifier (UUID) - # of the configuration policy. + # The Amazon Resource Name (ARN) of a configuration policy, the + # universally unique identifier (UUID) of a configuration policy, or a + # value of `SELF_MANAGED_SECURITY_HUB` for a self-managed configuration. # # @option params [required, Types::Target] :target # The identifier of the target account, organizational unit, or the root @@ -8106,7 +8298,7 @@ def list_tags_for_resource(params = {}, options = {}) # # resp.configuration_policy_id #=> String # resp.target_id #=> String - # resp.target_type #=> String, one of "ACCOUNT", "ORGANIZATIONAL_UNIT" + # resp.target_type #=> String, one of "ACCOUNT", "ORGANIZATIONAL_UNIT", "ROOT" # resp.association_type #=> String, one of "INHERITED", "APPLIED" # resp.updated_at #=> Time # resp.association_status #=> String, one of "PENDING", "SUCCESS", "FAILED" @@ -8135,8 +8327,9 @@ def start_configuration_policy_association(params = {}, options = {}) # to disassociate from the specified configuration. # # @option params [required, String] :configuration_policy_identifier - # The Amazon Resource Name (ARN) or universally unique identifier (UUID) - # of the configuration policy. + # The Amazon Resource Name (ARN) of a configuration policy, the + # universally unique identifier (UUID) of a configuration policy, or a + # value of `SELF_MANAGED_SECURITY_HUB` for a self-managed configuration. # # @return [Struct] Returns an empty {Seahorse::Client::Response response}. # @@ -8306,7 +8499,8 @@ def update_action_target(params = {}, options = {}) # of the configuration policy. # # @option params [String] :name - # The name of the configuration policy. + # The name of the configuration policy. Alphanumeric characters and the + # following ASCII characters are permitted: `-, ., !, *, /`. # # @option params [String] :description # The description of the configuration policy. @@ -8497,12 +8691,16 @@ def update_configuration_policy(params = {}, options = {}) req.send_request(options) end - # Updates the finding aggregation configuration. Used to update the - # Region linking mode and the list of included or excluded Regions. You - # cannot use `UpdateFindingAggregator` to change the aggregation Region. + # The *aggregation Region* is now called the *home Region*. # - # You must run `UpdateFindingAggregator` from the current aggregation - # Region. + # + # + # Updates cross-Region aggregation settings. You can use this operation + # to update the Region linking mode and the list of included or excluded + # Amazon Web Services Regions. However, you can't use this operation to + # change the home Region. + # + # You can invoke this operation from the current home Region only. # # @option params [required, String] :finding_aggregator_arn # The ARN of the finding aggregator. To obtain the ARN, use @@ -8519,29 +8717,35 @@ def update_configuration_policy(params = {}, options = {}) # # The options are as follows: # - # * `ALL_REGIONS` - Indicates to aggregate findings from all of the - # Regions where Security Hub is enabled. When you choose this option, - # Security Hub also automatically aggregates findings from new Regions - # as Security Hub supports them and you opt into them. + # * `ALL_REGIONS` - Aggregates findings from all of the Regions where + # Security Hub is enabled. When you choose this option, Security Hub + # also automatically aggregates findings from new Regions as Security + # Hub supports them and you opt into them. # - # * `ALL_REGIONS_EXCEPT_SPECIFIED` - Indicates to aggregate findings - # from all of the Regions where Security Hub is enabled, except for - # the Regions listed in the `Regions` parameter. When you choose this - # option, Security Hub also automatically aggregates findings from new - # Regions as Security Hub supports them and you opt into them. + # * `ALL_REGIONS_EXCEPT_SPECIFIED` - Aggregates findings from all of the + # Regions where Security Hub is enabled, except for the Regions listed + # in the `Regions` parameter. When you choose this option, Security + # Hub also automatically aggregates findings from new Regions as + # Security Hub supports them and you opt into them. # - # * `SPECIFIED_REGIONS` - Indicates to aggregate findings only from the - # Regions listed in the `Regions` parameter. Security Hub does not + # * `SPECIFIED_REGIONS` - Aggregates findings only from the Regions + # listed in the `Regions` parameter. Security Hub does not # automatically aggregate findings from new Regions. # + # * `NO_REGIONS` - Aggregates no data because no Regions are selected as + # linked Regions. + # # @option params [Array] :regions # If `RegionLinkingMode` is `ALL_REGIONS_EXCEPT_SPECIFIED`, then this is - # a space-separated list of Regions that do not aggregate findings to - # the aggregation Region. + # a space-separated list of Regions that don't replicate and send + # findings to the home Region. # # If `RegionLinkingMode` is `SPECIFIED_REGIONS`, then this is a - # space-separated list of Regions that do aggregate findings to the - # aggregation Region. + # space-separated list of Regions that do replicate and send findings to + # the home Region. + # + # An `InvalidInputException` error results if you populate this field + # while `RegionLinkingMode` is `NO_REGIONS`. # # @return [Types::UpdateFindingAggregatorResponse] Returns a {Seahorse::Client::Response response} object which responds to the following methods: # @@ -8602,12 +8806,18 @@ def update_finding_aggregator(params = {}, options = {}) req.send_request(options) end - # `UpdateFindings` is deprecated. Instead of `UpdateFindings`, use - # `BatchUpdateFindings`. + # `UpdateFindings` is a deprecated operation. Instead of + # `UpdateFindings`, use the `BatchUpdateFindings` operation. + # + # The `UpdateFindings` operation updates the `Note` and `RecordState` of + # the Security Hub aggregated findings that the filter attributes + # specify. Any member account that can view the finding can also see the + # update to the finding. # - # Updates the `Note` and `RecordState` of the Security Hub-aggregated - # findings that the filter attributes specify. Any member account that - # can view the finding also sees the update to the finding. + # Finding updates made with `UpdateFindings` aren't persisted if the + # same finding is later updated by the finding provider through the + # `BatchImportFindings` operation. In addition, Security Hub doesn't + # record updates made with `UpdateFindings` in the finding history. # # @option params [required, Types::AwsSecurityFindingFilters] :filters # A collection of attributes that specify which findings you want to @@ -10248,6 +10458,16 @@ def update_security_control(params = {}, options = {}) # automatically. To not automatically enable new controls, set this to # `false`. # + # When you automatically enable new controls, you can interact with the + # controls in the console and programmatically immediately after + # release. However, automatically enabled controls have a temporary + # default status of `DISABLED`. It can take up to several days for + # Security Hub to process the control release and designate the control + # as `ENABLED` in your account. During the processing period, you can + # manually enable or disable a control, and Security Hub will maintain + # that designation regardless of whether you have `AutoEnableControls` + # set to `true`. + # # @option params [String] :control_finding_generator # Updates whether the calling account has consolidated control findings # turned on. If the value for this field is set to `SECURITY_CONTROL`, @@ -10293,6 +10513,10 @@ def update_security_hub_configuration(params = {}, options = {}) # Used to control whether an individual security standard control is # enabled or disabled. # + # Calls to this operation return a `RESOURCE_NOT_FOUND_EXCEPTION` error + # when the standard subscription for the control has + # `StandardsControlsUpdatable` value `NOT_READY_FOR_UPDATES`. + # # @option params [required, String] :standards_control_arn # The ARN of the security standard control to enable or disable. # @@ -10339,14 +10563,19 @@ def update_standards_control(params = {}, options = {}) # @api private def build_request(operation_name, params = {}) handlers = @handlers.for(operation_name) + tracer = config.telemetry_provider.tracer_provider.tracer( + Aws::Telemetry.module_to_tracer_name('Aws::SecurityHub') + ) context = Seahorse::Client::RequestContext.new( operation_name: operation_name, operation: config.api.operation(operation_name), client: self, params: params, - config: config) + config: config, + tracer: tracer + ) context[:gem_name] = 'aws-sdk-securityhub' - context[:gem_version] = '1.97.0' + context[:gem_version] = '1.130.0' Seahorse::Client::Request.new(handlers, context) end From 31411f861874db51a99446759519ce6c9fcbaac5 Mon Sep 17 00:00:00 2001 From: Richard Wang Date: Fri, 21 Mar 2025 13:08:09 -0700 Subject: [PATCH 13/59] Add with_metric for service calls --- .../lib/aws-sdk-core/assume_role_credentials.rb | 10 +++++++++- .../assume_role_web_identity_credentials.rb | 10 +++++++++- .../lib/aws-sdk-core/sso_credentials.rb | 16 ++++++++++++---- 3 files changed, 30 insertions(+), 6 deletions(-) diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_credentials.rb b/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_credentials.rb index b0bbc3fb4c4..34ecc0609e8 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_credentials.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_credentials.rb @@ -66,7 +66,7 @@ def initialize(options = {}) private def refresh - resp = @client.assume_role(@assume_role_params) + resp = with_metric { @client.assume_role(@assume_role_params) } creds = resp.credentials # TODO: CREDENTIALS_STS_ASSUME_ROLE # Call will include "o" (from #assume_role_from_profile) and "n"/"qk"/"vw"/"rs"/"tu" (from #resolve_source_profile) @@ -80,6 +80,14 @@ def refresh @expiration = creds.expiration end + def with_metric(&block) + if @metrics + Aws::Plugins::UserAgent.metric(*@metrics, &block) + else + block.call + end + end + def parse_account_id(resp) arn = resp.assumed_role_user&.arn ARNParser.parse(arn).account_id if ARNParser.arn?(arn) diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_web_identity_credentials.rb b/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_web_identity_credentials.rb index b8068e4ab3b..aa0257a87c0 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_web_identity_credentials.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_web_identity_credentials.rb @@ -80,7 +80,7 @@ def refresh # TODO: CREDENTIALS_STS_ASSUME_ROLE_WEB_ID (k) # Call will include at least "q" (from #assume_role_web_identity_credentials_from_config) # OR call will include at least "h" (from #assume_role_web_identity_credentials) - resp = @client.assume_role_with_web_identity(@assume_role_web_identity_params) + resp = with_metric { client.assume_role_with_web_identity(@assume_role_web_identity_params) } creds = resp.credentials @credentials = Credentials.new( creds.access_key_id, @@ -91,6 +91,14 @@ def refresh @expiration = creds.expiration end + def with_metric(&block) + if @metrics + Aws::Plugins::UserAgent.metric(*@metrics, &block) + else + block.call + end + end + def _token_from_file(path) unless path && File.exist?(path) raise Aws::Errors::MissingWebIdentityTokenFile.new diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/sso_credentials.rb b/gems/aws-sdk-core/lib/aws-sdk-core/sso_credentials.rb index 900b2aef69f..afd0ebd72f9 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/sso_credentials.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/sso_credentials.rb @@ -150,19 +150,19 @@ def refresh cached_token = read_cached_token # TODO: CREDENTIALS_SSO_LEGACY (u) # Call will include at least "t" (from #initialize) - @client.get_role_credentials( + with_metric { @client.get_role_credentials( account_id: @sso_account_id, role_name: @sso_role_name, access_token: cached_token['accessToken'] - ).role_credentials + ).role_credentials } else # TODO: CREDENTIALS_SSO (s) # Call will include at least "r" (from #initialize) - @client.get_role_credentials( + with_metric { @client.get_role_credentials( account_id: @sso_account_id, role_name: @sso_role_name, access_token: @token_provider.token.token - ).role_credentials + ).role_credentials } end @credentials = Credentials.new( @@ -174,6 +174,14 @@ def refresh @expiration = Time.at(c.expiration / 1000.0) end + def with_metric(&block) + if @metrics + Aws::Plugins::UserAgent.metric(*@metrics, &block) + else + block.call + end + end + def sso_cache_file start_url_sha1 = OpenSSL::Digest::SHA1.hexdigest(@sso_start_url.encode('utf-8')) File.join(Dir.home, '.aws', 'sso', 'cache', "#{start_url_sha1}.json") From 2eb610e1e98a362bc5f18c6c102a150a17f45d3d Mon Sep 17 00:00:00 2001 From: Richard Wang Date: Fri, 21 Mar 2025 13:12:55 -0700 Subject: [PATCH 14/59] Remove some puts --- gems/aws-sdk-core/lib/aws-sdk-core/plugins/sign.rb | 2 -- gems/aws-sdk-core/lib/aws-sdk-core/sso_credentials.rb | 2 -- 2 files changed, 4 deletions(-) diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/plugins/sign.rb b/gems/aws-sdk-core/lib/aws-sdk-core/plugins/sign.rb index a9e74d6c76e..9705e97bd67 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/plugins/sign.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/plugins/sign.rb @@ -51,8 +51,6 @@ def call(context) ) # TODO: temp added this, double check if signer.is_a?(SignatureV4) - puts "Signer here" - pp signer credentials = signer.signer.credentials_provider end signer.sign(context) diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/sso_credentials.rb b/gems/aws-sdk-core/lib/aws-sdk-core/sso_credentials.rb index afd0ebd72f9..488353eecac 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/sso_credentials.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/sso_credentials.rb @@ -70,7 +70,6 @@ def initialize(options = {}) @metrics = options.delete(:metrics) options = options.select {|k, v| !v.nil? } if (options[:sso_session]) - puts "New SSO" # TODO: CREDENTIALS_PROFILE_SSO (r) missing_keys = TOKEN_PROVIDER_REQUIRED_OPTS.select { |k| options[k].nil? } unless missing_keys.empty? @@ -95,7 +94,6 @@ def initialize(options = {}) @client = Aws::SSO::Client.new(client_opts) end else # legacy behavior - puts "Legacy SSO" # TODO: CREDENTIALS_PROFILE_SSO_LEGACY (t) missing_keys = LEGACY_REQUIRED_OPTS.select { |k| options[k].nil? } unless missing_keys.empty? From 8fc119cc70d5d8273978580c8617299bb48f6a82 Mon Sep 17 00:00:00 2001 From: Richard Wang Date: Mon, 24 Mar 2025 11:53:32 -0700 Subject: [PATCH 15/59] Wrap intermediate calls with metric --- .../aws-sdk-core/assume_role_credentials.rb | 14 +-- .../assume_role_web_identity_credentials.rb | 14 +-- .../aws-sdk-core/credential_provider_chain.rb | 46 ++++++--- .../lib/aws-sdk-core/credentials.rb | 3 +- .../lib/aws-sdk-core/ecs_credentials.rb | 3 +- .../instance_profile_credentials.rb | 3 +- .../lib/aws-sdk-core/plugins/sign.rb | 4 +- .../lib/aws-sdk-core/plugins/user_agent.rb | 3 + .../lib/aws-sdk-core/process_credentials.rb | 1 - .../lib/aws-sdk-core/shared_config.rb | 96 ++++++++++++------- .../lib/aws-sdk-core/shared_credentials.rb | 3 +- .../lib/aws-sdk-core/sso_credentials.rb | 20 +--- 12 files changed, 109 insertions(+), 101 deletions(-) diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_credentials.rb b/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_credentials.rb index 34ecc0609e8..a772d7af7bf 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_credentials.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_credentials.rb @@ -39,7 +39,6 @@ class AssumeRoleCredentials # end # def initialize(options = {}) - @metrics = options.delete(:metrics) client_opts = {} @assume_role_params = {} options.each_pair do |key, value| @@ -52,7 +51,6 @@ def initialize(options = {}) @client = client_opts[:client] || STS::Client.new(client_opts) @async_refresh = true super - @metrics << 'CREDENTIALS_STS_ASSUME_ROLE' if @metrics end # @return [STS::Client] @@ -61,12 +59,12 @@ def initialize(options = {}) # @return [Hash] attr_reader :assume_role_params - attr_reader :metrics + attr_accessor :metrics private def refresh - resp = with_metric { @client.assume_role(@assume_role_params) } + resp = @client.assume_role(@assume_role_params) creds = resp.credentials # TODO: CREDENTIALS_STS_ASSUME_ROLE # Call will include "o" (from #assume_role_from_profile) and "n"/"qk"/"vw"/"rs"/"tu" (from #resolve_source_profile) @@ -80,14 +78,6 @@ def refresh @expiration = creds.expiration end - def with_metric(&block) - if @metrics - Aws::Plugins::UserAgent.metric(*@metrics, &block) - else - block.call - end - end - def parse_account_id(resp) arn = resp.assumed_role_user&.arn ARNParser.parse(arn).account_id if ARNParser.arn?(arn) diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_web_identity_credentials.rb b/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_web_identity_credentials.rb index aa0257a87c0..54b57304c17 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_web_identity_credentials.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_web_identity_credentials.rb @@ -44,7 +44,6 @@ class AssumeRoleWebIdentityCredentials # with an instance of this object when # AWS credentials are required and need to be refreshed. def initialize(options = {}) - @metrics = options.delete(:metrics) client_opts = {} @assume_role_web_identity_params = {} @token_file = options.delete(:web_identity_token_file) @@ -63,13 +62,12 @@ def initialize(options = {}) end @client = client_opts[:client] || STS::Client.new(client_opts.merge(credentials: nil)) super - @metrics << 'CREDENTIALS_STS_ASSUME_ROLE_WEB_ID' if @metrics end # @return [STS::Client] attr_reader :client - attr_reader :metrics + attr_accessor :metrics private @@ -80,7 +78,7 @@ def refresh # TODO: CREDENTIALS_STS_ASSUME_ROLE_WEB_ID (k) # Call will include at least "q" (from #assume_role_web_identity_credentials_from_config) # OR call will include at least "h" (from #assume_role_web_identity_credentials) - resp = with_metric { client.assume_role_with_web_identity(@assume_role_web_identity_params) } + resp = client.assume_role_with_web_identity(@assume_role_web_identity_params) creds = resp.credentials @credentials = Credentials.new( creds.access_key_id, @@ -91,14 +89,6 @@ def refresh @expiration = creds.expiration end - def with_metric(&block) - if @metrics - Aws::Plugins::UserAgent.metric(*@metrics, &block) - else - block.call - end - end - def _token_from_file(path) unless path && File.exist?(path) raise Aws::Errors::MissingWebIdentityTokenFile.new diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/credential_provider_chain.rb b/gems/aws-sdk-core/lib/aws-sdk-core/credential_provider_chain.rb index 0506daba741..61c6ef42b78 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/credential_provider_chain.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/credential_provider_chain.rb @@ -113,13 +113,14 @@ def providers # TODO: CREDENTIALS_PROFILE (n)?? def static_credentials(options) if options[:config] - Credentials.new( + credentials = Credentials.new( options[:config].access_key_id, options[:config].secret_access_key, options[:config].session_token, - account_id: options[:config].account_id, - metrics: ['CREDENTIALS_PROFILE'] + account_id: options[:config].account_id ) + credentials.metrics = ['CREDENTIALS_PROFILE'] + credentials end end @@ -148,7 +149,9 @@ def static_profile_assume_role_credentials(options) def static_profile_credentials(options) if options[:config] && options[:config].profile - SharedCredentials.new(profile_name: options[:config].profile, metrics: ['CREDENTIALS_PROFILE']) + credentials = SharedCredentials.new(profile_name: options[:config].profile) + credentials.metrics = ['CREDENTIALS_PROFILE'] + credentials end rescue Errors::NoSuchProfileError nil @@ -159,7 +162,7 @@ def static_profile_process_credentials(options) process_provider = Aws.shared_config.credential_process(profile: options[:config].profile) if process_provider credentials = ProcessCredentials.new([process_provider]) - credentials.metrics = ['CREDENTIALS_PROFILE_PROCESS', 'CREDENTIALS_PROCESS'] + credentials.metrics = %w[CREDENTIALS_PROFILE_PROCESS CREDENTIALS_PROCESS] return credentials end end @@ -174,13 +177,14 @@ def env_credentials(_options) secret = %w[AWS_SECRET_ACCESS_KEY AMAZON_SECRET_ACCESS_KEY AWS_SECRET_KEY] token = %w[AWS_SESSION_TOKEN AMAZON_SESSION_TOKEN] account_id = %w[AWS_ACCOUNT_ID] - Credentials.new( + credentials = Credentials.new( envar(key), envar(secret), envar(token), - account_id: envar(account_id), - metrics: ['CREDENTIALS_ENV_VARS'] + account_id: envar(account_id) ) + credentials.metrics = ['CREDENTIALS_ENV_VARS'] + credentials end def envar(keys) @@ -196,7 +200,9 @@ def determine_profile_name(options) def shared_credentials(options) profile_name = determine_profile_name(options) - SharedCredentials.new(profile_name: profile_name, metrics: ['CREDENTIALS_PROFILE']) + credentials = SharedCredentials.new(profile_name: profile_name) + credentials.metrics = ['CREDENTIALS_PROFILE'] + credentials rescue Errors::NoSuchProfileError nil end @@ -207,7 +213,7 @@ def process_credentials(options) process_provider = Aws.shared_config.credential_process(profile: profile_name) if process_provider credentials = ProcessCredentials.new([process_provider]) - credentials.metrics = ['CREDENTIALS_PROFILE_PROCESS', 'CREDENTIALS_PROCESS'] + credentials.metrics = %w[CREDENTIALS_PROFILE_PROCESS CREDENTIALS_PROCESS] return credentials end end @@ -238,10 +244,13 @@ def assume_role_web_identity_credentials(options) role_arn: role_arn, web_identity_token_file: token_file, role_session_name: ENV['AWS_ROLE_SESSION_NAME'], - metrics: ['CREDENTIALS_ENV_VARS_STS_WEB_ID_TOKEN'] } cfg[:region] = region if region - AssumeRoleWebIdentityCredentials.new(cfg) + with_metrics('CREDENTIALS_ENV_VARS_STS_WEB_ID_TOKEN') do + credentials = AssumeRoleWebIdentityCredentials.new(cfg) + credentials.metrics = %w[CREDENTIALS_ENV_VARS_STS_WEB_ID_TOKEN CREDENTIALS_STS_ASSUME_ROLE_WEB_ID] + credentials + end elsif Aws.shared_config.config_enabled? profile = options[:config].profile if options[:config] Aws.shared_config.assume_role_web_identity_credentials_from_config( @@ -256,11 +265,14 @@ def instance_profile_credentials(options) if ENV['AWS_CONTAINER_CREDENTIALS_RELATIVE_URI'] || ENV['AWS_CONTAINER_CREDENTIALS_FULL_URI'] # TODO: CREDENTIALS_HTTP (z) - options[:metrics] = 'CREDENTIALS_HTTP' - ECSCredentials.new(options.merge(metrics: ['CREDENTIALS_HTTP'])) + credentials = ECSCredentials.new(options) + credentials.metrics = ['CREDENTIALS_HTTP'] + credentials else # TODO: CREDENTIALS_IMDS (0) - InstanceProfileCredentials.new(options.merge(profile: profile_name, metrics: ['CREDENTIALS_IMDS'])) + credentials = InstanceProfileCredentials.new(options.merge(profile: profile_name)) + credentials.metrics = ['CREDENTIALS_IMDS'] + credentials end end @@ -274,5 +286,9 @@ def assume_role_with_profile(options, profile_name) end Aws.shared_config.assume_role_credentials_from_config(assume_opts) end + + def with_metrics(metric, &block) + Aws::Plugins::UserAgent.metric(metric, &block) + end end end diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/credentials.rb b/gems/aws-sdk-core/lib/aws-sdk-core/credentials.rb index 23acaefab2c..4e642c1abf8 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/credentials.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/credentials.rb @@ -10,7 +10,6 @@ class Credentials # @option kwargs [String] :credential_scope (nil) def initialize(access_key_id, secret_access_key, session_token = nil, **kwargs) - @metrics = kwargs.delete(:metrics) @access_key_id = access_key_id @secret_access_key = secret_access_key @session_token = session_token @@ -29,7 +28,7 @@ def initialize(access_key_id, secret_access_key, session_token = nil, # @return [String, nil] attr_reader :account_id - attr_reader :metrics + attr_accessor :metrics # @return [Credentials] def credentials diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/ecs_credentials.rb b/gems/aws-sdk-core/lib/aws-sdk-core/ecs_credentials.rb index 0829521e756..353442a06f2 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/ecs_credentials.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/ecs_credentials.rb @@ -65,7 +65,6 @@ class InvalidTokenError < RuntimeError; end # with an instance of this object when # AWS credentials are required and need to be refreshed. def initialize(options = {}) - @metrics = options.delete(:metrics) credential_path = options[:credential_path] || ENV['AWS_CONTAINER_CREDENTIALS_RELATIVE_URI'] endpoint = options[:endpoint] || @@ -85,7 +84,7 @@ def initialize(options = {}) # fetch credentials from the instance metadata service. Defaults to 0. attr_reader :retries - attr_reader :metrics + attr_accessor :metrics private diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/instance_profile_credentials.rb b/gems/aws-sdk-core/lib/aws-sdk-core/instance_profile_credentials.rb index befc4d9d27d..72c2b08e42b 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/instance_profile_credentials.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/instance_profile_credentials.rb @@ -75,7 +75,6 @@ class TokenExpiredError < RuntimeError; end # with an instance of this object when # AWS credentials are required and need to be refreshed. def initialize(options = {}) - @metrics = options.delete(:metrics) @retries = options[:retries] || 1 endpoint_mode = resolve_endpoint_mode(options) @endpoint = resolve_endpoint(options, endpoint_mode) @@ -99,7 +98,7 @@ def initialize(options = {}) # the default credential chain ({Aws::CredentialProviderChain}). attr_reader :retries - attr_reader :metrics + attr_accessor :metrics private diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/plugins/sign.rb b/gems/aws-sdk-core/lib/aws-sdk-core/plugins/sign.rb index 9705e97bd67..81effae87da 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/plugins/sign.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/plugins/sign.rb @@ -55,12 +55,12 @@ def call(context) end signer.sign(context) end - with_metric(credentials) { @handler.call(context) } + with_metrics(credentials) { @handler.call(context) } end private - def with_metric(credentials, &block) + def with_metrics(credentials, &block) puts "in with metric" unless credentials && credentials.respond_to?(:metrics) puts "No metrics" diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/plugins/user_agent.rb b/gems/aws-sdk-core/lib/aws-sdk-core/plugins/user_agent.rb index b526e9eee5d..a221291358b 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/plugins/user_agent.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/plugins/user_agent.rb @@ -215,6 +215,9 @@ def metric_metadata return end + # Needed for AssumeRoleCredentials feature id tracking + Thread.current[:aws_sdk_core_user_agent_metric].uniq! + metrics = Thread.current[:aws_sdk_core_user_agent_metric].join(',') # puts "Metrics metadata" diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/process_credentials.rb b/gems/aws-sdk-core/lib/aws-sdk-core/process_credentials.rb index 0163f66a7da..5005107d3fe 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/process_credentials.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/process_credentials.rb @@ -29,7 +29,6 @@ class ProcessCredentials # the process name and its arguments to execute, or a single string to be # executed by the shell (deprecated and insecure). def initialize(process) - @metrics = nil if process.is_a?(String) warn('Passing a single string to Aws::ProcessCredentials.new '\ 'is insecure, please use use an array of system arguments instead') diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/shared_config.rb b/gems/aws-sdk-core/lib/aws-sdk-core/shared_config.rb index af57aa0719a..e3be0f0954b 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/shared_config.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/shared_config.rb @@ -133,21 +133,17 @@ def assume_role_web_identity_credentials_from_config(opts = {}) entry = @parsed_config.fetch(p, {}) if entry['web_identity_token_file'] && entry['role_arn'] # TODO: CREDENTIALS_PROFILE_STS_WEB_ID_TOKEN (q) - - # Needed because of AssumeRole flow - if opts[:metrics] - opts[:metrics] << 'CREDENTIALS_PROFILE_STS_WEB_ID_TOKEN' - else - opts[:metrics] = ['CREDENTIALS_PROFILE_STS_WEB_ID_TOKEN'] - end cfg = { role_arn: entry['role_arn'], web_identity_token_file: entry['web_identity_token_file'], role_session_name: entry['role_session_name'], - metrics: opts.delete(:metrics) } cfg[:region] = opts[:region] if opts[:region] - AssumeRoleWebIdentityCredentials.new(cfg) + with_metrics('CREDENTIALS_PROFILE_STS_WEB_ID_TOKEN') do + credentials = AssumeRoleWebIdentityCredentials.new(cfg) + credentials.metrics = %w[CREDENTIALS_PROFILE_STS_WEB_ID_TOKEN CREDENTIALS_STS_ASSUME_ROLE_WEB_ID] + credentials + end end end end @@ -157,10 +153,9 @@ def assume_role_web_identity_credentials_from_config(opts = {}) # file, if present. def sso_credentials_from_config(opts = {}) p = opts[:profile] || @profile_name - metrics = opts.delete(:metrics) - credentials = sso_credentials_from_profile(@parsed_credentials, p, metrics) + credentials = sso_credentials_from_profile(@parsed_credentials, p) if @parsed_config - credentials ||= sso_credentials_from_profile(@parsed_config, p, metrics) + credentials ||= sso_credentials_from_profile(@parsed_config, p) end credentials end @@ -266,7 +261,9 @@ def assume_role_from_profile(cfg, profile, opts, chain_config) elsif opts[:source_profile] # TODO: CREDENTIALS_PROFILE_SOURCE_PROFILE (o) opts[:visited_profiles] ||= Set.new - opts[:credentials], metrics = resolve_source_profile(opts[:source_profile], opts) + opts[:credentials], metrics = with_metrics('CREDENTIALS_PROFILE_SOURCE_PROFILE') do + resolve_source_profile(opts[:source_profile], opts) + end if opts[:credentials] opts[:role_session_name] ||= prof_cfg['role_session_name'] opts[:role_session_name] ||= 'default_session' @@ -275,9 +272,12 @@ def assume_role_from_profile(cfg, profile, opts, chain_config) opts[:external_id] ||= prof_cfg['external_id'] opts[:serial_number] ||= prof_cfg['mfa_serial'] opts[:profile] = opts.delete(:source_profile) - opts[:metrics] = metrics opts.delete(:visited_profiles) - AssumeRoleCredentials.new(opts) + with_metrics(metrics) do + credentials = AssumeRoleCredentials.new(opts) + credentials.metrics = metrics << 'CREDENTIALS_STS_ASSUME_ROLE' + credentials + end else raise Errors::NoSourceProfileError, "Profile #{profile} has a role_arn, and source_profile, but the"\ @@ -285,10 +285,12 @@ def assume_role_from_profile(cfg, profile, opts, chain_config) end elsif credential_source # TODO: CREDENTIALS_PROFILE_NAMED_PROVIDER (p) - opts[:credentials], metrics = credentials_from_source( - credential_source, - chain_config - ) + opts[:credentials], metrics = with_metrics('CREDENTIALS_PROFILE_NAMED_PROVIDER') do + credentials_from_source( + credential_source, + chain_config + ) + end if opts[:credentials] opts[:role_session_name] ||= prof_cfg['role_session_name'] opts[:role_session_name] ||= 'default_session' @@ -296,9 +298,12 @@ def assume_role_from_profile(cfg, profile, opts, chain_config) opts[:duration_seconds] ||= prof_cfg['duration_seconds'] opts[:external_id] ||= prof_cfg['external_id'] opts[:serial_number] ||= prof_cfg['mfa_serial'] - opts[:metrics] = metrics opts.delete(:source_profile) # Cleanup - AssumeRoleCredentials.new(opts) + with_metrics(metrics) do + credentials = AssumeRoleCredentials.new(opts) + credentials.metrics = metrics << 'CREDENTIALS_STS_ASSUME_ROLE' + credentials + end else raise Errors::NoSourceCredentials, "Profile #{profile} could not get source credentials from"\ @@ -327,13 +332,13 @@ def resolve_source_profile(profile, opts = {}) elsif profile_config && profile_config['source_profile'] opts.delete(:source_profile) assume_role_credentials_from_config(opts.merge(profile: profile)) - elsif (provider = assume_role_web_identity_credentials_from_config(opts.merge(profile: profile, metrics: ['CREDENTIALS_PROFILE_SOURCE_PROFILE']))) + elsif (provider = assume_role_web_identity_credentials_from_config(opts.merge(profile: profile))) # TODO: CREDENTIALS_PROFILE_STS_WEB_ID_TOKEN and CREDENTIALS_STS_ASSUME_ROLE_WEB_ID (qk) [provider.credentials, provider.metrics] if provider.credentials.set? elsif (provider = assume_role_process_credentials_from_config(profile)) # TODO: CREDENTIALS_PROFILE_PROCESS and CREDENTIALS_PROCESS (vw) [provider.credentials, %w[CREDENTIALS_PROFILE_SOURCE_PROFILE CREDENTIALS_PROFILE_PROCESS CREDENTIALS_PROCESS]] if provider.credentials.set? - elsif (provider = sso_credentials_from_config(profile: profile, metrics: ['CREDENTIALS_PROFILE_SOURCE_PROFILE'])) + elsif (provider = sso_credentials_from_config(profile: profile)) # TODO: CREDENTIALS_PROFILE_SSO and CREDENTIALS_SSO (rs) or CREDENTIALS_PROFILE_SSO_LEGACY and CREDENTIALS_SSO_LEGACY (tu) [provider.credentials, provider.metrics] if provider.credentials.set? end @@ -380,7 +385,7 @@ def credentials_from_config(profile, _opts) # If any of the sso_ profile values are present, attempt to construct # SSOCredentials - def sso_credentials_from_profile(cfg, profile, metrics) + def sso_credentials_from_profile(cfg, profile) if @parsed_config && (prof_config = cfg[profile]) && !(prof_config.keys & SSO_CREDENTIAL_PROFILE_KEYS).empty? @@ -407,21 +412,32 @@ def sso_credentials_from_profile(cfg, profile, metrics) sso_start_url = prof_config['sso_start_url'] end - # Needed for AssumeRole - if metrics - metrics << prof_config['sso_session'].nil? ? 'CREDENTIALS_PROFILE_SSO_LEGACY' : 'CREDENTIALS_PROFILE_SSO' + if prof_config['sso_session'] + with_metrics('CREDENTIALS_PROFILE_SSO') do + credentials = SSOCredentials.new( + sso_account_id: prof_config['sso_account_id'], + sso_role_name: prof_config['sso_role_name'], + sso_session: prof_config['sso_session'], + sso_region: sso_region, + sso_start_url: sso_start_url, + ) + credentials.metrics = %w[CREDENTIALS_PROFILE_SSO CREDENTIALS_SSO] + credentials + end else - metrics = prof_config['sso_session'].nil? ? ['CREDENTIALS_PROFILE_SSO_LEGACY'] : ['CREDENTIALS_PROFILE_SSO'] + with_metrics('CREDENTIALS_PROFILE_SSO_LEGACY') do + credentials = SSOCredentials.new( + sso_account_id: prof_config['sso_account_id'], + sso_role_name: prof_config['sso_role_name'], + sso_session: prof_config['sso_session'], + sso_region: sso_region, + sso_start_url: sso_start_url, + ) + credentials.metrics = %w[CREDENTIALS_PROFILE_SSO_LEGACY CREDENTIALS_SSO_LEGACY] + credentials + end end - SSOCredentials.new( - sso_account_id: prof_config['sso_account_id'], - sso_role_name: prof_config['sso_role_name'], - sso_session: prof_config['sso_session'], - sso_region: sso_region, - sso_start_url: sso_start_url, - metrics: metrics - ) end end @@ -509,5 +525,13 @@ def sso_session(cfg, profile, sso_session_name) sso_session end + + def with_metrics(metrics, &block) + if metrics.is_a?(Array) + Aws::Plugins::UserAgent.metric(*metrics, &block) + else + Aws::Plugins::UserAgent.metric(metrics, &block) + end + end end end diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/shared_credentials.rb b/gems/aws-sdk-core/lib/aws-sdk-core/shared_credentials.rb index a152d9cdfdb..141a0003e3a 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/shared_credentials.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/shared_credentials.rb @@ -25,7 +25,6 @@ class SharedCredentials # `ENV['AWS_PROFILE']`. # def initialize(options = {}) - @metrics = options.delete(:metrics) shared_config = Aws.shared_config @path = options[:path] @path ||= shared_config.credentials_path @@ -52,7 +51,7 @@ def initialize(options = {}) # @return [Credentials] attr_reader :credentials - attr_reader :metrics + attr_accessor :metrics # @api private def inspect diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/sso_credentials.rb b/gems/aws-sdk-core/lib/aws-sdk-core/sso_credentials.rb index 488353eecac..48037728ef3 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/sso_credentials.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/sso_credentials.rb @@ -67,7 +67,6 @@ class SSOCredentials # with an instance of this object when # AWS credentials are required and need to be refreshed. def initialize(options = {}) - @metrics = options.delete(:metrics) options = options.select {|k, v| !v.nil? } if (options[:sso_session]) # TODO: CREDENTIALS_PROFILE_SSO (r) @@ -118,13 +117,12 @@ def initialize(options = {}) @async_refresh = true super - @legacy ? @metrics << 'CREDENTIALS_SSO_LEGACY' : @metrics << 'CREDENTIALS_SSO' if @metrics end # @return [SSO::Client] attr_reader :client - attr_reader :metrics + attr_accessor :metrics private @@ -148,19 +146,19 @@ def refresh cached_token = read_cached_token # TODO: CREDENTIALS_SSO_LEGACY (u) # Call will include at least "t" (from #initialize) - with_metric { @client.get_role_credentials( + @client.get_role_credentials( account_id: @sso_account_id, role_name: @sso_role_name, access_token: cached_token['accessToken'] - ).role_credentials } + ).role_credentials else # TODO: CREDENTIALS_SSO (s) # Call will include at least "r" (from #initialize) - with_metric { @client.get_role_credentials( + @client.get_role_credentials( account_id: @sso_account_id, role_name: @sso_role_name, access_token: @token_provider.token.token - ).role_credentials } + ).role_credentials end @credentials = Credentials.new( @@ -172,14 +170,6 @@ def refresh @expiration = Time.at(c.expiration / 1000.0) end - def with_metric(&block) - if @metrics - Aws::Plugins::UserAgent.metric(*@metrics, &block) - else - block.call - end - end - def sso_cache_file start_url_sha1 = OpenSSL::Digest::SHA1.hexdigest(@sso_start_url.encode('utf-8')) File.join(Dir.home, '.aws', 'sso', 'cache', "#{start_url_sha1}.json") From 8cde58b5eb63434e10b4e2d849e1b032490aa7e4 Mon Sep 17 00:00:00 2001 From: Richard Wang Date: Mon, 24 Mar 2025 11:56:29 -0700 Subject: [PATCH 16/59] Change priority and revert chaining --- gems/aws-sdk-core/lib/aws-sdk-core/plugins/user_agent.rb | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/plugins/user_agent.rb b/gems/aws-sdk-core/lib/aws-sdk-core/plugins/user_agent.rb index a221291358b..77df0f50a50 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/plugins/user_agent.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/plugins/user_agent.rb @@ -90,10 +90,7 @@ def self.feature(_feature, &block) def self.metric(*metrics, &block) Thread.current[:aws_sdk_core_user_agent_metric] ||= [] - metrics = metrics.map do |metric| - METRICS[metric] - end - metrics = metrics.compact + metrics = metrics.map { |metric| METRICS[metric] }.compact Thread.current[:aws_sdk_core_user_agent_metric].concat(metrics) block.call ensure @@ -231,7 +228,7 @@ def metric_metadata end end - handler(Handler, step: :sign, priority: 49) + handler(Handler, step: :sign, priority: 5) end end end From 0806c60b53e49a86da6f3d72be2599efba919bd5 Mon Sep 17 00:00:00 2001 From: Richard Wang Date: Mon, 24 Mar 2025 12:46:35 -0700 Subject: [PATCH 17/59] Remove comments --- .../lib/aws-sdk-core/assume_role_credentials.rb | 3 --- .../aws-sdk-core/assume_role_web_identity_credentials.rb | 3 --- .../lib/aws-sdk-core/credential_provider_chain.rb | 5 ----- gems/aws-sdk-core/lib/aws-sdk-core/plugins/sign.rb | 3 --- gems/aws-sdk-core/lib/aws-sdk-core/plugins/user_agent.rb | 2 -- .../aws-sdk-core/lib/aws-sdk-core/process_credentials.rb | 2 -- gems/aws-sdk-core/lib/aws-sdk-core/shared_config.rb | 9 --------- gems/aws-sdk-core/lib/aws-sdk-core/sso_credentials.rb | 6 ------ 8 files changed, 33 deletions(-) diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_credentials.rb b/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_credentials.rb index a772d7af7bf..136be5ab34f 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_credentials.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_credentials.rb @@ -66,9 +66,6 @@ def initialize(options = {}) def refresh resp = @client.assume_role(@assume_role_params) creds = resp.credentials - # TODO: CREDENTIALS_STS_ASSUME_ROLE - # Call will include "o" (from #assume_role_from_profile) and "n"/"qk"/"vw"/"rs"/"tu" (from #resolve_source_profile) - # OR call will include "p" (from #assume_role_from_profile) and "0"/"z" (from #credentials_from_source) @credentials = Credentials.new( creds.access_key_id, creds.secret_access_key, diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_web_identity_credentials.rb b/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_web_identity_credentials.rb index 54b57304c17..6a1b8302cf8 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_web_identity_credentials.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_web_identity_credentials.rb @@ -75,9 +75,6 @@ def refresh # read from token file everytime it refreshes @assume_role_web_identity_params[:web_identity_token] = _token_from_file(@token_file) - # TODO: CREDENTIALS_STS_ASSUME_ROLE_WEB_ID (k) - # Call will include at least "q" (from #assume_role_web_identity_credentials_from_config) - # OR call will include at least "h" (from #assume_role_web_identity_credentials) resp = client.assume_role_with_web_identity(@assume_role_web_identity_params) creds = resp.credentials @credentials = Credentials.new( diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/credential_provider_chain.rb b/gems/aws-sdk-core/lib/aws-sdk-core/credential_provider_chain.rb index 61c6ef42b78..3e1593283f2 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/credential_provider_chain.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/credential_provider_chain.rb @@ -110,7 +110,6 @@ def providers ] end - # TODO: CREDENTIALS_PROFILE (n)?? def static_credentials(options) if options[:config] credentials = Credentials.new( @@ -171,7 +170,6 @@ def static_profile_process_credentials(options) end - # TODO: CREDENTIALS_ENV_VARS (g)?? def env_credentials(_options) key = %w[AWS_ACCESS_KEY_ID AMAZON_ACCESS_KEY_ID AWS_ACCESS_KEY] secret = %w[AWS_SECRET_ACCESS_KEY AMAZON_SECRET_ACCESS_KEY AWS_SECRET_KEY] @@ -239,7 +237,6 @@ def assume_role_credentials(options) def assume_role_web_identity_credentials(options) region = options[:config].region if options[:config] if (role_arn = ENV['AWS_ROLE_ARN']) && (token_file = ENV['AWS_WEB_IDENTITY_TOKEN_FILE']) - # TODO: CREDENTIALS_ENV_VARS_STS_WEB_ID_TOKEN (h) cfg = { role_arn: role_arn, web_identity_token_file: token_file, @@ -264,12 +261,10 @@ def instance_profile_credentials(options) profile_name = determine_profile_name(options) if ENV['AWS_CONTAINER_CREDENTIALS_RELATIVE_URI'] || ENV['AWS_CONTAINER_CREDENTIALS_FULL_URI'] - # TODO: CREDENTIALS_HTTP (z) credentials = ECSCredentials.new(options) credentials.metrics = ['CREDENTIALS_HTTP'] credentials else - # TODO: CREDENTIALS_IMDS (0) credentials = InstanceProfileCredentials.new(options.merge(profile: profile_name)) credentials.metrics = ['CREDENTIALS_IMDS'] credentials diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/plugins/sign.rb b/gems/aws-sdk-core/lib/aws-sdk-core/plugins/sign.rb index 81effae87da..531aaac36d3 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/plugins/sign.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/plugins/sign.rb @@ -68,12 +68,9 @@ def with_metrics(credentials, &block) end metrics = [] - # Add check if flag isn't set, then emit Credentials CODE if !credentials.metrics - puts "!!!!! Credentials from code !!!!!" metrics << 'CREDENTIALS_CODE' else - puts "!!!!! Credential type !!!!!" puts credentials.class.name (metrics << credentials.metrics).flatten! end diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/plugins/user_agent.rb b/gems/aws-sdk-core/lib/aws-sdk-core/plugins/user_agent.rb index 77df0f50a50..6bba56137e0 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/plugins/user_agent.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/plugins/user_agent.rb @@ -217,8 +217,6 @@ def metric_metadata metrics = Thread.current[:aws_sdk_core_user_agent_metric].join(',') - # puts "Metrics metadata" - # pp metrics # Metric metadata is limited to 1024 bytes return "m/#{metrics}" if metrics.bytesize <= 1024 diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/process_credentials.rb b/gems/aws-sdk-core/lib/aws-sdk-core/process_credentials.rb index 5005107d3fe..0a85e0e0d9e 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/process_credentials.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/process_credentials.rb @@ -33,7 +33,6 @@ def initialize(process) warn('Passing a single string to Aws::ProcessCredentials.new '\ 'is insecure, please use use an array of system arguments instead') end - # TODO: CREDENTIALS_PROFILE_PROCESS (v) @process = process @credentials = credentials_from_process @async_refresh = false @@ -59,7 +58,6 @@ def credentials_from_process ) end - # TODO: CREDENTIALS_PROCESS (w) begin creds_json = Aws::Json.load(raw_out) rescue Aws::Json::ParseError diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/shared_config.rb b/gems/aws-sdk-core/lib/aws-sdk-core/shared_config.rb index e3be0f0954b..0cbeeaa38da 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/shared_config.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/shared_config.rb @@ -132,7 +132,6 @@ def assume_role_web_identity_credentials_from_config(opts = {}) if @config_enabled && @parsed_config entry = @parsed_config.fetch(p, {}) if entry['web_identity_token_file'] && entry['role_arn'] - # TODO: CREDENTIALS_PROFILE_STS_WEB_ID_TOKEN (q) cfg = { role_arn: entry['role_arn'], web_identity_token_file: entry['web_identity_token_file'], @@ -259,7 +258,6 @@ def assume_role_from_profile(cfg, profile, opts, chain_config) 'a credential_source. For assume role credentials, must '\ 'provide only source_profile or credential_source, not both.' elsif opts[:source_profile] - # TODO: CREDENTIALS_PROFILE_SOURCE_PROFILE (o) opts[:visited_profiles] ||= Set.new opts[:credentials], metrics = with_metrics('CREDENTIALS_PROFILE_SOURCE_PROFILE') do resolve_source_profile(opts[:source_profile], opts) @@ -284,7 +282,6 @@ def assume_role_from_profile(cfg, profile, opts, chain_config) ' source_profile does not have credentials.' end elsif credential_source - # TODO: CREDENTIALS_PROFILE_NAMED_PROVIDER (p) opts[:credentials], metrics = with_metrics('CREDENTIALS_PROFILE_NAMED_PROVIDER') do credentials_from_source( credential_source, @@ -327,19 +324,15 @@ def resolve_source_profile(profile, opts = {}) end if (creds = credentials(profile: profile)) - # TODO: CREDENTIALS_PROFILE (n) [creds, %w[CREDENTIALS_PROFILE_SOURCE_PROFILE CREDENTIALS_PROFILE]] # static credentials elsif profile_config && profile_config['source_profile'] opts.delete(:source_profile) assume_role_credentials_from_config(opts.merge(profile: profile)) elsif (provider = assume_role_web_identity_credentials_from_config(opts.merge(profile: profile))) - # TODO: CREDENTIALS_PROFILE_STS_WEB_ID_TOKEN and CREDENTIALS_STS_ASSUME_ROLE_WEB_ID (qk) [provider.credentials, provider.metrics] if provider.credentials.set? elsif (provider = assume_role_process_credentials_from_config(profile)) - # TODO: CREDENTIALS_PROFILE_PROCESS and CREDENTIALS_PROCESS (vw) [provider.credentials, %w[CREDENTIALS_PROFILE_SOURCE_PROFILE CREDENTIALS_PROFILE_PROCESS CREDENTIALS_PROCESS]] if provider.credentials.set? elsif (provider = sso_credentials_from_config(profile: profile)) - # TODO: CREDENTIALS_PROFILE_SSO and CREDENTIALS_SSO (rs) or CREDENTIALS_PROFILE_SSO_LEGACY and CREDENTIALS_SSO_LEGACY (tu) [provider.credentials, provider.metrics] if provider.credentials.set? end end @@ -347,7 +340,6 @@ def resolve_source_profile(profile, opts = {}) def credentials_from_source(credential_source, config) case credential_source when 'Ec2InstanceMetadata' - # TODO: CREDENTIALS_IMDS (0) [InstanceProfileCredentials.new( retries: config ? config.instance_profile_credentials_retries : 0, http_open_timeout: config ? config.instance_profile_credentials_timeout : 1, @@ -355,7 +347,6 @@ def credentials_from_source(credential_source, config) ), %w[CREDENTIALS_PROFILE_NAMED_PROVIDER CREDENTIALS_IMDS]] when 'EcsContainer' - # TODO: CREDENTIALS_HTTP (z) [ECSCredentials.new, %w[CREDENTIALS_PROFILE_NAMED_PROVIDER CREDENTIALS_HTTP]] else raise Errors::InvalidCredentialSourceError, "Unsupported credential_source: #{credential_source}" diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/sso_credentials.rb b/gems/aws-sdk-core/lib/aws-sdk-core/sso_credentials.rb index 48037728ef3..c41e8e5951b 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/sso_credentials.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/sso_credentials.rb @@ -69,7 +69,6 @@ class SSOCredentials def initialize(options = {}) options = options.select {|k, v| !v.nil? } if (options[:sso_session]) - # TODO: CREDENTIALS_PROFILE_SSO (r) missing_keys = TOKEN_PROVIDER_REQUIRED_OPTS.select { |k| options[k].nil? } unless missing_keys.empty? raise ArgumentError, "Missing required keys: #{missing_keys}" @@ -93,7 +92,6 @@ def initialize(options = {}) @client = Aws::SSO::Client.new(client_opts) end else # legacy behavior - # TODO: CREDENTIALS_PROFILE_SSO_LEGACY (t) missing_keys = LEGACY_REQUIRED_OPTS.select { |k| options[k].nil? } unless missing_keys.empty? raise ArgumentError, "Missing required keys: #{missing_keys}" @@ -144,16 +142,12 @@ def read_cached_token def refresh c = if @legacy cached_token = read_cached_token - # TODO: CREDENTIALS_SSO_LEGACY (u) - # Call will include at least "t" (from #initialize) @client.get_role_credentials( account_id: @sso_account_id, role_name: @sso_role_name, access_token: cached_token['accessToken'] ).role_credentials else - # TODO: CREDENTIALS_SSO (s) - # Call will include at least "r" (from #initialize) @client.get_role_credentials( account_id: @sso_account_id, role_name: @sso_role_name, From 5434f869476742fa186e5fa5e6de73d7ae5da032 Mon Sep 17 00:00:00 2001 From: Richard Wang Date: Mon, 24 Mar 2025 12:55:50 -0700 Subject: [PATCH 18/59] Fix process credentials --- .../lib/aws-sdk-core/credential_provider_chain.rb | 4 ++-- gems/aws-sdk-core/lib/aws-sdk-core/shared_config.rb | 8 ++++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/credential_provider_chain.rb b/gems/aws-sdk-core/lib/aws-sdk-core/credential_provider_chain.rb index 3e1593283f2..b2c6482285b 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/credential_provider_chain.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/credential_provider_chain.rb @@ -162,7 +162,7 @@ def static_profile_process_credentials(options) if process_provider credentials = ProcessCredentials.new([process_provider]) credentials.metrics = %w[CREDENTIALS_PROFILE_PROCESS CREDENTIALS_PROCESS] - return credentials + credentials end end rescue Errors::NoSuchProfileError @@ -212,7 +212,7 @@ def process_credentials(options) if process_provider credentials = ProcessCredentials.new([process_provider]) credentials.metrics = %w[CREDENTIALS_PROFILE_PROCESS CREDENTIALS_PROCESS] - return credentials + credentials end end rescue Errors::NoSuchProfileError diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/shared_config.rb b/gems/aws-sdk-core/lib/aws-sdk-core/shared_config.rb index 0cbeeaa38da..70e3e6b4a9c 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/shared_config.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/shared_config.rb @@ -331,7 +331,7 @@ def resolve_source_profile(profile, opts = {}) elsif (provider = assume_role_web_identity_credentials_from_config(opts.merge(profile: profile))) [provider.credentials, provider.metrics] if provider.credentials.set? elsif (provider = assume_role_process_credentials_from_config(profile)) - [provider.credentials, %w[CREDENTIALS_PROFILE_SOURCE_PROFILE CREDENTIALS_PROFILE_PROCESS CREDENTIALS_PROCESS]] if provider.credentials.set? + [provider.credentials, provider.metrics] if provider.credentials.set? elsif (provider = sso_credentials_from_config(profile: profile)) [provider.credentials, provider.metrics] if provider.credentials.set? end @@ -359,7 +359,11 @@ def assume_role_process_credentials_from_config(profile) if @parsed_config credential_process ||= @parsed_config.fetch(profile, {})['credential_process'] end - ProcessCredentials.new([credential_process]) if credential_process + if credential_process + credentials = ProcessCredentials.new([credential_process]) + credentials.metrics = %w[CREDENTIALS_PROFILE_PROCESS CREDENTIALS_PROCESS] + credentials + end end def credentials_from_shared(profile, _opts) From 6df4fd676407dcf9f7d7f7384e16c9625dac2dcc Mon Sep 17 00:00:00 2001 From: Richard Wang Date: Mon, 24 Mar 2025 13:04:53 -0700 Subject: [PATCH 19/59] Add small fixes --- .../assume_role_web_identity_credentials.rb | 2 +- .../lib/aws-sdk-core/credential_provider_chain.rb | 2 +- gems/aws-sdk-core/lib/aws-sdk-core/shared_config.rb | 10 ++++++---- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_web_identity_credentials.rb b/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_web_identity_credentials.rb index 6a1b8302cf8..70d30e1b3ac 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_web_identity_credentials.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_web_identity_credentials.rb @@ -75,7 +75,7 @@ def refresh # read from token file everytime it refreshes @assume_role_web_identity_params[:web_identity_token] = _token_from_file(@token_file) - resp = client.assume_role_with_web_identity(@assume_role_web_identity_params) + resp = @client.assume_role_with_web_identity(@assume_role_web_identity_params) creds = resp.credentials @credentials = Credentials.new( creds.access_key_id, diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/credential_provider_chain.rb b/gems/aws-sdk-core/lib/aws-sdk-core/credential_provider_chain.rb index b2c6482285b..bc911ccd10d 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/credential_provider_chain.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/credential_provider_chain.rb @@ -240,7 +240,7 @@ def assume_role_web_identity_credentials(options) cfg = { role_arn: role_arn, web_identity_token_file: token_file, - role_session_name: ENV['AWS_ROLE_SESSION_NAME'], + role_session_name: ENV['AWS_ROLE_SESSION_NAME'] } cfg[:region] = region if region with_metrics('CREDENTIALS_ENV_VARS_STS_WEB_ID_TOKEN') do diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/shared_config.rb b/gems/aws-sdk-core/lib/aws-sdk-core/shared_config.rb index 70e3e6b4a9c..2f385297db1 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/shared_config.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/shared_config.rb @@ -135,7 +135,7 @@ def assume_role_web_identity_credentials_from_config(opts = {}) cfg = { role_arn: entry['role_arn'], web_identity_token_file: entry['web_identity_token_file'], - role_session_name: entry['role_session_name'], + role_session_name: entry['role_session_name'] } cfg[:region] = opts[:region] if opts[:region] with_metrics('CREDENTIALS_PROFILE_STS_WEB_ID_TOKEN') do @@ -262,6 +262,7 @@ def assume_role_from_profile(cfg, profile, opts, chain_config) opts[:credentials], metrics = with_metrics('CREDENTIALS_PROFILE_SOURCE_PROFILE') do resolve_source_profile(opts[:source_profile], opts) end + metrics.unshift('CREDENTIALS_PROFILE_SOURCE_PROFILE') if opts[:credentials] opts[:role_session_name] ||= prof_cfg['role_session_name'] opts[:role_session_name] ||= 'default_session' @@ -288,6 +289,7 @@ def assume_role_from_profile(cfg, profile, opts, chain_config) chain_config ) end + metrics.unshift('CREDENTIALS_PROFILE_NAMED_PROVIDER') if opts[:credentials] opts[:role_session_name] ||= prof_cfg['role_session_name'] opts[:role_session_name] ||= 'default_session' @@ -324,7 +326,7 @@ def resolve_source_profile(profile, opts = {}) end if (creds = credentials(profile: profile)) - [creds, %w[CREDENTIALS_PROFILE_SOURCE_PROFILE CREDENTIALS_PROFILE]] # static credentials + [creds, ['CREDENTIALS_PROFILE']] # static credentials elsif profile_config && profile_config['source_profile'] opts.delete(:source_profile) assume_role_credentials_from_config(opts.merge(profile: profile)) @@ -345,9 +347,9 @@ def credentials_from_source(credential_source, config) http_open_timeout: config ? config.instance_profile_credentials_timeout : 1, http_read_timeout: config ? config.instance_profile_credentials_timeout : 1, ), - %w[CREDENTIALS_PROFILE_NAMED_PROVIDER CREDENTIALS_IMDS]] + ['CREDENTIALS_IMDS']] when 'EcsContainer' - [ECSCredentials.new, %w[CREDENTIALS_PROFILE_NAMED_PROVIDER CREDENTIALS_HTTP]] + [ECSCredentials.new, ['CREDENTIALS_HTTP']] else raise Errors::InvalidCredentialSourceError, "Unsupported credential_source: #{credential_source}" end From af62fafaf42f1c28c846b91cac41ad5b930d85d8 Mon Sep 17 00:00:00 2001 From: Richard Wang Date: Mon, 24 Mar 2025 13:09:21 -0700 Subject: [PATCH 20/59] Add CHANGELOG entry --- gems/aws-sdk-core/CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/gems/aws-sdk-core/CHANGELOG.md b/gems/aws-sdk-core/CHANGELOG.md index c39a28c4603..2f36520a4cf 100644 --- a/gems/aws-sdk-core/CHANGELOG.md +++ b/gems/aws-sdk-core/CHANGELOG.md @@ -1,6 +1,8 @@ Unreleased Changes ------------------ +* Feature - Add feature id tracking for credentials. + 3.220.1 (2025-03-06) ------------------ From 5b7cf4b8672d0b342a81e8a3b6b160c498ec8e9d Mon Sep 17 00:00:00 2001 From: Richard Wang Date: Mon, 24 Mar 2025 13:57:48 -0700 Subject: [PATCH 21/59] Fix assume role logic --- .../lib/aws-sdk-core/assume_role_credentials.rb | 1 + gems/aws-sdk-core/lib/aws-sdk-core/plugins/sign.rb | 1 + .../aws-sdk-core/lib/aws-sdk-core/shared_config.rb | 14 +++++++++----- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_credentials.rb b/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_credentials.rb index 136be5ab34f..1ea0ea7ce08 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_credentials.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_credentials.rb @@ -64,6 +64,7 @@ def initialize(options = {}) private def refresh + puts "Refreshing credentials" resp = @client.assume_role(@assume_role_params) creds = resp.credentials @credentials = Credentials.new( diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/plugins/sign.rb b/gems/aws-sdk-core/lib/aws-sdk-core/plugins/sign.rb index 531aaac36d3..502b190c3c4 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/plugins/sign.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/plugins/sign.rb @@ -72,6 +72,7 @@ def with_metrics(credentials, &block) metrics << 'CREDENTIALS_CODE' else puts credentials.class.name + puts credentials.metrics (metrics << credentials.metrics).flatten! end Aws::Plugins::UserAgent.metric(*metrics, &block) diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/shared_config.rb b/gems/aws-sdk-core/lib/aws-sdk-core/shared_config.rb index 2f385297db1..a79bc6a6863 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/shared_config.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/shared_config.rb @@ -262,7 +262,6 @@ def assume_role_from_profile(cfg, profile, opts, chain_config) opts[:credentials], metrics = with_metrics('CREDENTIALS_PROFILE_SOURCE_PROFILE') do resolve_source_profile(opts[:source_profile], opts) end - metrics.unshift('CREDENTIALS_PROFILE_SOURCE_PROFILE') if opts[:credentials] opts[:role_session_name] ||= prof_cfg['role_session_name'] opts[:role_session_name] ||= 'default_session' @@ -272,9 +271,11 @@ def assume_role_from_profile(cfg, profile, opts, chain_config) opts[:serial_number] ||= prof_cfg['mfa_serial'] opts[:profile] = opts.delete(:source_profile) opts.delete(:visited_profiles) + metrics.unshift('CREDENTIALS_PROFILE_SOURCE_PROFILE') if metrics.first != 'CREDENTIALS_PROFILE_SOURCE_PROFILE' with_metrics(metrics) do credentials = AssumeRoleCredentials.new(opts) - credentials.metrics = metrics << 'CREDENTIALS_STS_ASSUME_ROLE' + metrics << 'CREDENTIALS_STS_ASSUME_ROLE' if metrics.last != 'CREDENTIALS_STS_ASSUME_ROLE' + credentials.metrics = metrics credentials end else @@ -289,7 +290,6 @@ def assume_role_from_profile(cfg, profile, opts, chain_config) chain_config ) end - metrics.unshift('CREDENTIALS_PROFILE_NAMED_PROVIDER') if opts[:credentials] opts[:role_session_name] ||= prof_cfg['role_session_name'] opts[:role_session_name] ||= 'default_session' @@ -298,9 +298,11 @@ def assume_role_from_profile(cfg, profile, opts, chain_config) opts[:external_id] ||= prof_cfg['external_id'] opts[:serial_number] ||= prof_cfg['mfa_serial'] opts.delete(:source_profile) # Cleanup + metrics.unshift('CREDENTIALS_PROFILE_NAMED_PROVIDER') if metrics.first != 'CREDENTIALS_PROFILE_NAMED_PROVIDER' with_metrics(metrics) do credentials = AssumeRoleCredentials.new(opts) - credentials.metrics = metrics << 'CREDENTIALS_STS_ASSUME_ROLE' + metrics << 'CREDENTIALS_STS_ASSUME_ROLE' if metrics.last != 'CREDENTIALS_STS_ASSUME_ROLE' + credentials.metrics = metrics credentials end else @@ -326,10 +328,12 @@ def resolve_source_profile(profile, opts = {}) end if (creds = credentials(profile: profile)) + creds.metrics = ['CREDENTIALS_PROFILE'] [creds, ['CREDENTIALS_PROFILE']] # static credentials elsif profile_config && profile_config['source_profile'] opts.delete(:source_profile) - assume_role_credentials_from_config(opts.merge(profile: profile)) + provider = assume_role_credentials_from_config(opts.merge(profile: profile)) + [provider, provider.metrics] elsif (provider = assume_role_web_identity_credentials_from_config(opts.merge(profile: profile))) [provider.credentials, provider.metrics] if provider.credentials.set? elsif (provider = assume_role_process_credentials_from_config(profile)) From 015ece2e0035d460e25bb754c215b83217660fb8 Mon Sep 17 00:00:00 2001 From: Richard Wang Date: Mon, 24 Mar 2025 14:07:00 -0700 Subject: [PATCH 22/59] Fix name --- gems/aws-sdk-core/lib/aws-sdk-core/shared_config.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/shared_config.rb b/gems/aws-sdk-core/lib/aws-sdk-core/shared_config.rb index a79bc6a6863..be01bdd1914 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/shared_config.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/shared_config.rb @@ -332,8 +332,8 @@ def resolve_source_profile(profile, opts = {}) [creds, ['CREDENTIALS_PROFILE']] # static credentials elsif profile_config && profile_config['source_profile'] opts.delete(:source_profile) - provider = assume_role_credentials_from_config(opts.merge(profile: profile)) - [provider, provider.metrics] + creds = assume_role_credentials_from_config(opts.merge(profile: profile)) + [creds, creds.metrics] elsif (provider = assume_role_web_identity_credentials_from_config(opts.merge(profile: profile))) [provider.credentials, provider.metrics] if provider.credentials.set? elsif (provider = assume_role_process_credentials_from_config(profile)) From 804826e5c16e7500008a284afaa1b77d05024f92 Mon Sep 17 00:00:00 2001 From: Richard Wang Date: Tue, 25 Mar 2025 08:42:49 -0700 Subject: [PATCH 23/59] Start to add test --- .../aws-sdk-core/assume_role_credentials.rb | 1 - .../lib/aws-sdk-core/plugins/sign.rb | 1 + .../spec/aws/plugins/user_agent_spec.rb | 23 +++++++++++++++++++ 3 files changed, 24 insertions(+), 1 deletion(-) diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_credentials.rb b/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_credentials.rb index 1ea0ea7ce08..136be5ab34f 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_credentials.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_credentials.rb @@ -64,7 +64,6 @@ def initialize(options = {}) private def refresh - puts "Refreshing credentials" resp = @client.assume_role(@assume_role_params) creds = resp.credentials @credentials = Credentials.new( diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/plugins/sign.rb b/gems/aws-sdk-core/lib/aws-sdk-core/plugins/sign.rb index 502b190c3c4..1af044ef341 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/plugins/sign.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/plugins/sign.rb @@ -69,6 +69,7 @@ def with_metrics(credentials, &block) metrics = [] if !credentials.metrics + puts "Credentials code" metrics << 'CREDENTIALS_CODE' else puts credentials.class.name diff --git a/gems/aws-sdk-core/spec/aws/plugins/user_agent_spec.rb b/gems/aws-sdk-core/spec/aws/plugins/user_agent_spec.rb index 31bc3be6fa6..6d6362587f5 100644 --- a/gems/aws-sdk-core/spec/aws/plugins/user_agent_spec.rb +++ b/gems/aws-sdk-core/spec/aws/plugins/user_agent_spec.rb @@ -112,6 +112,29 @@ def assert_header(expected, actual) end end end + + context 'credential providers' do + it 'includes the correct metrics for credentials defined in code' do + stub_const( + 'ENV', + 'AWS_ACCESS_KEY_ID' => 'AKID_ENV_STUB', + 'AWS_SECRET_ACCESS_KEY' => 'SECRET_ENV_STUB' + ) + client = ApiHelper.sample_service::Client.new( + access_key_id: 'ACCESS_DIRECT', + secret_access_key: 'SECRET_DIRECT', + profile: 'fooprofile', + region: 'us-east-1' + ) + puts client.config.credentials + client.stub_responses(:example_operation, {}) + resp = client.example_operation + puts resp.context.http_request.headers['User-Agent'] + expect(resp.context.http_request.headers['User-Agent']) + .to include('md/akid') + end + + end end end end From e17ba4d5a4c99aaa9022ee5acbe399fc31c0eea0 Mon Sep 17 00:00:00 2001 From: Richard Wang Date: Tue, 25 Mar 2025 12:44:01 -0700 Subject: [PATCH 24/59] Try source approach --- .../aws-sdk-core/assume_role_credentials.rb | 30 ++++++- .../assume_role_web_identity_credentials.rb | 13 +++- .../aws-sdk-core/credential_provider_chain.rb | 18 ++--- .../lib/aws-sdk-core/credentials.rb | 13 +++- .../lib/aws-sdk-core/ecs_credentials.rb | 8 +- .../instance_profile_credentials.rb | 8 +- .../lib/aws-sdk-core/plugins/sign.rb | 2 + .../lib/aws-sdk-core/plugins/user_agent.rb | 4 +- .../lib/aws-sdk-core/process_credentials.rb | 8 +- .../lib/aws-sdk-core/shared_config.rb | 78 +++++++++---------- .../lib/aws-sdk-core/shared_credentials.rb | 8 +- .../lib/aws-sdk-core/sso_credentials.rb | 13 +++- .../spec/aws/plugins/user_agent_spec.rb | 44 +++++------ 13 files changed, 166 insertions(+), 81 deletions(-) diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_credentials.rb b/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_credentials.rb index 136be5ab34f..7db7b413ee3 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_credentials.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_credentials.rb @@ -59,7 +59,31 @@ def initialize(options = {}) # @return [Hash] attr_reader :assume_role_params - attr_accessor :metrics + attr_accessor :source + + def metrics + nil unless @source + + source_profile = %w[CREDENTIALS_PROFILE_SOURCE_PROFILE CREDENTIALS_STS_ASSUME_ROLE] + credential_source = %w[CREDENTIALS_PROFILE_NAMED_PROVIDER CREDENTIALS_STS_ASSUME_ROLE] + + case @source + when :static + insert_metric(source_profile, 'CREDENTIALS_PROFILE') + when :webID + insert_metric(source_profile, %w[CREDENTIALS_PROFILE_STS_WEB_ID_TOKEN CREDENTIALS_STS_ASSUME_ROLE_WEB_ID]) + when :process + insert_metric(source_profile, %w[CREDENTIALS_PROFILE_PROCESS CREDENTIALS_PROCESS]) + when :new + insert_metric(source_profile, %w[CREDENTIALS_PROFILE_SSO CREDENTIALS_SSO]) + when :legacy + insert_metric(source_profile, %w[CREDENTIALS_PROFILE_SSO_LEGACY CREDENTIALS_SSO_LEGACY]) + when :instance + insert_metric(credential_source, 'CREDENTIALS_IMDS') + when :ecs + insert_metric(credential_source, 'CREDENTIALS_HTTP') + end + end private @@ -80,6 +104,10 @@ def parse_account_id(resp) ARNParser.parse(arn).account_id if ARNParser.arn?(arn) end + def insert_metric(base, metrics) + base.insert(1, *metrics) + end + class << self # @api private diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_web_identity_credentials.rb b/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_web_identity_credentials.rb index 70d30e1b3ac..765a9aae181 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_web_identity_credentials.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_web_identity_credentials.rb @@ -67,7 +67,18 @@ def initialize(options = {}) # @return [STS::Client] attr_reader :client - attr_accessor :metrics + attr_accessor :source + + def metrics + nil unless @source + + case @source + when :profile + %w[CREDENTIALS_PROFILE_STS_WEB_ID_TOKEN CREDENTIALS_STS_ASSUME_ROLE_WEB_ID] + when :env + %w[CREDENTIALS_ENV_VARS_STS_WEB_ID_TOKEN CREDENTIALS_STS_ASSUME_ROLE_WEB_ID] + end + end private diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/credential_provider_chain.rb b/gems/aws-sdk-core/lib/aws-sdk-core/credential_provider_chain.rb index bc911ccd10d..9f75426e2d6 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/credential_provider_chain.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/credential_provider_chain.rb @@ -118,7 +118,7 @@ def static_credentials(options) options[:config].session_token, account_id: options[:config].account_id ) - credentials.metrics = ['CREDENTIALS_PROFILE'] + credentials.source = :profile credentials end end @@ -149,7 +149,7 @@ def static_profile_assume_role_credentials(options) def static_profile_credentials(options) if options[:config] && options[:config].profile credentials = SharedCredentials.new(profile_name: options[:config].profile) - credentials.metrics = ['CREDENTIALS_PROFILE'] + credentials.source = :set credentials end rescue Errors::NoSuchProfileError @@ -161,7 +161,7 @@ def static_profile_process_credentials(options) process_provider = Aws.shared_config.credential_process(profile: options[:config].profile) if process_provider credentials = ProcessCredentials.new([process_provider]) - credentials.metrics = %w[CREDENTIALS_PROFILE_PROCESS CREDENTIALS_PROCESS] + credentials.source = :set credentials end end @@ -181,7 +181,7 @@ def env_credentials(_options) envar(token), account_id: envar(account_id) ) - credentials.metrics = ['CREDENTIALS_ENV_VARS'] + credentials.source = :env credentials end @@ -199,7 +199,7 @@ def determine_profile_name(options) def shared_credentials(options) profile_name = determine_profile_name(options) credentials = SharedCredentials.new(profile_name: profile_name) - credentials.metrics = ['CREDENTIALS_PROFILE'] + credentials.source = :set credentials rescue Errors::NoSuchProfileError nil @@ -211,7 +211,7 @@ def process_credentials(options) process_provider = Aws.shared_config.credential_process(profile: profile_name) if process_provider credentials = ProcessCredentials.new([process_provider]) - credentials.metrics = %w[CREDENTIALS_PROFILE_PROCESS CREDENTIALS_PROCESS] + credentials.source = :set credentials end end @@ -245,7 +245,7 @@ def assume_role_web_identity_credentials(options) cfg[:region] = region if region with_metrics('CREDENTIALS_ENV_VARS_STS_WEB_ID_TOKEN') do credentials = AssumeRoleWebIdentityCredentials.new(cfg) - credentials.metrics = %w[CREDENTIALS_ENV_VARS_STS_WEB_ID_TOKEN CREDENTIALS_STS_ASSUME_ROLE_WEB_ID] + credentials.source = :env credentials end elsif Aws.shared_config.config_enabled? @@ -262,11 +262,11 @@ def instance_profile_credentials(options) if ENV['AWS_CONTAINER_CREDENTIALS_RELATIVE_URI'] || ENV['AWS_CONTAINER_CREDENTIALS_FULL_URI'] credentials = ECSCredentials.new(options) - credentials.metrics = ['CREDENTIALS_HTTP'] + credentials.source = :set credentials else credentials = InstanceProfileCredentials.new(options.merge(profile: profile_name)) - credentials.metrics = ['CREDENTIALS_IMDS'] + credentials.source = :set credentials end end diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/credentials.rb b/gems/aws-sdk-core/lib/aws-sdk-core/credentials.rb index 4e642c1abf8..5f6f40dbad6 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/credentials.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/credentials.rb @@ -28,7 +28,7 @@ def initialize(access_key_id, secret_access_key, session_token = nil, # @return [String, nil] attr_reader :account_id - attr_accessor :metrics + attr_accessor :source # @return [Credentials] def credentials @@ -50,5 +50,16 @@ def inspect "#<#{self.class.name} access_key_id=#{access_key_id.inspect}>" end + def metrics + nil unless @source + + case @source + when :profile + ['CREDENTIALS_PROFILE'] + when :env + ['CREDENTIALS_ENV_VARS'] + end + end + end end diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/ecs_credentials.rb b/gems/aws-sdk-core/lib/aws-sdk-core/ecs_credentials.rb index 353442a06f2..8bcf87f31fa 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/ecs_credentials.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/ecs_credentials.rb @@ -84,7 +84,13 @@ def initialize(options = {}) # fetch credentials from the instance metadata service. Defaults to 0. attr_reader :retries - attr_accessor :metrics + attr_accessor :source + + def metrics + nil unless @source + + ['CREDENTIALS_HTTP'] + end private diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/instance_profile_credentials.rb b/gems/aws-sdk-core/lib/aws-sdk-core/instance_profile_credentials.rb index 72c2b08e42b..95862cbbd5a 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/instance_profile_credentials.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/instance_profile_credentials.rb @@ -98,7 +98,13 @@ def initialize(options = {}) # the default credential chain ({Aws::CredentialProviderChain}). attr_reader :retries - attr_accessor :metrics + attr_accessor :source + + def metrics + nil unless @source + + ['CREDENTIALS_IMDS'] + end private diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/plugins/sign.rb b/gems/aws-sdk-core/lib/aws-sdk-core/plugins/sign.rb index 1af044ef341..1dac1bc0f60 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/plugins/sign.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/plugins/sign.rb @@ -67,6 +67,8 @@ def with_metrics(credentials, &block) return block.call end + puts credentials + metrics = [] if !credentials.metrics puts "Credentials code" diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/plugins/user_agent.rb b/gems/aws-sdk-core/lib/aws-sdk-core/plugins/user_agent.rb index 6bba56137e0..64d2a884064 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/plugins/user_agent.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/plugins/user_agent.rb @@ -213,9 +213,11 @@ def metric_metadata end # Needed for AssumeRoleCredentials feature id tracking - Thread.current[:aws_sdk_core_user_agent_metric].uniq! + # Thread.current[:aws_sdk_core_user_agent_metric].uniq! metrics = Thread.current[:aws_sdk_core_user_agent_metric].join(',') + puts "User agent metrics" + puts metrics # Metric metadata is limited to 1024 bytes return "m/#{metrics}" if metrics.bytesize <= 1024 diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/process_credentials.rb b/gems/aws-sdk-core/lib/aws-sdk-core/process_credentials.rb index 0a85e0e0d9e..241dd5e49fc 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/process_credentials.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/process_credentials.rb @@ -40,7 +40,13 @@ def initialize(process) super end - attr_accessor :metrics + attr_accessor :source + + def metrics + nil unless @source + + %w[CREDENTIALS_PROFILE_PROCESS CREDENTIALS_PROCESS] + end private diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/shared_config.rb b/gems/aws-sdk-core/lib/aws-sdk-core/shared_config.rb index be01bdd1914..c96fc39a48a 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/shared_config.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/shared_config.rb @@ -140,7 +140,7 @@ def assume_role_web_identity_credentials_from_config(opts = {}) cfg[:region] = opts[:region] if opts[:region] with_metrics('CREDENTIALS_PROFILE_STS_WEB_ID_TOKEN') do credentials = AssumeRoleWebIdentityCredentials.new(cfg) - credentials.metrics = %w[CREDENTIALS_PROFILE_STS_WEB_ID_TOKEN CREDENTIALS_STS_ASSUME_ROLE_WEB_ID] + credentials.source = :profile credentials end end @@ -259,7 +259,7 @@ def assume_role_from_profile(cfg, profile, opts, chain_config) 'provide only source_profile or credential_source, not both.' elsif opts[:source_profile] opts[:visited_profiles] ||= Set.new - opts[:credentials], metrics = with_metrics('CREDENTIALS_PROFILE_SOURCE_PROFILE') do + opts[:credentials], provider, source = with_metrics('CREDENTIALS_PROFILE_SOURCE_PROFILE') do resolve_source_profile(opts[:source_profile], opts) end if opts[:credentials] @@ -271,11 +271,16 @@ def assume_role_from_profile(cfg, profile, opts, chain_config) opts[:serial_number] ||= prof_cfg['mfa_serial'] opts[:profile] = opts.delete(:source_profile) opts.delete(:visited_profiles) + puts opts[:credentials] + metrics = provider.metrics + puts metrics + # Add the AssumeRole metric to the front if it isn't there metrics.unshift('CREDENTIALS_PROFILE_SOURCE_PROFILE') if metrics.first != 'CREDENTIALS_PROFILE_SOURCE_PROFILE' + # Remove the service call metric if it's already there + metrics.pop if metrics.last == 'CREDENTIALS_STS_ASSUME_ROLE' with_metrics(metrics) do credentials = AssumeRoleCredentials.new(opts) - metrics << 'CREDENTIALS_STS_ASSUME_ROLE' if metrics.last != 'CREDENTIALS_STS_ASSUME_ROLE' - credentials.metrics = metrics + credentials.source = source credentials end else @@ -284,7 +289,7 @@ def assume_role_from_profile(cfg, profile, opts, chain_config) ' source_profile does not have credentials.' end elsif credential_source - opts[:credentials], metrics = with_metrics('CREDENTIALS_PROFILE_NAMED_PROVIDER') do + opts[:credentials], source = with_metrics('CREDENTIALS_PROFILE_NAMED_PROVIDER') do credentials_from_source( credential_source, chain_config @@ -298,11 +303,11 @@ def assume_role_from_profile(cfg, profile, opts, chain_config) opts[:external_id] ||= prof_cfg['external_id'] opts[:serial_number] ||= prof_cfg['mfa_serial'] opts.delete(:source_profile) # Cleanup + metrics = opts[:credentials].metrics metrics.unshift('CREDENTIALS_PROFILE_NAMED_PROVIDER') if metrics.first != 'CREDENTIALS_PROFILE_NAMED_PROVIDER' with_metrics(metrics) do credentials = AssumeRoleCredentials.new(opts) - metrics << 'CREDENTIALS_STS_ASSUME_ROLE' if metrics.last != 'CREDENTIALS_STS_ASSUME_ROLE' - credentials.metrics = metrics + credentials.source = source credentials end else @@ -328,18 +333,23 @@ def resolve_source_profile(profile, opts = {}) end if (creds = credentials(profile: profile)) - creds.metrics = ['CREDENTIALS_PROFILE'] - [creds, ['CREDENTIALS_PROFILE']] # static credentials + puts "Creds" + creds.source = :profile + [creds, creds, :static] # static credentials elsif profile_config && profile_config['source_profile'] + puts "assume" opts.delete(:source_profile) creds = assume_role_credentials_from_config(opts.merge(profile: profile)) - [creds, creds.metrics] + [creds, creds, creds.source] elsif (provider = assume_role_web_identity_credentials_from_config(opts.merge(profile: profile))) - [provider.credentials, provider.metrics] if provider.credentials.set? + puts "web" + [provider.credentials, provider, :webID] if provider.credentials.set? elsif (provider = assume_role_process_credentials_from_config(profile)) - [provider.credentials, provider.metrics] if provider.credentials.set? + puts "process" + [provider.credentials, provider, :process] if provider.credentials.set? elsif (provider = sso_credentials_from_config(profile: profile)) - [provider.credentials, provider.metrics] if provider.credentials.set? + puts "sso" + [provider.credentials, provider, provider.source] end end @@ -351,9 +361,9 @@ def credentials_from_source(credential_source, config) http_open_timeout: config ? config.instance_profile_credentials_timeout : 1, http_read_timeout: config ? config.instance_profile_credentials_timeout : 1, ), - ['CREDENTIALS_IMDS']] + :instance] when 'EcsContainer' - [ECSCredentials.new, ['CREDENTIALS_HTTP']] + [ECSCredentials.new, :ecs] else raise Errors::InvalidCredentialSourceError, "Unsupported credential_source: #{credential_source}" end @@ -367,7 +377,7 @@ def assume_role_process_credentials_from_config(profile) end if credential_process credentials = ProcessCredentials.new([credential_process]) - credentials.metrics = %w[CREDENTIALS_PROFILE_PROCESS CREDENTIALS_PROCESS] + credentials.source = :set credentials end end @@ -413,32 +423,18 @@ def sso_credentials_from_profile(cfg, profile) sso_start_url = prof_config['sso_start_url'] end - if prof_config['sso_session'] - with_metrics('CREDENTIALS_PROFILE_SSO') do - credentials = SSOCredentials.new( - sso_account_id: prof_config['sso_account_id'], - sso_role_name: prof_config['sso_role_name'], - sso_session: prof_config['sso_session'], - sso_region: sso_region, - sso_start_url: sso_start_url, - ) - credentials.metrics = %w[CREDENTIALS_PROFILE_SSO CREDENTIALS_SSO] - credentials - end - else - with_metrics('CREDENTIALS_PROFILE_SSO_LEGACY') do - credentials = SSOCredentials.new( - sso_account_id: prof_config['sso_account_id'], - sso_role_name: prof_config['sso_role_name'], - sso_session: prof_config['sso_session'], - sso_region: sso_region, - sso_start_url: sso_start_url, - ) - credentials.metrics = %w[CREDENTIALS_PROFILE_SSO_LEGACY CREDENTIALS_SSO_LEGACY] - credentials - end + metric = prof_config['sso_session'] ? 'CREDENTIALS_PROFILE_SSO' : 'CREDENTIALS_PROFILE_SSO_LEGACY' + with_metrics(metric) do + credentials = SSOCredentials.new( + sso_account_id: prof_config['sso_account_id'], + sso_role_name: prof_config['sso_role_name'], + sso_session: prof_config['sso_session'], + sso_region: sso_region, + sso_start_url: sso_start_url, + ) + credentials.source = prof_config['sso_session'] ? :new : :legacy + credentials end - end end diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/shared_credentials.rb b/gems/aws-sdk-core/lib/aws-sdk-core/shared_credentials.rb index 141a0003e3a..9289e7ea10f 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/shared_credentials.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/shared_credentials.rb @@ -51,7 +51,7 @@ def initialize(options = {}) # @return [Credentials] attr_reader :credentials - attr_accessor :metrics + attr_accessor :source # @api private def inspect @@ -63,6 +63,12 @@ def inspect "#<#{parts.join(' ')}>" end + def metrics + nil unless @source + + ['CREDENTIALS_PROFILE'] + end + # @deprecated This method is no longer used. # @return [Boolean] Returns `true` if a credential file # exists and has appropriate read permissions at {#path}. diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/sso_credentials.rb b/gems/aws-sdk-core/lib/aws-sdk-core/sso_credentials.rb index c41e8e5951b..08eec87812a 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/sso_credentials.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/sso_credentials.rb @@ -120,7 +120,7 @@ def initialize(options = {}) # @return [SSO::Client] attr_reader :client - attr_accessor :metrics + attr_accessor :source private @@ -171,5 +171,16 @@ def sso_cache_file # Dir.home raises ArgumentError when ENV['home'] is not set raise ArgumentError, "Unable to load sso_cache_file: ENV['HOME'] is not set." end + + def metrics + nil unless @source + + case @source + when :new + %w[CREDENTIALS_PROFILE_SSO CREDENTIALS_SSO] + when :legacy + %w[CREDENTIALS_PROFILE_SSO_LEGACY CREDENTIALS_SSO_LEGACY] + end + end end end diff --git a/gems/aws-sdk-core/spec/aws/plugins/user_agent_spec.rb b/gems/aws-sdk-core/spec/aws/plugins/user_agent_spec.rb index 6d6362587f5..7e76969ca06 100644 --- a/gems/aws-sdk-core/spec/aws/plugins/user_agent_spec.rb +++ b/gems/aws-sdk-core/spec/aws/plugins/user_agent_spec.rb @@ -113,28 +113,28 @@ def assert_header(expected, actual) end end - context 'credential providers' do - it 'includes the correct metrics for credentials defined in code' do - stub_const( - 'ENV', - 'AWS_ACCESS_KEY_ID' => 'AKID_ENV_STUB', - 'AWS_SECRET_ACCESS_KEY' => 'SECRET_ENV_STUB' - ) - client = ApiHelper.sample_service::Client.new( - access_key_id: 'ACCESS_DIRECT', - secret_access_key: 'SECRET_DIRECT', - profile: 'fooprofile', - region: 'us-east-1' - ) - puts client.config.credentials - client.stub_responses(:example_operation, {}) - resp = client.example_operation - puts resp.context.http_request.headers['User-Agent'] - expect(resp.context.http_request.headers['User-Agent']) - .to include('md/akid') - end - - end + # context 'credential providers' do + # it 'includes the correct metrics for credentials defined in code' do + # stub_const( + # 'ENV', + # 'AWS_ACCESS_KEY_ID' => 'AKID_ENV_STUB', + # 'AWS_SECRET_ACCESS_KEY' => 'SECRET_ENV_STUB' + # ) + # client = ApiHelper.sample_service::Client.new( + # access_key_id: 'ACCESS_DIRECT', + # secret_access_key: 'SECRET_DIRECT', + # profile: 'fooprofile', + # region: 'us-east-1' + # ) + # puts client.config.credentials + # client.stub_responses(:example_operation, {}) + # resp = client.example_operation + # puts resp.context.http_request.headers['User-Agent'] + # expect(resp.context.http_request.headers['User-Agent']) + # .to include('md/akid') + # end + # + # end end end end From 01eca88c954eeae7399fcdfad287c7ca76f61a16 Mon Sep 17 00:00:00 2001 From: Richard Wang Date: Tue, 25 Mar 2025 13:23:24 -0700 Subject: [PATCH 25/59] Partially fix extra metrics issue --- gems/aws-sdk-core/lib/aws-sdk-core/credentials.rb | 2 ++ gems/aws-sdk-core/lib/aws-sdk-core/shared_config.rb | 6 +++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/credentials.rb b/gems/aws-sdk-core/lib/aws-sdk-core/credentials.rb index 5f6f40dbad6..0c49375e770 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/credentials.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/credentials.rb @@ -58,6 +58,8 @@ def metrics ['CREDENTIALS_PROFILE'] when :env ['CREDENTIALS_ENV_VARS'] + when :assume_role_resolution + [] end end diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/shared_config.rb b/gems/aws-sdk-core/lib/aws-sdk-core/shared_config.rb index c96fc39a48a..11de70ab3d6 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/shared_config.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/shared_config.rb @@ -271,13 +271,14 @@ def assume_role_from_profile(cfg, profile, opts, chain_config) opts[:serial_number] ||= prof_cfg['mfa_serial'] opts[:profile] = opts.delete(:source_profile) opts.delete(:visited_profiles) + puts "In assume role" puts opts[:credentials] metrics = provider.metrics - puts metrics # Add the AssumeRole metric to the front if it isn't there metrics.unshift('CREDENTIALS_PROFILE_SOURCE_PROFILE') if metrics.first != 'CREDENTIALS_PROFILE_SOURCE_PROFILE' # Remove the service call metric if it's already there metrics.pop if metrics.last == 'CREDENTIALS_STS_ASSUME_ROLE' + puts metrics with_metrics(metrics) do credentials = AssumeRoleCredentials.new(opts) credentials.source = source @@ -343,12 +344,15 @@ def resolve_source_profile(profile, opts = {}) [creds, creds, creds.source] elsif (provider = assume_role_web_identity_credentials_from_config(opts.merge(profile: profile))) puts "web" + provider.credentials.source = :assume_role_resolution [provider.credentials, provider, :webID] if provider.credentials.set? elsif (provider = assume_role_process_credentials_from_config(profile)) puts "process" + provider.credentials.source = :assume_role_resolution [provider.credentials, provider, :process] if provider.credentials.set? elsif (provider = sso_credentials_from_config(profile: profile)) puts "sso" + provider.credentials.source = :assume_role_resolution [provider.credentials, provider, provider.source] end end From 0299ccdb98211b08bba3ca581c3f8e86b1b14e1b Mon Sep 17 00:00:00 2001 From: Richard Wang Date: Wed, 26 Mar 2025 08:48:15 -0700 Subject: [PATCH 26/59] Fix extra 'i' metric error --- .../lib/aws-sdk-core/assume_role_credentials.rb | 7 +++++++ gems/aws-sdk-core/lib/aws-sdk-core/shared_config.rb | 5 ++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_credentials.rb b/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_credentials.rb index 7db7b413ee3..40c1ba5013a 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_credentials.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_credentials.rb @@ -61,12 +61,19 @@ def initialize(options = {}) attr_accessor :source + attr_accessor :resolving + def metrics nil unless @source source_profile = %w[CREDENTIALS_PROFILE_SOURCE_PROFILE CREDENTIALS_STS_ASSUME_ROLE] credential_source = %w[CREDENTIALS_PROFILE_NAMED_PROVIDER CREDENTIALS_STS_ASSUME_ROLE] + if @resolving + source_profile.pop + credential_source.pop + end + case @source when :static insert_metric(source_profile, 'CREDENTIALS_PROFILE') diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/shared_config.rb b/gems/aws-sdk-core/lib/aws-sdk-core/shared_config.rb index 11de70ab3d6..768195eb969 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/shared_config.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/shared_config.rb @@ -277,7 +277,10 @@ def assume_role_from_profile(cfg, profile, opts, chain_config) # Add the AssumeRole metric to the front if it isn't there metrics.unshift('CREDENTIALS_PROFILE_SOURCE_PROFILE') if metrics.first != 'CREDENTIALS_PROFILE_SOURCE_PROFILE' # Remove the service call metric if it's already there - metrics.pop if metrics.last == 'CREDENTIALS_STS_ASSUME_ROLE' + if metrics.last == 'CREDENTIALS_STS_ASSUME_ROLE' + metrics.pop + opts[:credentials].resolving = true + end puts metrics with_metrics(metrics) do credentials = AssumeRoleCredentials.new(opts) From 1dda7e2090431fe0ba8aac2e4f6af814b56935d1 Mon Sep 17 00:00:00 2001 From: Richard Wang Date: Wed, 26 Mar 2025 09:28:30 -0700 Subject: [PATCH 27/59] Fix some tests --- .../aws-sdk-core/assume_role_credentials.rb | 2 + .../assume_role_web_identity_credentials.rb | 2 + .../lib/aws-sdk-core/plugins/user_agent.rb | 2 +- .../lib/aws-sdk-core/sso_credentials.rb | 2 + .../aws/credential_provider_chain_spec.rb | 23 +++ .../aws/credential_resolution_chain_spec.rb | 150 +++++++++++++----- 6 files changed, 144 insertions(+), 37 deletions(-) diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_credentials.rb b/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_credentials.rb index 40c1ba5013a..3d03effc6ec 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_credentials.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_credentials.rb @@ -95,7 +95,9 @@ def metrics private def refresh + puts "AssumeRole refreshing" resp = @client.assume_role(@assume_role_params) + puts "AssumeRole refreshed" creds = resp.credentials @credentials = Credentials.new( creds.access_key_id, diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_web_identity_credentials.rb b/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_web_identity_credentials.rb index 765a9aae181..76d942fc263 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_web_identity_credentials.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_web_identity_credentials.rb @@ -86,7 +86,9 @@ def refresh # read from token file everytime it refreshes @assume_role_web_identity_params[:web_identity_token] = _token_from_file(@token_file) + puts "Web ID refreshing" resp = @client.assume_role_with_web_identity(@assume_role_web_identity_params) + puts "Web ID refreshed" creds = resp.credentials @credentials = Credentials.new( creds.access_key_id, diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/plugins/user_agent.rb b/gems/aws-sdk-core/lib/aws-sdk-core/plugins/user_agent.rb index 64d2a884064..37f36a6bb17 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/plugins/user_agent.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/plugins/user_agent.rb @@ -213,7 +213,7 @@ def metric_metadata end # Needed for AssumeRoleCredentials feature id tracking - # Thread.current[:aws_sdk_core_user_agent_metric].uniq! + Thread.current[:aws_sdk_core_user_agent_metric].uniq! metrics = Thread.current[:aws_sdk_core_user_agent_metric].join(',') puts "User agent metrics" diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/sso_credentials.rb b/gems/aws-sdk-core/lib/aws-sdk-core/sso_credentials.rb index 08eec87812a..0dac2bea75c 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/sso_credentials.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/sso_credentials.rb @@ -140,6 +140,7 @@ def read_cached_token end def refresh + puts "SSO refreshing" c = if @legacy cached_token = read_cached_token @client.get_role_credentials( @@ -154,6 +155,7 @@ def refresh access_token: @token_provider.token.token ).role_credentials end + puts "SSO refreshed" @credentials = Credentials.new( c.access_key_id, diff --git a/gems/aws-sdk-core/spec/aws/credential_provider_chain_spec.rb b/gems/aws-sdk-core/spec/aws/credential_provider_chain_spec.rb index 89debf334b8..5527478726d 100644 --- a/gems/aws-sdk-core/spec/aws/credential_provider_chain_spec.rb +++ b/gems/aws-sdk-core/spec/aws/credential_provider_chain_spec.rb @@ -59,6 +59,10 @@ def validate_credentials(expected_creds) expect(creds.account_id).to eq(expected_creds[:account_id]) end + def validate_metrics(expected_metrics) + expect(credentials.metrics).to eq(expected_metrics) + end + let(:config) do double('config', access_key_id: nil, @@ -79,11 +83,14 @@ def validate_credentials(expected_creds) before(:each) do allow(InstanceProfileCredentials).to receive(:new).and_return(mock_instance_creds) + allow(mock_instance_creds).to receive(:source=).with(:set) + allow(mock_instance_creds).to receive(:metrics).and_return(['CREDENTIALS_IMDS']) end it 'hydrates credentials from config options' do expected_creds = with_config_credentials validate_credentials(expected_creds) + validate_metrics(['CREDENTIALS_PROFILE']) end it 'hydrates credentials from ENV with prefix AWS_' do @@ -93,6 +100,7 @@ def validate_credentials(expected_creds) ENV['AWS_SESSION_TOKEN'] = expected_creds[:session_token] ENV['AWS_ACCOUNT_ID'] = expected_creds[:account_id] validate_credentials(expected_creds) + validate_metrics(['CREDENTIALS_ENV_VARS']) end it 'hydrates credentials from ENV with prefix AMAZON_' do @@ -101,6 +109,7 @@ def validate_credentials(expected_creds) ENV['AMAZON_SECRET_ACCESS_KEY'] = expected_creds[:secret_access_key] ENV['AMAZON_SESSION_TOKEN'] = expected_creds[:session_token] validate_credentials(expected_creds) + validate_metrics(['CREDENTIALS_ENV_VARS']) end it 'hydrates credentials from ENV at AWS_ACCESS_KEY & AWS_SECRET_KEY' do @@ -108,6 +117,7 @@ def validate_credentials(expected_creds) ENV['AWS_ACCESS_KEY'] = expected_creds[:access_key_id] ENV['AWS_SECRET_KEY'] = expected_creds[:secret_access_key] validate_credentials(expected_creds) + validate_metrics(['CREDENTIALS_ENV_VARS']) end it 'hydrates credentials from ENV at AWS_ACCESS_KEY_ID & AWS_SECRET_KEY' do @@ -115,27 +125,35 @@ def validate_credentials(expected_creds) ENV['AWS_ACCESS_KEY_ID'] = expected_creds[:access_key_id] ENV['AWS_SECRET_KEY'] = expected_creds[:secret_access_key] validate_credentials(expected_creds) + validate_metrics(['CREDENTIALS_ENV_VARS']) end it 'hydrates credentials from the instance profile service' do expect(mock_instance_creds).to receive(:set?).and_return(true) expect(credentials).to be(mock_instance_creds) + validate_metrics(['CREDENTIALS_IMDS']) end it 'hydrates credentials from ECS when AWS_CONTAINER_CREDENTIALS_RELATIVE_URI is set' do ENV['AWS_CONTAINER_CREDENTIALS_RELATIVE_URI'] = 'test_uri' mock_ecs_creds = double('ECSCredentials') + allow(mock_ecs_creds).to receive(:source=).with(:set) + allow(mock_ecs_creds).to receive(:metrics).and_return(['CREDENTIALS_HTTP']) expect(ECSCredentials).to receive(:new).and_return(mock_ecs_creds) expect(mock_ecs_creds).to receive(:set?).and_return(true) expect(credentials).to be(mock_ecs_creds) + validate_metrics(['CREDENTIALS_HTTP']) end it 'hydrates credentials from ECS when AWS_CONTAINER_CREDENTIALS_FULL_URI is set' do ENV['AWS_CONTAINER_CREDENTIALS_FULL_URI'] = 'test_uri' mock_ecs_creds = double('ECSCredentials') + allow(mock_ecs_creds).to receive(:source=).with(:set) + allow(mock_ecs_creds).to receive(:metrics).and_return(['CREDENTIALS_HTTP']) expect(ECSCredentials).to receive(:new).and_return(mock_ecs_creds) expect(mock_ecs_creds).to receive(:set?).and_return(true) expect(credentials).to be(mock_ecs_creds) + validate_metrics(['CREDENTIALS_HTTP']) end describe 'with config set to nil' do @@ -161,6 +179,7 @@ def validate_credentials(expected_creds) expected_creds = with_shared_credentials('test') ENV['AWS_DEFAULT_PROFILE'] = expected_creds[:profile_name] validate_credentials(expected_creds) + validate_metrics(['CREDENTIALS_PROFILE']) end it 'returns credentials from proper profile when config is set' do @@ -168,6 +187,7 @@ def validate_credentials(expected_creds) allow(config).to receive(:profile).and_return(expected_creds[:profile_name]) ENV['AWS_DEFAULT_PROFILE'] = 'BAD_PROFILE' validate_credentials(expected_creds) + validate_metrics(['CREDENTIALS_PROFILE']) end end @@ -177,12 +197,14 @@ def validate_credentials(expected_creds) ENV['AWS_DEFAULT_PROFILE'] = shared_creds[:profile_name] expected_creds = with_env_credentials validate_credentials(expected_creds) + validate_metrics(['CREDENTIALS_ENV_VARS']) end it 'hydrates credentials from config over ENV' do env_creds = with_env_credentials expected_creds = with_config_credentials validate_credentials(expected_creds) + validate_metrics(['CREDENTIALS_PROFILE']) end it 'hydrates credentials from profile when config set over ENV' do @@ -190,6 +212,7 @@ def validate_credentials(expected_creds) allow(config).to receive(:profile).and_return(expected_creds[:profile_name]) env_creds = with_env_credentials validate_credentials(expected_creds) + validate_metrics(['CREDENTIALS_PROFILE']) end end end diff --git a/gems/aws-sdk-core/spec/aws/credential_resolution_chain_spec.rb b/gems/aws-sdk-core/spec/aws/credential_resolution_chain_spec.rb index f628d9ddc1c..9b92dace383 100644 --- a/gems/aws-sdk-core/spec/aws/credential_resolution_chain_spec.rb +++ b/gems/aws-sdk-core/spec/aws/credential_resolution_chain_spec.rb @@ -31,7 +31,7 @@ module Aws before(:each) do allow(InstanceProfileCredentials).to receive(:new).and_return(mock_instance_creds) - + allow(mock_instance_creds).to receive(:source=) expect_any_instance_of(ProcessCredentials).not_to receive(:warn) end @@ -59,6 +59,7 @@ module Aws region: 'us-east-1' ) expect(client.config.credentials.access_key_id).to eq('ACCESS_DIRECT') + expect(client.config.credentials.metrics).to eq(['CREDENTIALS_PROFILE']) end it 'prefers assume role credentials when profile explicitly set over ENV credentials' do @@ -78,6 +79,9 @@ module Aws profile: 'assumerole_sc', region: 'us-east-1' ) expect(client.config.credentials.credentials.access_key_id).to eq('AR_AKID') + expect( + client.config.credentials.metrics + ).to eq(%w[CREDENTIALS_PROFILE_SOURCE_PROFILE CREDENTIALS_PROFILE CREDENTIALS_STS_ASSUME_ROLE]) end it 'prefers assume role web identity over sso' do @@ -93,22 +97,22 @@ module Aws expect( client.config.credentials.credentials.access_key_id ).to eq('AR_AKID') + expect( + client.config.credentials.metrics + ).to eq(%w[CREDENTIALS_PROFILE_STS_WEB_ID_TOKEN CREDENTIALS_STS_ASSUME_ROLE_WEB_ID]) end it 'prefers sso credentials over assume role' do + creds = double('creds', set?: true, credentials: double(access_key_id: 'SSO_AKID')) + allow(creds).to receive(:metrics).and_return(%w[CREDENTIALS_PROFILE_SSO CREDENTIALS_SSO]) expect(SSOCredentials).to receive(:new).with( sso_start_url: 'START_URL', sso_region: 'us-east-1', sso_account_id: 'SSO_ACCOUNT_ID', sso_role_name: 'SSO_ROLE_NAME', sso_session: 'sso-test-session' - ).and_return( - double( - 'creds', - set?: true, - credentials: double(access_key_id: 'SSO_AKID') - ) - ) + ).and_return(creds) + expect(creds).to receive(:source=).with(:new) client = ApiHelper.sample_rest_xml::Client.new( profile: 'sso_creds', token_provider: nil @@ -116,44 +120,44 @@ module Aws expect( client.config.credentials.credentials.access_key_id ).to eq('SSO_AKID') + expect( + client.config.credentials.metrics + ).to eq(%w[CREDENTIALS_PROFILE_SSO CREDENTIALS_SSO]) end it 'loads SSO credentials from a legacy profile' do + creds = double('creds', set?: true, credentials: double(access_key_id: 'SSO_AKID')) + allow(creds).to receive(:metrics).and_return(%w[CREDENTIALS_PROFILE_SSO_LEGACY CREDENTIALS_SSO_LEGACY]) expect(SSOCredentials).to receive(:new).with( sso_start_url: 'START_URL', sso_region: 'us-east-1', sso_account_id: 'SSO_ACCOUNT_ID', sso_role_name: 'SSO_ROLE_NAME', sso_session: nil - ).and_return( - double( - 'creds', - set?: true, - credentials: double(access_key_id: 'SSO_AKID') - ) - ) + ).and_return(creds) + expect(creds).to receive(:source=).with(:legacy) client = ApiHelper.sample_rest_xml::Client.new( profile: 'sso_creds_legacy' ) expect( client.config.credentials.credentials.access_key_id ).to eq('SSO_AKID') + expect( + client.config.credentials.metrics + ).to eq(%w[CREDENTIALS_PROFILE_SSO_LEGACY CREDENTIALS_SSO_LEGACY]) end it 'loads SSO credentials from a mixed legacy profile when values match' do + creds = double('creds', set?: true, credentials: double(access_key_id: 'SSO_AKID')) + allow(creds).to receive(:metrics).and_return(%w[CREDENTIALS_PROFILE_SSO CREDENTIALS_SSO]) expect(SSOCredentials).to receive(:new).with( sso_start_url: 'START_URL', sso_region: 'us-east-1', sso_account_id: 'SSO_ACCOUNT_ID', sso_role_name: 'SSO_ROLE_NAME', sso_session: 'sso-test-session' - ).and_return( - double( - 'creds', - set?: true, - credentials: double(access_key_id: 'SSO_AKID') - ) - ) + ).and_return(creds) + expect(creds).to receive(:source=).with(:new) client = ApiHelper.sample_rest_xml::Client.new( profile: 'sso_creds_mixed_legacy', token_provider: nil, @@ -161,22 +165,22 @@ module Aws expect( client.config.credentials.credentials.access_key_id ).to eq('SSO_AKID') + expect( + client.config.credentials.metrics + ).to eq(%w[CREDENTIALS_PROFILE_SSO CREDENTIALS_SSO]) end it 'loads SSO credentials from when the session name has quotes' do + creds = double('creds', set?: true, credentials: double(access_key_id: 'SSO_AKID')) + allow(creds).to receive(:metrics).and_return(%w[CREDENTIALS_PROFILE_SSO CREDENTIALS_SSO]) expect(SSOCredentials).to receive(:new).with( sso_start_url: 'START_URL', sso_region: 'us-east-1', sso_account_id: 'SSO_ACCOUNT_ID', sso_role_name: 'SSO_ROLE_NAME', sso_session: 'sso test session' - ).and_return( - double( - 'creds', - set?: true, - credentials: double(access_key_id: 'SSO_AKID') - ) - ) + ).and_return(creds) + expect(creds).to receive(:source=).with(:new) client = ApiHelper.sample_rest_xml::Client.new( profile: 'sso_creds_session_with_quotes', token_provider: nil @@ -184,6 +188,9 @@ module Aws expect( client.config.credentials.credentials.access_key_id ).to eq('SSO_AKID') + expect( + client.config.credentials.metrics + ).to eq(%w[CREDENTIALS_PROFILE_SSO CREDENTIALS_SSO]) end it 'raises when attempting to load an incomplete SSO Profile' do @@ -230,6 +237,10 @@ module Aws client.config.credentials.credentials.access_key_id ).to eq('AR_AKID') + expect( + client.config.credentials.metrics + ).to eq(%w[CREDENTIALS_PROFILE_SOURCE_PROFILE CREDENTIALS_PROFILE CREDENTIALS_STS_ASSUME_ROLE]) + sts_client = client.config.credentials.client expect( sts_client.config.region @@ -243,6 +254,9 @@ module Aws expect( client.config.credentials.credentials.access_key_id ).to eq('ACCESS_KEY_CRD') + expect( + client.config.credentials.metrics + ).to eq(['CREDENTIALS_PROFILE']) end it 'will source static credentials from shared config after shared credentials' do @@ -252,6 +266,9 @@ module Aws expect( client.config.credentials.credentials.access_key_id ).to eq('ACCESS_KEY_SC1') + expect( + client.config.credentials.metrics + ).to eq(['CREDENTIALS_PROFILE']) end it 'prefers process credentials over metadata credentials' do @@ -261,6 +278,9 @@ module Aws expect( client.config.credentials.credentials.access_key_id ).to eq('AK_PROC1') + expect( + client.config.credentials.metrics + ).to eq(%w[CREDENTIALS_PROFILE_PROCESS CREDENTIALS_PROCESS]) end it 'prefers direct credentials over process credentials when profile not set' do @@ -275,6 +295,9 @@ module Aws expect( client.config.credentials.credentials.access_key_id ).to eq('AKID_ENV_STUB') + expect( + client.config.credentials.metrics + ).to eq(['CREDENTIALS_ENV_VARS']) end it 'prefers process credentials from direct profile over env' do @@ -289,6 +312,9 @@ module Aws expect( client.config.credentials.credentials.access_key_id ).to eq('AK_PROC1') + expect( + client.config.credentials.metrics + ).to eq(%w[CREDENTIALS_PROFILE_PROCESS CREDENTIALS_PROCESS]) end it 'attempts to fetch metadata credentials last' do @@ -326,6 +352,9 @@ module Aws expect( client.config.credentials.credentials.access_key_id ).to eq('akid-md') + expect( + client.config.credentials.metrics + ).to eq(['CREDENTIALS_IMDS']) end describe 'Assume Role Resolution' do @@ -365,6 +394,10 @@ module Aws expect( client.config.credentials.credentials.access_key_id ).to eq('AR_AKID') + expect( + client.config.credentials.metrics + ).to eq(%w[CREDENTIALS_PROFILE_SOURCE_PROFILE CREDENTIALS_PROFILE_STS_WEB_ID_TOKEN + CREDENTIALS_STS_ASSUME_ROLE_WEB_ID CREDENTIALS_STS_ASSUME_ROLE]) sts_client = client.config.credentials.client expect( @@ -387,22 +420,24 @@ module Aws expect( client.config.credentials.credentials.access_key_id ).to eq('AK_PROC1') + expect( + client.config.credentials.metrics + ).to eq(%w[CREDENTIALS_PROFILE_SOURCE_PROFILE CREDENTIALS_PROFILE_PROCESS CREDENTIALS_PROCESS + CREDENTIALS_STS_ASSUME_ROLE]) end it 'supports :source_profile from sso credentials' do + creds = double('creds', set?: true, credentials: Credentials.new('SSO_AKID', 'sak')) + allow(creds).to receive(:metrics).and_return(%w[CREDENTIALS_PROFILE_SSO CREDENTIALS_SSO]) expect(SSOCredentials).to receive(:new).with( sso_start_url: 'START_URL', sso_region: 'us-east-1', sso_account_id: 'SSO_ACCOUNT_ID', sso_role_name: 'SSO_ROLE_NAME', sso_session: 'sso-test-session' - ).and_return( - double( - 'SSOCreds', - set?: true, - credentials: Credentials.new('SSO_AKID', 'sak') - ) - ) + ).and_return(creds) + expect(creds).to receive(:source=).with(:new) + expect(creds).to receive(:source).and_return(:new) allow(SSOTokenProvider).to receive(:new) .and_return(double('SSOToken', set?: true)) @@ -421,6 +456,10 @@ module Aws expect( client.config.credentials.credentials.access_key_id ).to eq('AR_AKID') + expect( + client.config.credentials.metrics + ).to eq(%w[CREDENTIALS_PROFILE_SOURCE_PROFILE CREDENTIALS_PROFILE_SSO CREDENTIALS_SSO + CREDENTIALS_STS_ASSUME_ROLE]) end it 'supports assume role chaining' do @@ -446,6 +485,9 @@ module Aws expect( client.config.credentials.credentials.access_key_id ).to eq('AK_2') + expect( + client.config.credentials.metrics + ).to eq(%w[CREDENTIALS_PROFILE_SOURCE_PROFILE CREDENTIALS_PROFILE CREDENTIALS_STS_ASSUME_ROLE]) end it 'uses source credentials when source and static are both set' do @@ -463,6 +505,9 @@ module Aws expect( client.config.credentials.credentials.access_key_id ).to eq('AK_2') + expect( + client.config.credentials.metrics + ).to eq(%w[CREDENTIALS_PROFILE_SOURCE_PROFILE CREDENTIALS_PROFILE CREDENTIALS_STS_ASSUME_ROLE]) end it 'uses static credentials when the profile self references' do @@ -480,6 +525,9 @@ module Aws expect( client.config.credentials.credentials.access_key_id ).to eq('AK_2') + expect( + client.config.credentials.metrics + ).to eq(%w[CREDENTIALS_PROFILE_SOURCE_PROFILE CREDENTIALS_PROFILE CREDENTIALS_STS_ASSUME_ROLE]) end it 'raises if there is a loop in chained profiles' do @@ -521,6 +569,9 @@ module Aws expect( client.config.credentials.credentials.access_key_id ).to eq('AR_AKID') + expect( + client.config.credentials.metrics + ).to eq(%w[CREDENTIALS_PROFILE_SOURCE_PROFILE CREDENTIALS_PROFILE CREDENTIALS_STS_ASSUME_ROLE]) end it 'will then try to assume a role from shared config' do @@ -537,6 +588,9 @@ module Aws expect( client.config.credentials.credentials.access_key_id ).to eq('AR_AKID') + expect( + client.config.credentials.metrics + ).to eq(%w[CREDENTIALS_PROFILE_SOURCE_PROFILE CREDENTIALS_PROFILE CREDENTIALS_STS_ASSUME_ROLE]) end it 'assumes a role from config using source in shared credentials' do @@ -553,6 +607,9 @@ module Aws expect( client.config.credentials.credentials.access_key_id ).to eq('AR_AKID') + expect( + client.config.credentials.metrics + ).to eq(%w[CREDENTIALS_PROFILE_SOURCE_PROFILE CREDENTIALS_PROFILE CREDENTIALS_STS_ASSUME_ROLE]) end it 'allows region to be resolved when unspecified' do @@ -573,6 +630,9 @@ module Aws expect( credentials.credentials.access_key_id ).to eq('AR_AKID') + expect( + credentials.metrics + ).to eq(%w[CREDENTIALS_PROFILE_SOURCE_PROFILE CREDENTIALS_PROFILE CREDENTIALS_STS_ASSUME_ROLE]) end end @@ -617,6 +677,9 @@ module Aws expect( client.config.credentials.credentials.access_key_id ).to eq('AR_AKID') + expect( + client.config.credentials.metrics + ).to eq(%w[CREDENTIALS_PROFILE_NAMED_PROVIDER CREDENTIALS_IMDS CREDENTIALS_STS_ASSUME_ROLE]) end it 'can assume a role with ECS Credentials as a source' do @@ -649,6 +712,9 @@ module Aws expect( client.config.credentials.credentials.access_key_id ).to eq('AR_AKID') + expect( + client.config.credentials.metrics + ).to eq(%w[CREDENTIALS_PROFILE_NAMED_PROVIDER CREDENTIALS_HTTP CREDENTIALS_STS_ASSUME_ROLE]) end end @@ -678,6 +744,9 @@ module Aws expect( client.config.credentials.credentials.access_key_id ).to eq('ACCESS_DIRECT') + expect( + client.config.credentials.metrics + ).to eq(['CREDENTIALS_PROFILE']) end it 'prefers ENV credentials over shared config when profile not set' do @@ -692,6 +761,9 @@ module Aws expect( client.config.credentials.credentials.access_key_id ).to eq('AKID_ENV_STUB') + expect( + client.config.credentials.metrics + ).to eq(['CREDENTIALS_ENV_VARS']) end it 'prefers config from profile over ENV credentials when profile is set on client' do @@ -706,6 +778,9 @@ module Aws expect( client.config.credentials.credentials.access_key_id ).to eq('ACCESS_KEY_1') + expect( + client.config.credentials.metrics + ).to eq(['CREDENTIALS_PROFILE']) end it 'will not load credentials from shared config' do @@ -757,6 +832,9 @@ module Aws expect( client.config.credentials.credentials.access_key_id ).to eq('akid-md') + expect( + client.config.credentials.metrics + ).to eq(['CREDENTIALS_IMDS']) end end From 3c421480aa11a63cf55ad6bf47c7500a41cfeb01 Mon Sep 17 00:00:00 2001 From: Richard Wang Date: Wed, 26 Mar 2025 14:05:13 -0700 Subject: [PATCH 28/59] Fix code to align with correct credentials_code --- .../aws-sdk-core/assume_role_credentials.rb | 5 ++-- .../assume_role_web_identity_credentials.rb | 5 ++-- .../aws-sdk-core/credential_provider_chain.rb | 24 +++++------------- .../lib/aws-sdk-core/credentials.rb | 5 ++-- .../lib/aws-sdk-core/ecs_credentials.rb | 4 --- .../instance_profile_credentials.rb | 4 --- .../lib/aws-sdk-core/plugins/sign.rb | 12 +++------ .../lib/aws-sdk-core/process_credentials.rb | 4 --- .../lib/aws-sdk-core/shared_config.rb | 25 ++++++++----------- .../lib/aws-sdk-core/shared_credentials.rb | 4 --- .../lib/aws-sdk-core/sso_credentials.rb | 16 +++++++++--- .../aws/credential_provider_chain_spec.rb | 1 - .../aws/credential_resolution_chain_spec.rb | 1 - 13 files changed, 41 insertions(+), 69 deletions(-) diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_credentials.rb b/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_credentials.rb index 3d03effc6ec..65e26dd4b7b 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_credentials.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_credentials.rb @@ -50,6 +50,7 @@ def initialize(options = {}) end @client = client_opts[:client] || STS::Client.new(client_opts) @async_refresh = true + @source = :none super end @@ -64,8 +65,6 @@ def initialize(options = {}) attr_accessor :resolving def metrics - nil unless @source - source_profile = %w[CREDENTIALS_PROFILE_SOURCE_PROFILE CREDENTIALS_STS_ASSUME_ROLE] credential_source = %w[CREDENTIALS_PROFILE_NAMED_PROVIDER CREDENTIALS_STS_ASSUME_ROLE] @@ -75,6 +74,8 @@ def metrics end case @source + when :none + ['CREDENTIALS_STS_ASSUME_ROLE'] when :static insert_metric(source_profile, 'CREDENTIALS_PROFILE') when :webID diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_web_identity_credentials.rb b/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_web_identity_credentials.rb index 76d942fc263..0b86be61ad4 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_web_identity_credentials.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_web_identity_credentials.rb @@ -61,6 +61,7 @@ def initialize(options = {}) @assume_role_web_identity_params[:role_session_name] = _session_name end @client = client_opts[:client] || STS::Client.new(client_opts.merge(credentials: nil)) + @source = :none super end @@ -70,9 +71,9 @@ def initialize(options = {}) attr_accessor :source def metrics - nil unless @source - case @source + when :none + ['CREDENTIALS_STS_ASSUME_ROLE_WEB_ID'] when :profile %w[CREDENTIALS_PROFILE_STS_WEB_ID_TOKEN CREDENTIALS_STS_ASSUME_ROLE_WEB_ID] when :env diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/credential_provider_chain.rb b/gems/aws-sdk-core/lib/aws-sdk-core/credential_provider_chain.rb index 9f75426e2d6..91659b22991 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/credential_provider_chain.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/credential_provider_chain.rb @@ -148,9 +148,7 @@ def static_profile_assume_role_credentials(options) def static_profile_credentials(options) if options[:config] && options[:config].profile - credentials = SharedCredentials.new(profile_name: options[:config].profile) - credentials.source = :set - credentials + SharedCredentials.new(profile_name: options[:config].profile) end rescue Errors::NoSuchProfileError nil @@ -160,9 +158,7 @@ def static_profile_process_credentials(options) if Aws.shared_config.config_enabled? && options[:config] && options[:config].profile process_provider = Aws.shared_config.credential_process(profile: options[:config].profile) if process_provider - credentials = ProcessCredentials.new([process_provider]) - credentials.source = :set - credentials + ProcessCredentials.new([process_provider]) end end rescue Errors::NoSuchProfileError @@ -198,9 +194,7 @@ def determine_profile_name(options) def shared_credentials(options) profile_name = determine_profile_name(options) - credentials = SharedCredentials.new(profile_name: profile_name) - credentials.source = :set - credentials + SharedCredentials.new(profile_name: profile_name) rescue Errors::NoSuchProfileError nil end @@ -210,9 +204,7 @@ def process_credentials(options) if Aws.shared_config.config_enabled? process_provider = Aws.shared_config.credential_process(profile: profile_name) if process_provider - credentials = ProcessCredentials.new([process_provider]) - credentials.source = :set - credentials + ProcessCredentials.new([process_provider]) end end rescue Errors::NoSuchProfileError @@ -261,13 +253,9 @@ def instance_profile_credentials(options) profile_name = determine_profile_name(options) if ENV['AWS_CONTAINER_CREDENTIALS_RELATIVE_URI'] || ENV['AWS_CONTAINER_CREDENTIALS_FULL_URI'] - credentials = ECSCredentials.new(options) - credentials.source = :set - credentials + ECSCredentials.new(options) else - credentials = InstanceProfileCredentials.new(options.merge(profile: profile_name)) - credentials.source = :set - credentials + InstanceProfileCredentials.new(options.merge(profile: profile_name)) end end diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/credentials.rb b/gems/aws-sdk-core/lib/aws-sdk-core/credentials.rb index 0c49375e770..1b202b8916b 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/credentials.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/credentials.rb @@ -14,6 +14,7 @@ def initialize(access_key_id, secret_access_key, session_token = nil, @secret_access_key = secret_access_key @session_token = session_token @account_id = kwargs[:account_id] + @source = :none end # @return [String] @@ -51,9 +52,9 @@ def inspect end def metrics - nil unless @source - case @source + when :none + ['CREDENTIALS_CODE'] when :profile ['CREDENTIALS_PROFILE'] when :env diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/ecs_credentials.rb b/gems/aws-sdk-core/lib/aws-sdk-core/ecs_credentials.rb index 8bcf87f31fa..578708d699f 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/ecs_credentials.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/ecs_credentials.rb @@ -84,11 +84,7 @@ def initialize(options = {}) # fetch credentials from the instance metadata service. Defaults to 0. attr_reader :retries - attr_accessor :source - def metrics - nil unless @source - ['CREDENTIALS_HTTP'] end diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/instance_profile_credentials.rb b/gems/aws-sdk-core/lib/aws-sdk-core/instance_profile_credentials.rb index 95862cbbd5a..52e2154181d 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/instance_profile_credentials.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/instance_profile_credentials.rb @@ -98,11 +98,7 @@ def initialize(options = {}) # the default credential chain ({Aws::CredentialProviderChain}). attr_reader :retries - attr_accessor :source - def metrics - nil unless @source - ['CREDENTIALS_IMDS'] end diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/plugins/sign.rb b/gems/aws-sdk-core/lib/aws-sdk-core/plugins/sign.rb index 1dac1bc0f60..fed05d46462 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/plugins/sign.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/plugins/sign.rb @@ -68,16 +68,10 @@ def with_metrics(credentials, &block) end puts credentials - metrics = [] - if !credentials.metrics - puts "Credentials code" - metrics << 'CREDENTIALS_CODE' - else - puts credentials.class.name - puts credentials.metrics - (metrics << credentials.metrics).flatten! - end + puts credentials.class.name + puts credentials.metrics + (metrics << credentials.metrics).flatten! Aws::Plugins::UserAgent.metric(*metrics, &block) end diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/process_credentials.rb b/gems/aws-sdk-core/lib/aws-sdk-core/process_credentials.rb index 241dd5e49fc..f50110bb3ab 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/process_credentials.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/process_credentials.rb @@ -40,11 +40,7 @@ def initialize(process) super end - attr_accessor :source - def metrics - nil unless @source - %w[CREDENTIALS_PROFILE_PROCESS CREDENTIALS_PROCESS] end diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/shared_config.rb b/gems/aws-sdk-core/lib/aws-sdk-core/shared_config.rb index 768195eb969..14d8404eac6 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/shared_config.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/shared_config.rb @@ -383,9 +383,7 @@ def assume_role_process_credentials_from_config(profile) credential_process ||= @parsed_config.fetch(profile, {})['credential_process'] end if credential_process - credentials = ProcessCredentials.new([credential_process]) - credentials.source = :set - credentials + ProcessCredentials.new([credential_process]) end end @@ -430,18 +428,15 @@ def sso_credentials_from_profile(cfg, profile) sso_start_url = prof_config['sso_start_url'] end - metric = prof_config['sso_session'] ? 'CREDENTIALS_PROFILE_SSO' : 'CREDENTIALS_PROFILE_SSO_LEGACY' - with_metrics(metric) do - credentials = SSOCredentials.new( - sso_account_id: prof_config['sso_account_id'], - sso_role_name: prof_config['sso_role_name'], - sso_session: prof_config['sso_session'], - sso_region: sso_region, - sso_start_url: sso_start_url, - ) - credentials.source = prof_config['sso_session'] ? :new : :legacy - credentials - end + credentials = SSOCredentials.new( + sso_account_id: prof_config['sso_account_id'], + sso_role_name: prof_config['sso_role_name'], + sso_session: prof_config['sso_session'], + sso_region: sso_region, + sso_start_url: sso_start_url, + ) + credentials.source = prof_config['sso_session'] ? :new : :legacy + credentials end end diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/shared_credentials.rb b/gems/aws-sdk-core/lib/aws-sdk-core/shared_credentials.rb index 9289e7ea10f..c66225655f9 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/shared_credentials.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/shared_credentials.rb @@ -51,8 +51,6 @@ def initialize(options = {}) # @return [Credentials] attr_reader :credentials - attr_accessor :source - # @api private def inspect parts = [ @@ -64,8 +62,6 @@ def inspect end def metrics - nil unless @source - ['CREDENTIALS_PROFILE'] end diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/sso_credentials.rb b/gems/aws-sdk-core/lib/aws-sdk-core/sso_credentials.rb index 0dac2bea75c..7cce3315873 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/sso_credentials.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/sso_credentials.rb @@ -114,7 +114,9 @@ def initialize(options = {}) end @async_refresh = true - super + @source = :none + metric = @legacy ? 'CREDENTIALS_PROFILE_SSO_LEGACY' : 'CREDENTIALS_PROFILE_SSO' + with_metric(metric) { super } end # @return [SSO::Client] @@ -175,14 +177,22 @@ def sso_cache_file end def metrics - nil unless @source - case @source when :new %w[CREDENTIALS_PROFILE_SSO CREDENTIALS_SSO] when :legacy %w[CREDENTIALS_PROFILE_SSO_LEGACY CREDENTIALS_SSO_LEGACY] + when :none + if @legacy + %w[CREDENTIALS_PROFILE_SSO_LEGACY CREDENTIALS_SSO_LEGACY] + else + %w[CREDENTIALS_PROFILE_SSO CREDENTIALS_SSO] + end end end + + def with_metric(metric, &block) + Aws::Plugins::UserAgent.metric(metric, &block) + end end end diff --git a/gems/aws-sdk-core/spec/aws/credential_provider_chain_spec.rb b/gems/aws-sdk-core/spec/aws/credential_provider_chain_spec.rb index 5527478726d..408ce8a31ad 100644 --- a/gems/aws-sdk-core/spec/aws/credential_provider_chain_spec.rb +++ b/gems/aws-sdk-core/spec/aws/credential_provider_chain_spec.rb @@ -83,7 +83,6 @@ def validate_metrics(expected_metrics) before(:each) do allow(InstanceProfileCredentials).to receive(:new).and_return(mock_instance_creds) - allow(mock_instance_creds).to receive(:source=).with(:set) allow(mock_instance_creds).to receive(:metrics).and_return(['CREDENTIALS_IMDS']) end diff --git a/gems/aws-sdk-core/spec/aws/credential_resolution_chain_spec.rb b/gems/aws-sdk-core/spec/aws/credential_resolution_chain_spec.rb index 9b92dace383..4d0981dbac6 100644 --- a/gems/aws-sdk-core/spec/aws/credential_resolution_chain_spec.rb +++ b/gems/aws-sdk-core/spec/aws/credential_resolution_chain_spec.rb @@ -31,7 +31,6 @@ module Aws before(:each) do allow(InstanceProfileCredentials).to receive(:new).and_return(mock_instance_creds) - allow(mock_instance_creds).to receive(:source=) expect_any_instance_of(ProcessCredentials).not_to receive(:warn) end From 7cd276fa0699b88b8314facb202141195dcde422 Mon Sep 17 00:00:00 2001 From: Richard Wang Date: Wed, 26 Mar 2025 14:14:40 -0700 Subject: [PATCH 29/59] Cleanup --- .../aws-sdk-core/assume_role_credentials.rb | 2 - .../assume_role_web_identity_credentials.rb | 2 - .../aws-sdk-core/credential_provider_chain.rb | 73 +------------------ .../lib/aws-sdk-core/shared_config.rb | 12 +-- .../lib/aws-sdk-core/sso_credentials.rb | 2 - 5 files changed, 3 insertions(+), 88 deletions(-) diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_credentials.rb b/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_credentials.rb index 65e26dd4b7b..8d82df5935f 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_credentials.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_credentials.rb @@ -96,9 +96,7 @@ def metrics private def refresh - puts "AssumeRole refreshing" resp = @client.assume_role(@assume_role_params) - puts "AssumeRole refreshed" creds = resp.credentials @credentials = Credentials.new( creds.access_key_id, diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_web_identity_credentials.rb b/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_web_identity_credentials.rb index 0b86be61ad4..81a63bf9064 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_web_identity_credentials.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_web_identity_credentials.rb @@ -87,9 +87,7 @@ def refresh # read from token file everytime it refreshes @assume_role_web_identity_params[:web_identity_token] = _token_from_file(@token_file) - puts "Web ID refreshing" resp = @client.assume_role_with_web_identity(@assume_role_web_identity_params) - puts "Web ID refreshed" creds = resp.credentials @credentials = Credentials.new( creds.access_key_id, diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/credential_provider_chain.rb b/gems/aws-sdk-core/lib/aws-sdk-core/credential_provider_chain.rb index 91659b22991..df8c3eeffed 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/credential_provider_chain.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/credential_provider_chain.rb @@ -15,71 +15,6 @@ def resolve if provider && provider.set? puts method_name puts provider - case method_name.to_s - when "static_credentials" - puts "CREDENTIALS_PROFILE: n" - when "static_profile_assume_role_web_identity_credentials" - puts "CREDENTIALS_PROFILE_STS_WEB_ID_TOKEN and CREDENTIALS_STS_ASSUME_ROLE_WEB_ID: qk" - when "static_profile_sso_credentials" - puts "CREDENTIALS_PROFILE_SSO and CREDENTIALS_SSO: rs (NEW)" - puts "OR" - puts "CREDENTIALS_PROFILE_SSO_LEGACY and CREDENTIALS_SSO_LEGACY: tu (LEGACY)" - when "static_profile_assume_role_credentials" - puts "CREDENTIALS_PROFILE_SOURCE_PROFILE: o and ( \ - CREDENTIALS_PROFILE: n or \ - CREDENTIALS_PROFILE_STS_WEB_ID_TOKEN and CREDENTIALS_STS_ASSUME_ROLE_WEB_ID: qk or \ - CREDENTIALS_PROFILE_PROCESS and CREDENTIALS_PROCESS: vw or \ - CREDENTIALS_PROFILE_SSO and CREDENTIALS_SSO: rs (NEW) or \ - CREDENTIALS_PROFILE_SSO_LEGACY and CREDENTIALS_SSO_LEGACY: tu (LEGACY) \ - ) \ - and CREDENTIALS_STS_ASSUME_ROLE: i" - puts "OR" - puts "CREDENTIALS_PROFILE_NAMED_PROVIDER: p and ( \ - CREDENTIALS_IMDS: 0 or \ - CREDENTIALS_HTTP: z \ - ) \ - and CREDENTIALS_STS_ASSUME_ROLE: i" - when "static_profile_credentials" - puts "CREDENTIALS_PROFILE: n" - when "static_profile_process_credentials" - puts "CREDENTIALS_PROFILE_PROCESS and CREDENTIALS_PROCESS: vw" - when "env_credentials" - puts "CREDENTIALS_ENV_VARS: g" - when "assume_role_web_identity_credentials" - puts "CREDENTIALS_ENV_VARS_STS_WEB_ID_TOKEN and CREDENTIALS_STS_ASSUME_ROLE_WEB_ID: hk" - puts "OR" - puts "CREDENTIALS_PROFILE_STS_WEB_ID_TOKEN and CREDENTIALS_STS_ASSUME_ROLE_WEB_ID: qk" - when "sso_credentials" - puts "CREDENTIALS_PROFILE_SSO and CREDENTIALS_SSO: rs (NEW)" - puts "OR" - puts "CREDENTIALS_PROFILE_SSO_LEGACY and CREDENTIALS_SSO_LEGACY: tu (LEGACY)" - when "assume_role_credentials" - puts "CREDENTIALS_PROFILE_SOURCE_PROFILE: o and ( \ - CREDENTIALS_PROFILE: n or \ - CREDENTIALS_PROFILE_STS_WEB_ID_TOKEN and CREDENTIALS_STS_ASSUME_ROLE_WEB_ID: qk or \ - CREDENTIALS_PROFILE_PROCESS and CREDENTIALS_PROCESS: vw or \ - CREDENTIALS_PROFILE_SSO and CREDENTIALS_SSO: rs (NEW) or \ - CREDENTIALS_PROFILE_SSO_LEGACY and CREDENTIALS_SSO_LEGACY: tu (LEGACY) \ - ) \ - and CREDENTIALS_STS_ASSUME_ROLE: i" - puts "OR" - puts "CREDENTIALS_PROFILE_NAMED_PROVIDER: p and ( \ - CREDENTIALS_IMDS: 0 or \ - CREDENTIALS_HTTP: z \ - ) \ - and CREDENTIALS_STS_ASSUME_ROLE: i" - when "shared_credentials" - puts "CREDENTIALS_PROFILE: n" - when "process_credentials" - puts "CREDENTIALS_PROFILE_PROCESS and CREDENTIALS_PROCESS: vw" - when "instance_profile_credentials" - puts "CREDENTIALS_HTTP (z)" - puts "OR" - puts "CREDENTIALS_IMDS (0)" - else - puts method_name - puts "!! UNKNOWN !!" - end return provider end end @@ -157,9 +92,7 @@ def static_profile_credentials(options) def static_profile_process_credentials(options) if Aws.shared_config.config_enabled? && options[:config] && options[:config].profile process_provider = Aws.shared_config.credential_process(profile: options[:config].profile) - if process_provider - ProcessCredentials.new([process_provider]) - end + ProcessCredentials.new([process_provider]) if process_provider end rescue Errors::NoSuchProfileError nil @@ -203,9 +136,7 @@ def process_credentials(options) profile_name = determine_profile_name(options) if Aws.shared_config.config_enabled? process_provider = Aws.shared_config.credential_process(profile: profile_name) - if process_provider - ProcessCredentials.new([process_provider]) - end + ProcessCredentials.new([process_provider]) if process_provider end rescue Errors::NoSuchProfileError nil diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/shared_config.rb b/gems/aws-sdk-core/lib/aws-sdk-core/shared_config.rb index 14d8404eac6..21c49aee160 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/shared_config.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/shared_config.rb @@ -271,8 +271,6 @@ def assume_role_from_profile(cfg, profile, opts, chain_config) opts[:serial_number] ||= prof_cfg['mfa_serial'] opts[:profile] = opts.delete(:source_profile) opts.delete(:visited_profiles) - puts "In assume role" - puts opts[:credentials] metrics = provider.metrics # Add the AssumeRole metric to the front if it isn't there metrics.unshift('CREDENTIALS_PROFILE_SOURCE_PROFILE') if metrics.first != 'CREDENTIALS_PROFILE_SOURCE_PROFILE' @@ -281,7 +279,6 @@ def assume_role_from_profile(cfg, profile, opts, chain_config) metrics.pop opts[:credentials].resolving = true end - puts metrics with_metrics(metrics) do credentials = AssumeRoleCredentials.new(opts) credentials.source = source @@ -337,24 +334,19 @@ def resolve_source_profile(profile, opts = {}) end if (creds = credentials(profile: profile)) - puts "Creds" creds.source = :profile [creds, creds, :static] # static credentials elsif profile_config && profile_config['source_profile'] - puts "assume" opts.delete(:source_profile) creds = assume_role_credentials_from_config(opts.merge(profile: profile)) [creds, creds, creds.source] elsif (provider = assume_role_web_identity_credentials_from_config(opts.merge(profile: profile))) - puts "web" provider.credentials.source = :assume_role_resolution [provider.credentials, provider, :webID] if provider.credentials.set? elsif (provider = assume_role_process_credentials_from_config(profile)) - puts "process" provider.credentials.source = :assume_role_resolution [provider.credentials, provider, :process] if provider.credentials.set? elsif (provider = sso_credentials_from_config(profile: profile)) - puts "sso" provider.credentials.source = :assume_role_resolution [provider.credentials, provider, provider.source] end @@ -382,9 +374,7 @@ def assume_role_process_credentials_from_config(profile) if @parsed_config credential_process ||= @parsed_config.fetch(profile, {})['credential_process'] end - if credential_process - ProcessCredentials.new([credential_process]) - end + ProcessCredentials.new([credential_process]) if credential_process end def credentials_from_shared(profile, _opts) diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/sso_credentials.rb b/gems/aws-sdk-core/lib/aws-sdk-core/sso_credentials.rb index 7cce3315873..0da1443438f 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/sso_credentials.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/sso_credentials.rb @@ -142,7 +142,6 @@ def read_cached_token end def refresh - puts "SSO refreshing" c = if @legacy cached_token = read_cached_token @client.get_role_credentials( @@ -157,7 +156,6 @@ def refresh access_token: @token_provider.token.token ).role_credentials end - puts "SSO refreshed" @credentials = Credentials.new( c.access_key_id, From 1612b213569417926efaa1cbbd33e15261c7adc9 Mon Sep 17 00:00:00 2001 From: Richard Wang Date: Wed, 26 Mar 2025 14:49:45 -0700 Subject: [PATCH 30/59] Fix SSO credential source --- .../lib/aws-sdk-core/shared_config.rb | 21 ++++++---- .../lib/aws-sdk-core/sso_credentials.rb | 12 ++---- .../spec/aws/plugins/user_agent_spec.rb | 42 +++++++++---------- 3 files changed, 36 insertions(+), 39 deletions(-) diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/shared_config.rb b/gems/aws-sdk-core/lib/aws-sdk-core/shared_config.rb index 21c49aee160..56fe15a2f07 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/shared_config.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/shared_config.rb @@ -418,15 +418,18 @@ def sso_credentials_from_profile(cfg, profile) sso_start_url = prof_config['sso_start_url'] end - credentials = SSOCredentials.new( - sso_account_id: prof_config['sso_account_id'], - sso_role_name: prof_config['sso_role_name'], - sso_session: prof_config['sso_session'], - sso_region: sso_region, - sso_start_url: sso_start_url, - ) - credentials.source = prof_config['sso_session'] ? :new : :legacy - credentials + metric = prof_config['sso_session'] ? 'CREDENTIALS_PROFILE_SSO' : 'CREDENTIALS_PROFILE_SSO_LEGACY' + with_metrics(metric) do + credentials = SSOCredentials.new( + sso_account_id: prof_config['sso_account_id'], + sso_role_name: prof_config['sso_role_name'], + sso_session: prof_config['sso_session'], + sso_region: sso_region, + sso_start_url: sso_start_url, + ) + credentials.source = prof_config['sso_session'] ? :new : :legacy + credentials + end end end diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/sso_credentials.rb b/gems/aws-sdk-core/lib/aws-sdk-core/sso_credentials.rb index 0da1443438f..bb5e89fdfc4 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/sso_credentials.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/sso_credentials.rb @@ -115,8 +115,7 @@ def initialize(options = {}) @async_refresh = true @source = :none - metric = @legacy ? 'CREDENTIALS_PROFILE_SSO_LEGACY' : 'CREDENTIALS_PROFILE_SSO' - with_metric(metric) { super } + super end # @return [SSO::Client] @@ -180,17 +179,14 @@ def metrics %w[CREDENTIALS_PROFILE_SSO CREDENTIALS_SSO] when :legacy %w[CREDENTIALS_PROFILE_SSO_LEGACY CREDENTIALS_SSO_LEGACY] + # TODO: Check if Ruby has "source-less" SSO credentials when :none if @legacy - %w[CREDENTIALS_PROFILE_SSO_LEGACY CREDENTIALS_SSO_LEGACY] + ['CREDENTIALS_SSO_LEGACY'] else - %w[CREDENTIALS_PROFILE_SSO CREDENTIALS_SSO] + ['CREDENTIALS_SSO'] end end end - - def with_metric(metric, &block) - Aws::Plugins::UserAgent.metric(metric, &block) - end end end diff --git a/gems/aws-sdk-core/spec/aws/plugins/user_agent_spec.rb b/gems/aws-sdk-core/spec/aws/plugins/user_agent_spec.rb index 7e76969ca06..97d82a859c5 100644 --- a/gems/aws-sdk-core/spec/aws/plugins/user_agent_spec.rb +++ b/gems/aws-sdk-core/spec/aws/plugins/user_agent_spec.rb @@ -113,28 +113,26 @@ def assert_header(expected, actual) end end - # context 'credential providers' do - # it 'includes the correct metrics for credentials defined in code' do - # stub_const( - # 'ENV', - # 'AWS_ACCESS_KEY_ID' => 'AKID_ENV_STUB', - # 'AWS_SECRET_ACCESS_KEY' => 'SECRET_ENV_STUB' - # ) - # client = ApiHelper.sample_service::Client.new( - # access_key_id: 'ACCESS_DIRECT', - # secret_access_key: 'SECRET_DIRECT', - # profile: 'fooprofile', - # region: 'us-east-1' - # ) - # puts client.config.credentials - # client.stub_responses(:example_operation, {}) - # resp = client.example_operation - # puts resp.context.http_request.headers['User-Agent'] - # expect(resp.context.http_request.headers['User-Agent']) - # .to include('md/akid') - # end - # - # end + context 'credential providers' do + it 'includes the correct metrics for credentials resolved from env vars' do + creds = Credentials.new( + 'AKID_ENV_STUB', + 'SECRET_ENV_STUB' + ) + client = ApiHelper.sample_service::Client.new( + stub_responses: true, + region: 'us-east-1', + credentials: creds + ) + puts client.config.credentials + client.stub_responses(:example_operation, {}) + resp = client.example_operation + puts resp.context.http_request.headers['User-Agent'] + expect(resp.context.http_request.headers['User-Agent']) + .to include('m/e,Z,b') + end + + end end end end From b1eb3400dc18888bb16a35925c0e6f42ac310c6b Mon Sep 17 00:00:00 2001 From: Richard Wang Date: Thu, 27 Mar 2025 11:15:28 -0700 Subject: [PATCH 31/59] Start to add unit tests to sign spec --- .../spec/aws/plugins/sign_spec.rb | 67 ++++++++++++++++++- .../spec/aws/plugins/user_agent_spec.rb | 21 ------ gems/aws-sdk-core/spec/sigv4_helper.rb | 1 + 3 files changed, 67 insertions(+), 22 deletions(-) diff --git a/gems/aws-sdk-core/spec/aws/plugins/sign_spec.rb b/gems/aws-sdk-core/spec/aws/plugins/sign_spec.rb index 18df297647c..498d0ebd01a 100644 --- a/gems/aws-sdk-core/spec/aws/plugins/sign_spec.rb +++ b/gems/aws-sdk-core/spec/aws/plugins/sign_spec.rb @@ -99,7 +99,7 @@ def call(context) end it 'raises an error when attempting to sign a request w/out credentials' do - client = TestClient.new(client_options.merge(credentials: nil) ) + client = TestClient.new(client_options.merge(credentials: nil)) expect { client.operation }.to raise_error(Errors::MissingCredentialsError) @@ -315,6 +315,71 @@ def call(context) expect(req.headers.key?('authorization')).to be(false) end end + + context 'UserAgent header' do + def metrics_from_header(header) + header[(header.index('m/')+2)..] + end + + let(:auth_scheme) do + { + 'name' => 'sigv4', + 'signingRegion' => region, + 'signingName' => 'svc', + } + end + + it 'adds the correct headers for static credentials from code' do + creds = Aws::Credentials.new('akid', 'secret') + client = TestClient.new(client_options.merge(credentials: creds)) + resp = client.operation + req = resp.context.http_request + metrics = metrics_from_header(req.headers['User-Agent']) + expect(metrics).to include('e') + end + + it 'adds the correct headers for static credentials from profile' do + creds = Aws::Credentials.new('akid', 'secret') + creds.source = :profile + client = TestClient.new(client_options.merge(credentials: creds)) + resp = client.operation + req = resp.context.http_request + metrics = metrics_from_header(req.headers['User-Agent']) + expect(metrics).to include('n') + end + + it 'adds the correct headers for static credentials from environment variables' do + creds = Aws::Credentials.new('akid', 'secret') + creds.source = :env + client = TestClient.new(client_options.merge(credentials: creds)) + resp = client.operation + req = resp.context.http_request + metrics = metrics_from_header(req.headers['User-Agent']) + expect(metrics).to include('g') + end + + it 'adds the correct headers for shared credentials' do + creds = Aws::SharedCredentials.new('akid', 'secret') + client = TestClient.new(client_options.merge(credentials: creds)) + resp = client.operation + req = resp.context.http_request + metrics = metrics_from_header(req.headers['User-Agent']) + expect(metrics).to include('g') + end + + it 'adds the correct headers for assume role web identity credentials from code' do + mock_creds = double('AssumeRoleWebIdentityCredentials', set?: true, source: :none) + allow(mock_creds).to receive(:credentials).and_return(Aws::Credentials.new('akid', 'secret')) + allow(mock_creds).to receive(:metrics).and_return(['CREDENTIALS_STS_ASSUME_ROLE_WEB_ID']) + allow(AssumeRoleWebIdentityCredentials).to receive(:new).and_return(mock_creds) + creds = Aws::AssumeRoleWebIdentityCredentials.new(region: 'us-west-2') + client = TestClient.new(client_options.merge(credentials: creds)) + resp = client.operation + req = resp.context.http_request + metrics = metrics_from_header(req.headers['User-Agent']) + expect(metrics).to include('k') + end + end end end end diff --git a/gems/aws-sdk-core/spec/aws/plugins/user_agent_spec.rb b/gems/aws-sdk-core/spec/aws/plugins/user_agent_spec.rb index 97d82a859c5..31bc3be6fa6 100644 --- a/gems/aws-sdk-core/spec/aws/plugins/user_agent_spec.rb +++ b/gems/aws-sdk-core/spec/aws/plugins/user_agent_spec.rb @@ -112,27 +112,6 @@ def assert_header(expected, actual) end end end - - context 'credential providers' do - it 'includes the correct metrics for credentials resolved from env vars' do - creds = Credentials.new( - 'AKID_ENV_STUB', - 'SECRET_ENV_STUB' - ) - client = ApiHelper.sample_service::Client.new( - stub_responses: true, - region: 'us-east-1', - credentials: creds - ) - puts client.config.credentials - client.stub_responses(:example_operation, {}) - resp = client.example_operation - puts resp.context.http_request.headers['User-Agent'] - expect(resp.context.http_request.headers['User-Agent']) - .to include('m/e,Z,b') - end - - end end end end diff --git a/gems/aws-sdk-core/spec/sigv4_helper.rb b/gems/aws-sdk-core/spec/sigv4_helper.rb index 62236a6b73a..0ee993d4c9b 100644 --- a/gems/aws-sdk-core/spec/sigv4_helper.rb +++ b/gems/aws-sdk-core/spec/sigv4_helper.rb @@ -20,6 +20,7 @@ def expect_auth(auth_scheme, region: nil, credentials: nil) expect(Aws::Sigv4::Signer).to receive(:new) .with(hash_including(signing_algorithm: :sigv4a, region: region)) .and_return(signer) + expect(signer).to receive(:credentials_provider) end m.call(*args) From b5828b0cfe170e284eff39c6e313efdbfed26059 Mon Sep 17 00:00:00 2001 From: Richard Wang Date: Thu, 27 Mar 2025 12:40:18 -0700 Subject: [PATCH 32/59] Add source testing --- .../aws/credential_resolution_chain_spec.rb | 52 ++++++++++++- .../spec/aws/plugins/sign_spec.rb | 77 +++---------------- 2 files changed, 63 insertions(+), 66 deletions(-) diff --git a/gems/aws-sdk-core/spec/aws/credential_resolution_chain_spec.rb b/gems/aws-sdk-core/spec/aws/credential_resolution_chain_spec.rb index 4d0981dbac6..e552668644a 100644 --- a/gems/aws-sdk-core/spec/aws/credential_resolution_chain_spec.rb +++ b/gems/aws-sdk-core/spec/aws/credential_resolution_chain_spec.rb @@ -58,6 +58,7 @@ module Aws region: 'us-east-1' ) expect(client.config.credentials.access_key_id).to eq('ACCESS_DIRECT') + expect(client.config.credentials.source).to eq(:profile) expect(client.config.credentials.metrics).to eq(['CREDENTIALS_PROFILE']) end @@ -78,6 +79,7 @@ module Aws profile: 'assumerole_sc', region: 'us-east-1' ) expect(client.config.credentials.credentials.access_key_id).to eq('AR_AKID') + expect(client.config.credentials.source).to eq(:static) expect( client.config.credentials.metrics ).to eq(%w[CREDENTIALS_PROFILE_SOURCE_PROFILE CREDENTIALS_PROFILE CREDENTIALS_STS_ASSUME_ROLE]) @@ -96,6 +98,7 @@ module Aws expect( client.config.credentials.credentials.access_key_id ).to eq('AR_AKID') + expect(client.config.credentials.source).to eq(:profile) expect( client.config.credentials.metrics ).to eq(%w[CREDENTIALS_PROFILE_STS_WEB_ID_TOKEN CREDENTIALS_STS_ASSUME_ROLE_WEB_ID]) @@ -235,7 +238,9 @@ module Aws expect( client.config.credentials.credentials.access_key_id ).to eq('AR_AKID') - + expect( + client.config.credentials.source + ).to eq(:static) expect( client.config.credentials.metrics ).to eq(%w[CREDENTIALS_PROFILE_SOURCE_PROFILE CREDENTIALS_PROFILE CREDENTIALS_STS_ASSUME_ROLE]) @@ -294,6 +299,9 @@ module Aws expect( client.config.credentials.credentials.access_key_id ).to eq('AKID_ENV_STUB') + expect( + client.config.credentials.source + ).to eq(:env) expect( client.config.credentials.metrics ).to eq(['CREDENTIALS_ENV_VARS']) @@ -393,6 +401,9 @@ module Aws expect( client.config.credentials.credentials.access_key_id ).to eq('AR_AKID') + expect( + client.config.credentials.source + ).to eq(:webID) expect( client.config.credentials.metrics ).to eq(%w[CREDENTIALS_PROFILE_SOURCE_PROFILE CREDENTIALS_PROFILE_STS_WEB_ID_TOKEN @@ -419,6 +430,9 @@ module Aws expect( client.config.credentials.credentials.access_key_id ).to eq('AK_PROC1') + expect( + client.config.credentials.source + ).to eq(:process) expect( client.config.credentials.metrics ).to eq(%w[CREDENTIALS_PROFILE_SOURCE_PROFILE CREDENTIALS_PROFILE_PROCESS CREDENTIALS_PROCESS @@ -455,6 +469,9 @@ module Aws expect( client.config.credentials.credentials.access_key_id ).to eq('AR_AKID') + expect( + client.config.credentials.source + ).to eq(:new) expect( client.config.credentials.metrics ).to eq(%w[CREDENTIALS_PROFILE_SOURCE_PROFILE CREDENTIALS_PROFILE_SSO CREDENTIALS_SSO @@ -484,6 +501,9 @@ module Aws expect( client.config.credentials.credentials.access_key_id ).to eq('AK_2') + expect( + client.config.credentials.source + ).to eq(:static) expect( client.config.credentials.metrics ).to eq(%w[CREDENTIALS_PROFILE_SOURCE_PROFILE CREDENTIALS_PROFILE CREDENTIALS_STS_ASSUME_ROLE]) @@ -504,6 +524,9 @@ module Aws expect( client.config.credentials.credentials.access_key_id ).to eq('AK_2') + expect( + client.config.credentials.source + ).to eq(:static) expect( client.config.credentials.metrics ).to eq(%w[CREDENTIALS_PROFILE_SOURCE_PROFILE CREDENTIALS_PROFILE CREDENTIALS_STS_ASSUME_ROLE]) @@ -524,6 +547,9 @@ module Aws expect( client.config.credentials.credentials.access_key_id ).to eq('AK_2') + expect( + client.config.credentials.source + ).to eq(:static) expect( client.config.credentials.metrics ).to eq(%w[CREDENTIALS_PROFILE_SOURCE_PROFILE CREDENTIALS_PROFILE CREDENTIALS_STS_ASSUME_ROLE]) @@ -568,6 +594,9 @@ module Aws expect( client.config.credentials.credentials.access_key_id ).to eq('AR_AKID') + expect( + client.config.credentials.source + ).to eq(:static) expect( client.config.credentials.metrics ).to eq(%w[CREDENTIALS_PROFILE_SOURCE_PROFILE CREDENTIALS_PROFILE CREDENTIALS_STS_ASSUME_ROLE]) @@ -587,6 +616,9 @@ module Aws expect( client.config.credentials.credentials.access_key_id ).to eq('AR_AKID') + expect( + client.config.credentials.source + ).to eq(:static) expect( client.config.credentials.metrics ).to eq(%w[CREDENTIALS_PROFILE_SOURCE_PROFILE CREDENTIALS_PROFILE CREDENTIALS_STS_ASSUME_ROLE]) @@ -606,6 +638,9 @@ module Aws expect( client.config.credentials.credentials.access_key_id ).to eq('AR_AKID') + expect( + client.config.credentials.source + ).to eq(:static) expect( client.config.credentials.metrics ).to eq(%w[CREDENTIALS_PROFILE_SOURCE_PROFILE CREDENTIALS_PROFILE CREDENTIALS_STS_ASSUME_ROLE]) @@ -629,6 +664,9 @@ module Aws expect( credentials.credentials.access_key_id ).to eq('AR_AKID') + expect( + credentials.source + ).to eq(:static) expect( credentials.metrics ).to eq(%w[CREDENTIALS_PROFILE_SOURCE_PROFILE CREDENTIALS_PROFILE CREDENTIALS_STS_ASSUME_ROLE]) @@ -676,6 +714,9 @@ module Aws expect( client.config.credentials.credentials.access_key_id ).to eq('AR_AKID') + expect( + client.config.credentials.source + ).to eq(:instance) expect( client.config.credentials.metrics ).to eq(%w[CREDENTIALS_PROFILE_NAMED_PROVIDER CREDENTIALS_IMDS CREDENTIALS_STS_ASSUME_ROLE]) @@ -711,6 +752,9 @@ module Aws expect( client.config.credentials.credentials.access_key_id ).to eq('AR_AKID') + expect( + client.config.credentials.source + ).to eq(:ecs) expect( client.config.credentials.metrics ).to eq(%w[CREDENTIALS_PROFILE_NAMED_PROVIDER CREDENTIALS_HTTP CREDENTIALS_STS_ASSUME_ROLE]) @@ -743,6 +787,9 @@ module Aws expect( client.config.credentials.credentials.access_key_id ).to eq('ACCESS_DIRECT') + expect( + client.config.credentials.source + ).to eq(:profile) expect( client.config.credentials.metrics ).to eq(['CREDENTIALS_PROFILE']) @@ -760,6 +807,9 @@ module Aws expect( client.config.credentials.credentials.access_key_id ).to eq('AKID_ENV_STUB') + expect( + client.config.credentials.source + ).to eq(:env) expect( client.config.credentials.metrics ).to eq(['CREDENTIALS_ENV_VARS']) diff --git a/gems/aws-sdk-core/spec/aws/plugins/sign_spec.rb b/gems/aws-sdk-core/spec/aws/plugins/sign_spec.rb index 498d0ebd01a..60cfbb32da0 100644 --- a/gems/aws-sdk-core/spec/aws/plugins/sign_spec.rb +++ b/gems/aws-sdk-core/spec/aws/plugins/sign_spec.rb @@ -202,6 +202,18 @@ def call(context) to eq (now.utc + 1000).strftime("%Y%m%dT%H%M%SZ") end end + + context 'UserAgent header' do + it 'Adds metrics from the credential providers' do + creds = Aws::Credentials.new('akid', 'secret') + client = TestClient.new(client_options.merge(credentials: creds)) + resp = client.operation + req = resp.context.http_request + header = req.headers['User-Agent'] + metrics = header[(header.index('m/')+2)..] + expect(metrics).to include('e') + end + end end context 'sigv4a' do @@ -315,71 +327,6 @@ def call(context) expect(req.headers.key?('authorization')).to be(false) end end - - context 'UserAgent header' do - def metrics_from_header(header) - header[(header.index('m/')+2)..] - end - - let(:auth_scheme) do - { - 'name' => 'sigv4', - 'signingRegion' => region, - 'signingName' => 'svc', - } - end - - it 'adds the correct headers for static credentials from code' do - creds = Aws::Credentials.new('akid', 'secret') - client = TestClient.new(client_options.merge(credentials: creds)) - resp = client.operation - req = resp.context.http_request - metrics = metrics_from_header(req.headers['User-Agent']) - expect(metrics).to include('e') - end - - it 'adds the correct headers for static credentials from profile' do - creds = Aws::Credentials.new('akid', 'secret') - creds.source = :profile - client = TestClient.new(client_options.merge(credentials: creds)) - resp = client.operation - req = resp.context.http_request - metrics = metrics_from_header(req.headers['User-Agent']) - expect(metrics).to include('n') - end - - it 'adds the correct headers for static credentials from environment variables' do - creds = Aws::Credentials.new('akid', 'secret') - creds.source = :env - client = TestClient.new(client_options.merge(credentials: creds)) - resp = client.operation - req = resp.context.http_request - metrics = metrics_from_header(req.headers['User-Agent']) - expect(metrics).to include('g') - end - - it 'adds the correct headers for shared credentials' do - creds = Aws::SharedCredentials.new('akid', 'secret') - client = TestClient.new(client_options.merge(credentials: creds)) - resp = client.operation - req = resp.context.http_request - metrics = metrics_from_header(req.headers['User-Agent']) - expect(metrics).to include('g') - end - - it 'adds the correct headers for assume role web identity credentials from code' do - mock_creds = double('AssumeRoleWebIdentityCredentials', set?: true, source: :none) - allow(mock_creds).to receive(:credentials).and_return(Aws::Credentials.new('akid', 'secret')) - allow(mock_creds).to receive(:metrics).and_return(['CREDENTIALS_STS_ASSUME_ROLE_WEB_ID']) - allow(AssumeRoleWebIdentityCredentials).to receive(:new).and_return(mock_creds) - creds = Aws::AssumeRoleWebIdentityCredentials.new(region: 'us-west-2') - client = TestClient.new(client_options.merge(credentials: creds)) - resp = client.operation - req = resp.context.http_request - metrics = metrics_from_header(req.headers['User-Agent']) - expect(metrics).to include('k') - end - end end end end From bdac7df69322313a0756e5c702bf0e461e188170 Mon Sep 17 00:00:00 2001 From: Richard Wang Date: Thu, 27 Mar 2025 14:10:50 -0700 Subject: [PATCH 33/59] Add metrics tests --- .../lib/aws-sdk-core/plugins/user_agent.rb | 1 + .../lib/aws-sdk-core/sso_credentials.rb | 32 ++--- .../spec/aws/assume_role_credentials_spec.rb | 128 ++++++++++++++++++ ...sume_role_web_identity_credentials_spec.rb | 41 ++++++ .../aws/credential_resolution_chain_spec.rb | 1 + .../aws-sdk-core/spec/aws/credentials_spec.rb | 29 ++++ .../spec/aws/ecs_credentials_spec.rb | 5 + .../aws/instance_profile_credentials_spec.rb | 5 + .../spec/aws/plugins/sign_spec.rb | 2 +- .../spec/aws/process_credentials_spec.rb | 6 + .../spec/aws/shared_credentials_spec.rb | 5 + .../spec/aws/sso_credentials_spec.rb | 40 ++++++ 12 files changed, 278 insertions(+), 17 deletions(-) diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/plugins/user_agent.rb b/gems/aws-sdk-core/lib/aws-sdk-core/plugins/user_agent.rb index 37f36a6bb17..a7c01eadd92 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/plugins/user_agent.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/plugins/user_agent.rb @@ -106,6 +106,7 @@ def call(context) def set_user_agent(context) context.http_request.headers['User-Agent'] = UserAgent.new(context).to_s + puts context.http_request.headers['User-Agent'] end class UserAgent diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/sso_credentials.rb b/gems/aws-sdk-core/lib/aws-sdk-core/sso_credentials.rb index bb5e89fdfc4..5dc91c367e9 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/sso_credentials.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/sso_credentials.rb @@ -123,6 +123,22 @@ def initialize(options = {}) attr_accessor :source + def metrics + case @source + when :new + %w[CREDENTIALS_PROFILE_SSO CREDENTIALS_SSO] + when :legacy + %w[CREDENTIALS_PROFILE_SSO_LEGACY CREDENTIALS_SSO_LEGACY] + # TODO: Check if Ruby has "source-less" SSO credentials + when :none + if @legacy + ['CREDENTIALS_SSO_LEGACY'] + else + ['CREDENTIALS_SSO'] + end + end + end + private def read_cached_token @@ -172,21 +188,5 @@ def sso_cache_file # Dir.home raises ArgumentError when ENV['home'] is not set raise ArgumentError, "Unable to load sso_cache_file: ENV['HOME'] is not set." end - - def metrics - case @source - when :new - %w[CREDENTIALS_PROFILE_SSO CREDENTIALS_SSO] - when :legacy - %w[CREDENTIALS_PROFILE_SSO_LEGACY CREDENTIALS_SSO_LEGACY] - # TODO: Check if Ruby has "source-less" SSO credentials - when :none - if @legacy - ['CREDENTIALS_SSO_LEGACY'] - else - ['CREDENTIALS_SSO'] - end - end - end end end diff --git a/gems/aws-sdk-core/spec/aws/assume_role_credentials_spec.rb b/gems/aws-sdk-core/spec/aws/assume_role_credentials_spec.rb index caadd47f486..b568eb6fc24 100644 --- a/gems/aws-sdk-core/spec/aws/assume_role_credentials_spec.rb +++ b/gems/aws-sdk-core/spec/aws/assume_role_credentials_spec.rb @@ -174,5 +174,133 @@ module Aws expect(before_refresh_called).to be(true) end + it 'defaults the source to none' do + c = AssumeRoleCredentials.new( + role_arn: 'arn', + role_session_name: 'session' + ) + expect(c.source).to eq(:none) + end + + describe '#metrics' do + + context 'from code' do + it 'returns the correct metrics when the source is none' do + c = AssumeRoleCredentials.new( + role_arn: 'arn', + role_session_name: 'session' + ) + expect(c.metrics).to eq(['CREDENTIALS_STS_ASSUME_ROLE']) + end + end + + context 'while resolving' do + let(:creds) { + c = AssumeRoleCredentials.new( + role_arn: 'arn', + role_session_name: 'session' + ) + c.resolving = true + c + } + + it 'returns the correct metrics when the source is static' do + c = creds + c.source = :static + expect(c.metrics).to eq(%w[CREDENTIALS_PROFILE_SOURCE_PROFILE CREDENTIALS_PROFILE]) + end + + it 'returns the correct metrics when the source is webID' do + c = creds + c.source = :webID + expect(c.metrics).to eq(%w[CREDENTIALS_PROFILE_SOURCE_PROFILE CREDENTIALS_PROFILE_STS_WEB_ID_TOKEN CREDENTIALS_STS_ASSUME_ROLE_WEB_ID]) + end + + it 'returns the correct metrics when the source is process' do + c = creds + c.source = :process + expect(c.metrics).to eq(%w[CREDENTIALS_PROFILE_SOURCE_PROFILE CREDENTIALS_PROFILE_PROCESS CREDENTIALS_PROCESS]) + end + + it 'returns the correct metrics when the source is new SSO' do + c = creds + c.source = :new + expect(c.metrics).to eq(%w[CREDENTIALS_PROFILE_SOURCE_PROFILE CREDENTIALS_PROFILE_SSO CREDENTIALS_SSO]) + end + + it 'returns the correct metrics when the source is legacy SSO' do + c = creds + c.source = :legacy + expect(c.metrics).to eq(%w[CREDENTIALS_PROFILE_SOURCE_PROFILE CREDENTIALS_PROFILE_SSO_LEGACY CREDENTIALS_SSO_LEGACY]) + end + + it 'returns the correct metrics when the source is instance' do + c = creds + c.source = :instance + expect(c.metrics).to eq(%w[CREDENTIALS_PROFILE_NAMED_PROVIDER CREDENTIALS_IMDS]) + end + + it 'returns the correct metrics when the source is ecs' do + c = creds + c.source = :ecs + expect(c.metrics).to eq(%w[CREDENTIALS_PROFILE_NAMED_PROVIDER CREDENTIALS_HTTP]) + end + end + + context 'when resolved' do + let(:creds) { + c = AssumeRoleCredentials.new( + role_arn: 'arn', + role_session_name: 'session' + ) + c + } + + it 'returns the correct metrics when the source is static' do + c = creds + c.source = :static + expect(c.metrics).to eq(%w[CREDENTIALS_PROFILE_SOURCE_PROFILE CREDENTIALS_PROFILE CREDENTIALS_STS_ASSUME_ROLE]) + end + + it 'returns the correct metrics when the source is webID' do + c = creds + c.source = :webID + expect(c.metrics).to eq(%w[CREDENTIALS_PROFILE_SOURCE_PROFILE CREDENTIALS_PROFILE_STS_WEB_ID_TOKEN CREDENTIALS_STS_ASSUME_ROLE_WEB_ID CREDENTIALS_STS_ASSUME_ROLE]) + end + + it 'returns the correct metrics when the source is process' do + c = creds + c.source = :process + expect(c.metrics).to eq(%w[CREDENTIALS_PROFILE_SOURCE_PROFILE CREDENTIALS_PROFILE_PROCESS CREDENTIALS_PROCESS CREDENTIALS_STS_ASSUME_ROLE]) + end + + it 'returns the correct metrics when the source is new SSO' do + c = creds + c.source = :new + expect(c.metrics).to eq(%w[CREDENTIALS_PROFILE_SOURCE_PROFILE CREDENTIALS_PROFILE_SSO CREDENTIALS_SSO CREDENTIALS_STS_ASSUME_ROLE]) + end + + it 'returns the correct metrics when the source is legacy SSO' do + c = creds + c.source = :legacy + expect(c.metrics).to eq(%w[CREDENTIALS_PROFILE_SOURCE_PROFILE CREDENTIALS_PROFILE_SSO_LEGACY CREDENTIALS_SSO_LEGACY CREDENTIALS_STS_ASSUME_ROLE]) + end + + it 'returns the correct metrics when the source is instance' do + c = creds + c.source = :instance + expect(c.metrics).to eq(%w[CREDENTIALS_PROFILE_NAMED_PROVIDER CREDENTIALS_IMDS CREDENTIALS_STS_ASSUME_ROLE]) + end + + it 'returns the correct metrics when the source is ecs' do + c = creds + c.source = :ecs + expect(c.metrics).to eq(%w[CREDENTIALS_PROFILE_NAMED_PROVIDER CREDENTIALS_HTTP CREDENTIALS_STS_ASSUME_ROLE]) + end + end + + + end + end end diff --git a/gems/aws-sdk-core/spec/aws/assume_role_web_identity_credentials_spec.rb b/gems/aws-sdk-core/spec/aws/assume_role_web_identity_credentials_spec.rb index 546097f2034..4adc78d4f1c 100644 --- a/gems/aws-sdk-core/spec/aws/assume_role_web_identity_credentials_spec.rb +++ b/gems/aws-sdk-core/spec/aws/assume_role_web_identity_credentials_spec.rb @@ -213,5 +213,46 @@ module Aws c.credentials c.credentials end + + it 'defaults the source to none' do + c = AssumeRoleWebIdentityCredentials.new( + role_arn: 'arn', + web_identity_token_file: token_file_path, + role_session_name: 'session' + ) + expect(c.source).to eq(:none) + end + + describe '#metrics' do + + it 'returns the correct metrics when the source is none' do + c = AssumeRoleWebIdentityCredentials.new( + role_arn: 'arn', + web_identity_token_file: token_file_path, + role_session_name: 'session' + ) + expect(c.metrics).to eq(['CREDENTIALS_STS_ASSUME_ROLE_WEB_ID']) + end + + it 'returns the correct metrics when the source is profile' do + c = AssumeRoleWebIdentityCredentials.new( + role_arn: 'arn', + web_identity_token_file: token_file_path, + role_session_name: 'session' + ) + c.source = :profile + expect(c.metrics).to eq(%w[CREDENTIALS_PROFILE_STS_WEB_ID_TOKEN CREDENTIALS_STS_ASSUME_ROLE_WEB_ID]) + end + + it 'returns the correct metrics when the source is env' do + c = AssumeRoleWebIdentityCredentials.new( + role_arn: 'arn', + web_identity_token_file: token_file_path, + role_session_name: 'session' + ) + c.source = :env + expect(c.metrics).to eq(%w[CREDENTIALS_ENV_VARS_STS_WEB_ID_TOKEN CREDENTIALS_STS_ASSUME_ROLE_WEB_ID]) + end + end end end diff --git a/gems/aws-sdk-core/spec/aws/credential_resolution_chain_spec.rb b/gems/aws-sdk-core/spec/aws/credential_resolution_chain_spec.rb index e552668644a..e438b2a4727 100644 --- a/gems/aws-sdk-core/spec/aws/credential_resolution_chain_spec.rb +++ b/gems/aws-sdk-core/spec/aws/credential_resolution_chain_spec.rb @@ -98,6 +98,7 @@ module Aws expect( client.config.credentials.credentials.access_key_id ).to eq('AR_AKID') + expect(client.config.credentials.source).to eq(:profile) expect( client.config.credentials.metrics diff --git a/gems/aws-sdk-core/spec/aws/credentials_spec.rb b/gems/aws-sdk-core/spec/aws/credentials_spec.rb index 3c65274667c..42f58fa2c3c 100644 --- a/gems/aws-sdk-core/spec/aws/credentials_spec.rb +++ b/gems/aws-sdk-core/spec/aws/credentials_spec.rb @@ -37,6 +37,10 @@ module Aws expect(Credentials.new('akid', 'secret').account_id).to be(nil) end + it 'defaults the source to none' do + expect(Credentials.new('akid', 'secret').source).to eq(:none) + end + describe '#set?' do it 'returns true when the key and secret are both non nil values' do @@ -60,5 +64,30 @@ module Aws end end + + describe '#metrics' do + + it 'returns the correct metrics when the source is none' do + expect(Credentials.new('akid', 'secret').metrics).to eq(['CREDENTIALS_CODE']) + end + + it 'returns the correct metrics when the source is profile' do + creds = Credentials.new('akid', 'secret') + creds.source = :profile + expect(creds.metrics).to eq(['CREDENTIALS_PROFILE']) + end + + it 'returns the correct metrics when the source is env' do + creds = Credentials.new('akid', 'secret') + creds.source = :env + expect(creds.metrics).to eq(['CREDENTIALS_ENV_VARS']) + end + + it 'returns no metrics when the source is assume_role_resolution' do + creds = Credentials.new('akid', 'secret') + creds.source = :assume_role_resolution + expect(creds.metrics).to eq([]) + end + end end end diff --git a/gems/aws-sdk-core/spec/aws/ecs_credentials_spec.rb b/gems/aws-sdk-core/spec/aws/ecs_credentials_spec.rb index 8c963c0d1d0..797fb122431 100644 --- a/gems/aws-sdk-core/spec/aws/ecs_credentials_spec.rb +++ b/gems/aws-sdk-core/spec/aws/ecs_credentials_spec.rb @@ -87,6 +87,11 @@ module Aws expect(c.expiration.to_s).to eq(expiration.to_s) end + it 'will return the correct metrics' do + c = ECSCredentials.new(backoff: 0, retries: 0) + expect(c.metrics).to eq(['CREDENTIALS_HTTP']) + end + context 'auto refreshing' do # expire in 4 minutes let(:expiration) { Time.now.utc + 299 } diff --git a/gems/aws-sdk-core/spec/aws/instance_profile_credentials_spec.rb b/gems/aws-sdk-core/spec/aws/instance_profile_credentials_spec.rb index 925b5808e9a..8f2d91b1023 100644 --- a/gems/aws-sdk-core/spec/aws/instance_profile_credentials_spec.rb +++ b/gems/aws-sdk-core/spec/aws/instance_profile_credentials_spec.rb @@ -687,5 +687,10 @@ module Aws assert_requested(expected_request, times: 2) end end + + it 'will return the correct metrics' do + c = InstanceProfileCredentials.new + expect(c.metrics).to eq(['CREDENTIALS_IMDS']) + end end end diff --git a/gems/aws-sdk-core/spec/aws/plugins/sign_spec.rb b/gems/aws-sdk-core/spec/aws/plugins/sign_spec.rb index 60cfbb32da0..e9edea5d233 100644 --- a/gems/aws-sdk-core/spec/aws/plugins/sign_spec.rb +++ b/gems/aws-sdk-core/spec/aws/plugins/sign_spec.rb @@ -203,7 +203,7 @@ def call(context) end end - context 'UserAgent header' do + describe 'UserAgent header' do it 'Adds metrics from the credential providers' do creds = Aws::Credentials.new('akid', 'secret') client = TestClient.new(client_options.merge(credentials: creds)) diff --git a/gems/aws-sdk-core/spec/aws/process_credentials_spec.rb b/gems/aws-sdk-core/spec/aws/process_credentials_spec.rb index d038b0322bb..2e659fb23df 100644 --- a/gems/aws-sdk-core/spec/aws/process_credentials_spec.rb +++ b/gems/aws-sdk-core/spec/aws/process_credentials_spec.rb @@ -46,6 +46,12 @@ module Aws }.to raise_error(Errors::InvalidProcessCredentialsPayload) end + it 'will return the correct metrics' do + process = %w[echo {"Version":1,"AccessKeyId":"AK_PROC1","SecretAccessKey":"SECRET_AK_PROC1","SessionToken":"TOKEN_PROC1","AccountId":"ACCOUNT_ID_PROC1"}] + c = ProcessCredentials.new(process) + expect(c.metrics).to eq(%w[CREDENTIALS_PROFILE_PROCESS CREDENTIALS_PROCESS]) + end + context 'legacy process string' do before do expect_any_instance_of(ProcessCredentials) diff --git a/gems/aws-sdk-core/spec/aws/shared_credentials_spec.rb b/gems/aws-sdk-core/spec/aws/shared_credentials_spec.rb index 1b0ca3f48fc..02b4931ca77 100644 --- a/gems/aws-sdk-core/spec/aws/shared_credentials_spec.rb +++ b/gems/aws-sdk-core/spec/aws/shared_credentials_spec.rb @@ -137,5 +137,10 @@ module Aws expect(creds).to eq(nil) end + it 'will return the correct metrics' do + creds = SharedCredentials.new(path:mock_credential_file) + expect(creds.metrics).to eq(['CREDENTIALS_PROFILE']) + end + end end diff --git a/gems/aws-sdk-core/spec/aws/sso_credentials_spec.rb b/gems/aws-sdk-core/spec/aws/sso_credentials_spec.rb index 5cc05286a6d..0f0812fc98f 100644 --- a/gems/aws-sdk-core/spec/aws/sso_credentials_spec.rb +++ b/gems/aws-sdk-core/spec/aws/sso_credentials_spec.rb @@ -148,6 +148,22 @@ def mock_token_file(start_url, cached_token) expect(sso_creds.expiration).to eq(expiration) end end + + describe '#metrics' do + + it 'returns the correct metrics when the source is none' do + c = SSOCredentials.new(sso_opts) + expect(c.metrics).to eq(['CREDENTIALS_SSO']) + end + + it 'returns the correct metrics when the source is new' do + c = SSOCredentials.new(sso_opts) + c.source = :new + expect(c.metrics).to eq(%w[CREDENTIALS_PROFILE_SSO CREDENTIALS_SSO]) + end + + end + end context 'legacy profile' do @@ -290,6 +306,30 @@ def mock_token_file(start_url, cached_token) sso_creds.credentials end end + + describe '#metrics' do + + it 'returns the correct metrics when the source is none' do + expect(SSO::Client).to receive(:new) + .with({region: sso_region, credentials: nil}) + .and_return(client) + + mock_token_file(sso_start_url, cached_token) + c = SSOCredentials.new(sso_opts) + expect(c.metrics).to eq(['CREDENTIALS_SSO_LEGACY']) + end + + it 'returns the correct metrics when the source is legacy' do + expect(SSO::Client).to receive(:new) + .with({region: sso_region, credentials: nil}) + .and_return(client) + + mock_token_file(sso_start_url, cached_token) + c = SSOCredentials.new(sso_opts) + c.source = :legacy + expect(c.metrics).to eq(%w[CREDENTIALS_PROFILE_SSO_LEGACY CREDENTIALS_SSO_LEGACY]) + end + end end end end From e2be224d5e3cf3c3aaa4e9593dc5d66401623cf1 Mon Sep 17 00:00:00 2001 From: Richard Wang Date: Thu, 27 Mar 2025 15:24:25 -0700 Subject: [PATCH 34/59] Add missing test cases --- .../aws/credential_resolution_chain_spec.rb | 98 ++++++++++++++++++- .../fixtures/credentials/mock_shared_config | 4 + 2 files changed, 97 insertions(+), 5 deletions(-) diff --git a/gems/aws-sdk-core/spec/aws/credential_resolution_chain_spec.rb b/gems/aws-sdk-core/spec/aws/credential_resolution_chain_spec.rb index e438b2a4727..23c0b3cd759 100644 --- a/gems/aws-sdk-core/spec/aws/credential_resolution_chain_spec.rb +++ b/gems/aws-sdk-core/spec/aws/credential_resolution_chain_spec.rb @@ -85,7 +85,7 @@ module Aws ).to eq(%w[CREDENTIALS_PROFILE_SOURCE_PROFILE CREDENTIALS_PROFILE CREDENTIALS_STS_ASSUME_ROLE]) end - it 'prefers assume role web identity over sso' do + it 'prefers assume role web identity from profile over sso' do assume_role_web_identity_stub( 'arn:aws:iam::123456789012:role/foo', 'AR_AKID', @@ -105,6 +105,31 @@ module Aws ).to eq(%w[CREDENTIALS_PROFILE_STS_WEB_ID_TOKEN CREDENTIALS_STS_ASSUME_ROLE_WEB_ID]) end + it 'prefers assume role web identity from ENV over sso' do + stub_const( + 'ENV', + 'AWS_ROLE_ARN' => 'arn:aws:iam::123456789012:role/foo', + 'AWS_WEB_IDENTITY_TOKEN_FILE' => 'my-token.jwt' + ) + assume_role_web_identity_stub( + 'arn:aws:iam::123456789012:role/foo', + 'AR_AKID', + 'AR_SECRET', + 'AR_TOKEN' + ) + client = ApiHelper.sample_rest_xml::Client.new( + region: 'us-east-1' + ) + expect( + client.config.credentials.credentials.access_key_id + ).to eq('AR_AKID') + + expect(client.config.credentials.source).to eq(:env) + expect( + client.config.credentials.metrics + ).to eq(%w[CREDENTIALS_ENV_VARS_STS_WEB_ID_TOKEN CREDENTIALS_STS_ASSUME_ROLE_WEB_ID]) + end + it 'prefers sso credentials over assume role' do creds = double('creds', set?: true, credentials: double(access_key_id: 'SSO_AKID')) allow(creds).to receive(:metrics).and_return(%w[CREDENTIALS_PROFILE_SSO CREDENTIALS_SSO]) @@ -325,7 +350,7 @@ module Aws ).to eq(%w[CREDENTIALS_PROFILE_PROCESS CREDENTIALS_PROCESS]) end - it 'attempts to fetch metadata credentials last' do + it 'attempts to fetch metadata credentials last IMDS' do allow(InstanceProfileCredentials).to receive(:new).and_call_original stub_request(:put, 'http://169.254.169.254/latest/api/token') @@ -353,7 +378,7 @@ module Aws "Token" : "session-token-md", "Expiration" : "#{(Time.now.utc + 3600).strftime('%Y-%m-%dT%H:%M:%SZ')}" } - JSON + JSON client = ApiHelper.sample_rest_xml::Client.new( profile: 'nonexistant', region: 'us-east-1' ) @@ -365,6 +390,30 @@ module Aws ).to eq(['CREDENTIALS_IMDS']) end + it 'attempts to fetch metadata credentials last HTTP' do + path = '/latest/credentials?id=foobarbaz' + resp = <<-JSON.strip + { + "RoleArn" : "arn:aws:iam::123456789012:role/BarFooRole", + "AccessKeyId" : "ACCESS_KEY_ECS", + "SecretAccessKey" : "secret", + "Token" : "session-token", + "Expiration" : "#{(Time.now.utc + 3600).strftime('%Y-%m-%dT%H:%M:%SZ')}" + } + JSON + stub_const('ENV', + 'AWS_CONTAINER_CREDENTIALS_RELATIVE_URI' => path) + stub_request(:get, "http://169.254.170.2#{path}") + .to_return(status: 200, body: resp) + client = ApiHelper.sample_rest_xml::Client.new( + profile: 'nonexistent', + region: 'us-east-1' + ) + expect( + client.config.credentials.metrics + ).to eq(['CREDENTIALS_HTTP']) + end + describe 'Assume Role Resolution' do it 'will not assume a role without a source present' do expect do @@ -454,7 +503,7 @@ module Aws expect(creds).to receive(:source).and_return(:new) allow(SSOTokenProvider).to receive(:new) - .and_return(double('SSOToken', set?: true)) + .and_return(double('SSOToken', set?: true)) assume_role_stub( 'arn:aws:iam::123456789012:role/foo', @@ -479,6 +528,45 @@ module Aws CREDENTIALS_STS_ASSUME_ROLE]) end + it 'supports :source_profile from legacy sso credentials' do + creds = double('creds', set?: true, credentials: Credentials.new('SSO_AKID', 'sak')) + allow(creds).to receive(:metrics).and_return(%w[CREDENTIALS_PROFILE_SSO_LEGACY CREDENTIALS_SSO_LEGACY]) + expect(SSOCredentials).to receive(:new).with( + sso_start_url: 'START_URL', + sso_region: 'us-east-1', + sso_account_id: 'SSO_ACCOUNT_ID', + sso_role_name: 'SSO_ROLE_NAME', + sso_session: nil + ).and_return(creds) + expect(creds).to receive(:source=).with(:legacy) + expect(creds).to receive(:source).and_return(:legacy) + + allow(SSOTokenProvider).to receive(:new) + .and_return(double('SSOToken', set?: true)) + + assume_role_stub( + 'arn:aws:iam::123456789012:role/foo', + 'SSO_AKID', + 'AR_AKID', + 'SECRET_AK', + 'TOKEN' + ) + + client = ApiHelper.sample_rest_xml::Client.new( + profile: 'ar_sso_legacy_src', region: 'us-east-1' + ) + expect( + client.config.credentials.credentials.access_key_id + ).to eq('AR_AKID') + expect( + client.config.credentials.source + ).to eq(:legacy) + expect( + client.config.credentials.metrics + ).to eq(%w[CREDENTIALS_PROFILE_SOURCE_PROFILE CREDENTIALS_PROFILE_SSO_LEGACY CREDENTIALS_SSO_LEGACY + CREDENTIALS_STS_ASSUME_ROLE]) + end + it 'supports assume role chaining' do assume_role_stub( 'arn:aws:iam::123456789012:role/role_b', @@ -875,7 +963,7 @@ module Aws "Token" : "session-token-md", "Expiration" : "#{(Time.now.utc + 3600).strftime('%Y-%m-%dT%H:%M:%SZ')}" } - JSON + JSON client = ApiHelper.sample_rest_xml::Client.new( profile: 'nonexistant', region: 'us-east-1' ) diff --git a/gems/aws-sdk-core/spec/fixtures/credentials/mock_shared_config b/gems/aws-sdk-core/spec/fixtures/credentials/mock_shared_config index 9c19c758d79..7b2ee6dc0a1 100644 --- a/gems/aws-sdk-core/spec/fixtures/credentials/mock_shared_config +++ b/gems/aws-sdk-core/spec/fixtures/credentials/mock_shared_config @@ -173,6 +173,10 @@ sso_account_id = 123456789012 source_profile = sso_creds role_arn = arn:aws:iam::123456789012:role/bar +[profile ar_sso_legacy_src] +source_profile = sso_creds_legacy +role_arn = arn:aws:iam::123456789012:role/bar + [profile sso_creds_session_with_quotes] sso_account_id = SSO_ACCOUNT_ID sso_role_name = SSO_ROLE_NAME From c68e112ebece0cb2045cd9b531812d3cad4302a0 Mon Sep 17 00:00:00 2001 From: Richard Wang Date: Fri, 28 Mar 2025 09:14:06 -0700 Subject: [PATCH 35/59] Add with metrics to refresh --- .../aws-sdk-core/assume_role_credentials.rb | 7 +++- .../assume_role_web_identity_credentials.rb | 8 +++-- .../lib/aws-sdk-core/sso_credentials.rb | 35 +++++++++++-------- 3 files changed, 33 insertions(+), 17 deletions(-) diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_credentials.rb b/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_credentials.rb index 8d82df5935f..64069069ed6 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_credentials.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_credentials.rb @@ -96,7 +96,8 @@ def metrics private def refresh - resp = @client.assume_role(@assume_role_params) + metric = metrics[0...-1] + resp = with_metrics(metric) { @client.assume_role(@assume_role_params) } creds = resp.credentials @credentials = Credentials.new( creds.access_key_id, @@ -116,6 +117,10 @@ def insert_metric(base, metrics) base.insert(1, *metrics) end + def with_metrics(metrics, &block) + Aws::Plugins::UserAgent.metric(*metrics, &block) + end + class << self # @api private diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_web_identity_credentials.rb b/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_web_identity_credentials.rb index 81a63bf9064..7adf512889d 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_web_identity_credentials.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_web_identity_credentials.rb @@ -86,8 +86,8 @@ def metrics def refresh # read from token file everytime it refreshes @assume_role_web_identity_params[:web_identity_token] = _token_from_file(@token_file) - - resp = @client.assume_role_with_web_identity(@assume_role_web_identity_params) + metric = metrics[0...-1] + resp = with_metrics(metric) { @client.assume_role_with_web_identity(@assume_role_web_identity_params) } creds = resp.credentials @credentials = Credentials.new( creds.access_key_id, @@ -114,6 +114,10 @@ def parse_account_id(resp) ARNParser.parse(arn).account_id if ARNParser.arn?(arn) end + def with_metrics(metrics, &block) + Aws::Plugins::UserAgent.metric(*metrics, &block) + end + class << self # @api private diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/sso_credentials.rb b/gems/aws-sdk-core/lib/aws-sdk-core/sso_credentials.rb index 5dc91c367e9..3c604a09931 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/sso_credentials.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/sso_credentials.rb @@ -157,20 +157,23 @@ def read_cached_token end def refresh - c = if @legacy - cached_token = read_cached_token - @client.get_role_credentials( - account_id: @sso_account_id, - role_name: @sso_role_name, - access_token: cached_token['accessToken'] - ).role_credentials - else - @client.get_role_credentials( - account_id: @sso_account_id, - role_name: @sso_role_name, - access_token: @token_provider.token.token - ).role_credentials - end + metric = metrics[0...-1] + c = with_metrics(metric) do + if @legacy + cached_token = read_cached_token + @client.get_role_credentials( + account_id: @sso_account_id, + role_name: @sso_role_name, + access_token: cached_token['accessToken'] + ).role_credentials + else + @client.get_role_credentials( + account_id: @sso_account_id, + role_name: @sso_role_name, + access_token: @token_provider.token.token + ).role_credentials + end + end @credentials = Credentials.new( c.access_key_id, @@ -188,5 +191,9 @@ def sso_cache_file # Dir.home raises ArgumentError when ENV['home'] is not set raise ArgumentError, "Unable to load sso_cache_file: ENV['HOME'] is not set." end + + def with_metrics(metrics, &block) + Aws::Plugins::UserAgent.metric(*metrics, &block) + end end end From cb816abfd18d8596a4ed83e43c5494cf5c126c34 Mon Sep 17 00:00:00 2001 From: Richard Wang Date: Fri, 28 Mar 2025 12:35:07 -0700 Subject: [PATCH 36/59] Add partial refresh tests --- gems/aws-sdk-core/CHANGELOG.md | 2 +- .../assume_role_web_identity_credentials.rb | 1 + .../spec/aws/assume_role_credentials_spec.rb | 45 +++++++++++ ...sume_role_web_identity_credentials_spec.rb | 75 ++++++++++++++++--- 4 files changed, 112 insertions(+), 11 deletions(-) diff --git a/gems/aws-sdk-core/CHANGELOG.md b/gems/aws-sdk-core/CHANGELOG.md index 2f36520a4cf..2cce016c96e 100644 --- a/gems/aws-sdk-core/CHANGELOG.md +++ b/gems/aws-sdk-core/CHANGELOG.md @@ -1,7 +1,7 @@ Unreleased Changes ------------------ -* Feature - Add feature id tracking for credentials. +Issue - Additional metrics collection for credentials in the User-Agent plugin. 3.220.1 (2025-03-06) ------------------ diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_web_identity_credentials.rb b/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_web_identity_credentials.rb index 7adf512889d..78a03b4adf9 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_web_identity_credentials.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_web_identity_credentials.rb @@ -87,6 +87,7 @@ def refresh # read from token file everytime it refreshes @assume_role_web_identity_params[:web_identity_token] = _token_from_file(@token_file) metric = metrics[0...-1] + puts "Refreshing with metrics #{metric}" resp = with_metrics(metric) { @client.assume_role_with_web_identity(@assume_role_web_identity_params) } creds = resp.credentials @credentials = Credentials.new( diff --git a/gems/aws-sdk-core/spec/aws/assume_role_credentials_spec.rb b/gems/aws-sdk-core/spec/aws/assume_role_credentials_spec.rb index b568eb6fc24..12afe78b08c 100644 --- a/gems/aws-sdk-core/spec/aws/assume_role_credentials_spec.rb +++ b/gems/aws-sdk-core/spec/aws/assume_role_credentials_spec.rb @@ -302,5 +302,50 @@ module Aws end + describe '#with_metrics' do + it 'is called with the correct metrics when initializing credentials' do + expect_any_instance_of(AssumeRoleCredentials).to receive(:with_metrics).with([]).and_return(resp) + AssumeRoleCredentials.new( + role_arn: 'arn', + role_session_name: 'session' + ) + end + + context 'refreshing expired credentials' do + it 'is called with the correct metrics when source is none' do + allow(credentials).to receive(:expiration).and_return(Time.now) + expect_any_instance_of(AssumeRoleCredentials).to receive(:with_metrics).with([]).and_return(resp) + expect_any_instance_of(AssumeRoleCredentials).to receive(:with_metrics).with([]).and_return(resp) + c = AssumeRoleCredentials.new( + role_arn: 'arn', + role_session_name: 'session') + c.source = :none + c.credentials + end + + it 'is called with the correct metrics when source is static' do + allow(credentials).to receive(:expiration).and_return(Time.now) + expect_any_instance_of(AssumeRoleCredentials).to receive(:with_metrics).with([]).and_return(resp) + expect_any_instance_of(AssumeRoleCredentials).to receive(:with_metrics).with(%w[CREDENTIALS_PROFILE_SOURCE_PROFILE CREDENTIALS_PROFILE]).and_return(resp) + c = AssumeRoleCredentials.new( + role_arn: 'arn', + role_session_name: 'session') + c.source = :static + c.credentials + end + + it 'is called with the correct metrics when source is webID' do + allow(credentials).to receive(:expiration).and_return(Time.now) + expect_any_instance_of(AssumeRoleCredentials).to receive(:with_metrics).with([]).and_return(resp) + expect_any_instance_of(AssumeRoleCredentials).to receive(:with_metrics).with([]).and_return(resp) + c = AssumeRoleCredentials.new( + role_arn: 'arn', + role_session_name: 'session') + c.source = :none + c.credentials + end + + end + end end end diff --git a/gems/aws-sdk-core/spec/aws/assume_role_web_identity_credentials_spec.rb b/gems/aws-sdk-core/spec/aws/assume_role_web_identity_credentials_spec.rb index 4adc78d4f1c..11a923f2440 100644 --- a/gems/aws-sdk-core/spec/aws/assume_role_web_identity_credentials_spec.rb +++ b/gems/aws-sdk-core/spec/aws/assume_role_web_identity_credentials_spec.rb @@ -59,7 +59,7 @@ module Aws creds = AssumeRoleWebIdentityCredentials.new( role_arn: 'arn', web_identity_token_file: token_file_path, - role_session_name: "session-name" + role_session_name: 'session-name' ) expect(creds.client).to be(client) end @@ -70,7 +70,7 @@ module Aws creds = AssumeRoleWebIdentityCredentials.new( role_arn: 'arn', web_identity_token_file: token_file_path, - role_session_name: "session-name", + role_session_name: 'session-name', before_refresh: proc { } ) expect(creds.client).to be(client) @@ -107,12 +107,12 @@ module Aws expect(client).to receive(:assume_role_with_web_identity).with({ role_arn: 'arn', web_identity_token: 'token', - role_session_name: "session-name" + role_session_name: 'session-name' }) AssumeRoleWebIdentityCredentials.new( role_arn: 'arn', web_identity_token_file: token_file_path, - role_session_name: "session-name" + role_session_name: 'session-name' ) end @@ -142,16 +142,16 @@ module Aws expect(client).to receive(:assume_role_with_web_identity).with({ role_arn: 'arn', web_identity_token: '', - role_session_name: "session-name", - provider_id: "urlType", - policy: "sessionPolicyDocumentType" + role_session_name: 'session-name', + provider_id: 'urlType', + policy: 'sessionPolicyDocumentType' }) AssumeRoleWebIdentityCredentials.new( role_arn: 'arn', web_identity_token_file: token_file_path, - role_session_name: "session-name", - provider_id: "urlType", - policy: "sessionPolicyDocumentType" + role_session_name: 'session-name', + provider_id: 'urlType', + policy: 'sessionPolicyDocumentType' ) end @@ -254,5 +254,60 @@ module Aws expect(c.metrics).to eq(%w[CREDENTIALS_ENV_VARS_STS_WEB_ID_TOKEN CREDENTIALS_STS_ASSUME_ROLE_WEB_ID]) end end + + describe '#with_metrics' do + it 'is called with the correct metrics when initializing credentials' do + expect_any_instance_of(AssumeRoleWebIdentityCredentials).to receive(:with_metrics).with([]).and_return(resp) + AssumeRoleWebIdentityCredentials.new( + role_arn: 'arn', + web_identity_token_file: token_file_path, + role_session_name: 'session' + ) + end + + context 'refreshing expired credentials' do + it 'is called with the correct metrics when source is none' do + allow(credentials).to receive(:expiration).and_return(Time.now) + expect(File).to receive(:read).with(token_file_path).exactly(2).times + expect_any_instance_of(AssumeRoleWebIdentityCredentials).to receive(:with_metrics).with([]).and_return(resp) + expect_any_instance_of(AssumeRoleWebIdentityCredentials).to receive(:with_metrics).with([]).and_return(resp) + c = AssumeRoleWebIdentityCredentials.new( + role_arn: 'arn', + web_identity_token_file: token_file_path, + role_session_name: 'session' + ) + c.source = :none + c.credentials + end + + it 'is called with the correct metrics when source is profile' do + allow(credentials).to receive(:expiration).and_return(Time.now) + expect(File).to receive(:read).with(token_file_path).exactly(2).times + expect_any_instance_of(AssumeRoleWebIdentityCredentials).to receive(:with_metrics).with([]).and_return(resp) + expect_any_instance_of(AssumeRoleWebIdentityCredentials).to receive(:with_metrics).with(['CREDENTIALS_PROFILE_STS_WEB_ID_TOKEN']).and_return(resp) + c = AssumeRoleWebIdentityCredentials.new( + role_arn: 'arn', + web_identity_token_file: token_file_path, + role_session_name: 'session' + ) + c.source = :profile + c.credentials + end + + it 'is called with the correct metrics when source is env' do + allow(credentials).to receive(:expiration).and_return(Time.now) + expect(File).to receive(:read).with(token_file_path).exactly(2).times + expect_any_instance_of(AssumeRoleWebIdentityCredentials).to receive(:with_metrics).with([]).and_return(resp) + expect_any_instance_of(AssumeRoleWebIdentityCredentials).to receive(:with_metrics).with(['CREDENTIALS_ENV_VARS_STS_WEB_ID_TOKEN']).and_return(resp) + c = AssumeRoleWebIdentityCredentials.new( + role_arn: 'arn', + web_identity_token_file: token_file_path, + role_session_name: 'session' + ) + c.source = :env + c.credentials + end + end + end end end From 9693b9ed04cd6d82d48b122a7100b6b3ba94e1cb Mon Sep 17 00:00:00 2001 From: Richard Wang Date: Fri, 28 Mar 2025 13:17:00 -0700 Subject: [PATCH 37/59] Remove metrics from refresh --- .../aws-sdk-core/assume_role_credentials.rb | 7 +-- .../assume_role_web_identity_credentials.rb | 8 +-- .../lib/aws-sdk-core/sso_credentials.rb | 35 +++++------- .../spec/aws/assume_role_credentials_spec.rb | 48 ---------------- ...sume_role_web_identity_credentials_spec.rb | 55 ------------------- 5 files changed, 16 insertions(+), 137 deletions(-) diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_credentials.rb b/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_credentials.rb index 64069069ed6..8d82df5935f 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_credentials.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_credentials.rb @@ -96,8 +96,7 @@ def metrics private def refresh - metric = metrics[0...-1] - resp = with_metrics(metric) { @client.assume_role(@assume_role_params) } + resp = @client.assume_role(@assume_role_params) creds = resp.credentials @credentials = Credentials.new( creds.access_key_id, @@ -117,10 +116,6 @@ def insert_metric(base, metrics) base.insert(1, *metrics) end - def with_metrics(metrics, &block) - Aws::Plugins::UserAgent.metric(*metrics, &block) - end - class << self # @api private diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_web_identity_credentials.rb b/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_web_identity_credentials.rb index 78a03b4adf9..5860b62e54e 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_web_identity_credentials.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_web_identity_credentials.rb @@ -86,9 +86,7 @@ def metrics def refresh # read from token file everytime it refreshes @assume_role_web_identity_params[:web_identity_token] = _token_from_file(@token_file) - metric = metrics[0...-1] - puts "Refreshing with metrics #{metric}" - resp = with_metrics(metric) { @client.assume_role_with_web_identity(@assume_role_web_identity_params) } + resp = @client.assume_role_with_web_identity(@assume_role_web_identity_params) creds = resp.credentials @credentials = Credentials.new( creds.access_key_id, @@ -115,10 +113,6 @@ def parse_account_id(resp) ARNParser.parse(arn).account_id if ARNParser.arn?(arn) end - def with_metrics(metrics, &block) - Aws::Plugins::UserAgent.metric(*metrics, &block) - end - class << self # @api private diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/sso_credentials.rb b/gems/aws-sdk-core/lib/aws-sdk-core/sso_credentials.rb index 3c604a09931..5dc91c367e9 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/sso_credentials.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/sso_credentials.rb @@ -157,23 +157,20 @@ def read_cached_token end def refresh - metric = metrics[0...-1] - c = with_metrics(metric) do - if @legacy - cached_token = read_cached_token - @client.get_role_credentials( - account_id: @sso_account_id, - role_name: @sso_role_name, - access_token: cached_token['accessToken'] - ).role_credentials - else - @client.get_role_credentials( - account_id: @sso_account_id, - role_name: @sso_role_name, - access_token: @token_provider.token.token - ).role_credentials - end - end + c = if @legacy + cached_token = read_cached_token + @client.get_role_credentials( + account_id: @sso_account_id, + role_name: @sso_role_name, + access_token: cached_token['accessToken'] + ).role_credentials + else + @client.get_role_credentials( + account_id: @sso_account_id, + role_name: @sso_role_name, + access_token: @token_provider.token.token + ).role_credentials + end @credentials = Credentials.new( c.access_key_id, @@ -191,9 +188,5 @@ def sso_cache_file # Dir.home raises ArgumentError when ENV['home'] is not set raise ArgumentError, "Unable to load sso_cache_file: ENV['HOME'] is not set." end - - def with_metrics(metrics, &block) - Aws::Plugins::UserAgent.metric(*metrics, &block) - end end end diff --git a/gems/aws-sdk-core/spec/aws/assume_role_credentials_spec.rb b/gems/aws-sdk-core/spec/aws/assume_role_credentials_spec.rb index 12afe78b08c..46e02d7b3bf 100644 --- a/gems/aws-sdk-core/spec/aws/assume_role_credentials_spec.rb +++ b/gems/aws-sdk-core/spec/aws/assume_role_credentials_spec.rb @@ -298,54 +298,6 @@ module Aws expect(c.metrics).to eq(%w[CREDENTIALS_PROFILE_NAMED_PROVIDER CREDENTIALS_HTTP CREDENTIALS_STS_ASSUME_ROLE]) end end - - - end - - describe '#with_metrics' do - it 'is called with the correct metrics when initializing credentials' do - expect_any_instance_of(AssumeRoleCredentials).to receive(:with_metrics).with([]).and_return(resp) - AssumeRoleCredentials.new( - role_arn: 'arn', - role_session_name: 'session' - ) - end - - context 'refreshing expired credentials' do - it 'is called with the correct metrics when source is none' do - allow(credentials).to receive(:expiration).and_return(Time.now) - expect_any_instance_of(AssumeRoleCredentials).to receive(:with_metrics).with([]).and_return(resp) - expect_any_instance_of(AssumeRoleCredentials).to receive(:with_metrics).with([]).and_return(resp) - c = AssumeRoleCredentials.new( - role_arn: 'arn', - role_session_name: 'session') - c.source = :none - c.credentials - end - - it 'is called with the correct metrics when source is static' do - allow(credentials).to receive(:expiration).and_return(Time.now) - expect_any_instance_of(AssumeRoleCredentials).to receive(:with_metrics).with([]).and_return(resp) - expect_any_instance_of(AssumeRoleCredentials).to receive(:with_metrics).with(%w[CREDENTIALS_PROFILE_SOURCE_PROFILE CREDENTIALS_PROFILE]).and_return(resp) - c = AssumeRoleCredentials.new( - role_arn: 'arn', - role_session_name: 'session') - c.source = :static - c.credentials - end - - it 'is called with the correct metrics when source is webID' do - allow(credentials).to receive(:expiration).and_return(Time.now) - expect_any_instance_of(AssumeRoleCredentials).to receive(:with_metrics).with([]).and_return(resp) - expect_any_instance_of(AssumeRoleCredentials).to receive(:with_metrics).with([]).and_return(resp) - c = AssumeRoleCredentials.new( - role_arn: 'arn', - role_session_name: 'session') - c.source = :none - c.credentials - end - - end end end end diff --git a/gems/aws-sdk-core/spec/aws/assume_role_web_identity_credentials_spec.rb b/gems/aws-sdk-core/spec/aws/assume_role_web_identity_credentials_spec.rb index 11a923f2440..3aa1deb753d 100644 --- a/gems/aws-sdk-core/spec/aws/assume_role_web_identity_credentials_spec.rb +++ b/gems/aws-sdk-core/spec/aws/assume_role_web_identity_credentials_spec.rb @@ -254,60 +254,5 @@ module Aws expect(c.metrics).to eq(%w[CREDENTIALS_ENV_VARS_STS_WEB_ID_TOKEN CREDENTIALS_STS_ASSUME_ROLE_WEB_ID]) end end - - describe '#with_metrics' do - it 'is called with the correct metrics when initializing credentials' do - expect_any_instance_of(AssumeRoleWebIdentityCredentials).to receive(:with_metrics).with([]).and_return(resp) - AssumeRoleWebIdentityCredentials.new( - role_arn: 'arn', - web_identity_token_file: token_file_path, - role_session_name: 'session' - ) - end - - context 'refreshing expired credentials' do - it 'is called with the correct metrics when source is none' do - allow(credentials).to receive(:expiration).and_return(Time.now) - expect(File).to receive(:read).with(token_file_path).exactly(2).times - expect_any_instance_of(AssumeRoleWebIdentityCredentials).to receive(:with_metrics).with([]).and_return(resp) - expect_any_instance_of(AssumeRoleWebIdentityCredentials).to receive(:with_metrics).with([]).and_return(resp) - c = AssumeRoleWebIdentityCredentials.new( - role_arn: 'arn', - web_identity_token_file: token_file_path, - role_session_name: 'session' - ) - c.source = :none - c.credentials - end - - it 'is called with the correct metrics when source is profile' do - allow(credentials).to receive(:expiration).and_return(Time.now) - expect(File).to receive(:read).with(token_file_path).exactly(2).times - expect_any_instance_of(AssumeRoleWebIdentityCredentials).to receive(:with_metrics).with([]).and_return(resp) - expect_any_instance_of(AssumeRoleWebIdentityCredentials).to receive(:with_metrics).with(['CREDENTIALS_PROFILE_STS_WEB_ID_TOKEN']).and_return(resp) - c = AssumeRoleWebIdentityCredentials.new( - role_arn: 'arn', - web_identity_token_file: token_file_path, - role_session_name: 'session' - ) - c.source = :profile - c.credentials - end - - it 'is called with the correct metrics when source is env' do - allow(credentials).to receive(:expiration).and_return(Time.now) - expect(File).to receive(:read).with(token_file_path).exactly(2).times - expect_any_instance_of(AssumeRoleWebIdentityCredentials).to receive(:with_metrics).with([]).and_return(resp) - expect_any_instance_of(AssumeRoleWebIdentityCredentials).to receive(:with_metrics).with(['CREDENTIALS_ENV_VARS_STS_WEB_ID_TOKEN']).and_return(resp) - c = AssumeRoleWebIdentityCredentials.new( - role_arn: 'arn', - web_identity_token_file: token_file_path, - role_session_name: 'session' - ) - c.source = :env - c.credentials - end - end - end end end From 0398f249e59355b4a50a70135cf28ced7166686d Mon Sep 17 00:00:00 2001 From: Richard Wang Date: Fri, 28 Mar 2025 14:23:03 -0700 Subject: [PATCH 38/59] Clean up code --- .../assume_role_web_identity_credentials.rb | 1 + .../aws-sdk-core/credential_provider_chain.rb | 7 +------ .../lib/aws-sdk-core/plugins/sign.rb | 10 +--------- .../lib/aws-sdk-core/plugins/user_agent.rb | 5 ++--- ...sume_role_web_identity_credentials_spec.rb | 20 +++++++++---------- 5 files changed, 15 insertions(+), 28 deletions(-) diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_web_identity_credentials.rb b/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_web_identity_credentials.rb index 5860b62e54e..81a63bf9064 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_web_identity_credentials.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_web_identity_credentials.rb @@ -86,6 +86,7 @@ def metrics def refresh # read from token file everytime it refreshes @assume_role_web_identity_params[:web_identity_token] = _token_from_file(@token_file) + resp = @client.assume_role_with_web_identity(@assume_role_web_identity_params) creds = resp.credentials @credentials = Credentials.new( diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/credential_provider_chain.rb b/gems/aws-sdk-core/lib/aws-sdk-core/credential_provider_chain.rb index df8c3eeffed..989d5281f05 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/credential_provider_chain.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/credential_provider_chain.rb @@ -9,14 +9,9 @@ def initialize(config = nil) # @return [CredentialProvider, nil] def resolve - puts "RESOLVING CREDENTIALS" providers.each do |method_name, options| provider = send(method_name, options.merge(config: @config)) - if provider && provider.set? - puts method_name - puts provider - return provider - end + return provider if provider && provider.set? end nil end diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/plugins/sign.rb b/gems/aws-sdk-core/lib/aws-sdk-core/plugins/sign.rb index fed05d46462..5a036c7aef8 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/plugins/sign.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/plugins/sign.rb @@ -49,10 +49,7 @@ def call(context) context[:sigv4_region], context[:sigv4_credentials] ) - # TODO: temp added this, double check - if signer.is_a?(SignatureV4) - credentials = signer.signer.credentials_provider - end + credentials = signer.signer.credentials_provider if signer.is_a?(SignatureV4) signer.sign(context) end with_metrics(credentials) { @handler.call(context) } @@ -61,16 +58,11 @@ def call(context) private def with_metrics(credentials, &block) - puts "in with metric" unless credentials && credentials.respond_to?(:metrics) - puts "No metrics" return block.call end - puts credentials metrics = [] - puts credentials.class.name - puts credentials.metrics (metrics << credentials.metrics).flatten! Aws::Plugins::UserAgent.metric(*metrics, &block) end diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/plugins/user_agent.rb b/gems/aws-sdk-core/lib/aws-sdk-core/plugins/user_agent.rb index a7c01eadd92..ae62ef04c00 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/plugins/user_agent.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/plugins/user_agent.rb @@ -106,7 +106,6 @@ def call(context) def set_user_agent(context) context.http_request.headers['User-Agent'] = UserAgent.new(context).to_s - puts context.http_request.headers['User-Agent'] end class UserAgent @@ -217,8 +216,8 @@ def metric_metadata Thread.current[:aws_sdk_core_user_agent_metric].uniq! metrics = Thread.current[:aws_sdk_core_user_agent_metric].join(',') - puts "User agent metrics" - puts metrics + # puts "User agent metrics" + # puts metrics # Metric metadata is limited to 1024 bytes return "m/#{metrics}" if metrics.bytesize <= 1024 diff --git a/gems/aws-sdk-core/spec/aws/assume_role_web_identity_credentials_spec.rb b/gems/aws-sdk-core/spec/aws/assume_role_web_identity_credentials_spec.rb index 3aa1deb753d..4adc78d4f1c 100644 --- a/gems/aws-sdk-core/spec/aws/assume_role_web_identity_credentials_spec.rb +++ b/gems/aws-sdk-core/spec/aws/assume_role_web_identity_credentials_spec.rb @@ -59,7 +59,7 @@ module Aws creds = AssumeRoleWebIdentityCredentials.new( role_arn: 'arn', web_identity_token_file: token_file_path, - role_session_name: 'session-name' + role_session_name: "session-name" ) expect(creds.client).to be(client) end @@ -70,7 +70,7 @@ module Aws creds = AssumeRoleWebIdentityCredentials.new( role_arn: 'arn', web_identity_token_file: token_file_path, - role_session_name: 'session-name', + role_session_name: "session-name", before_refresh: proc { } ) expect(creds.client).to be(client) @@ -107,12 +107,12 @@ module Aws expect(client).to receive(:assume_role_with_web_identity).with({ role_arn: 'arn', web_identity_token: 'token', - role_session_name: 'session-name' + role_session_name: "session-name" }) AssumeRoleWebIdentityCredentials.new( role_arn: 'arn', web_identity_token_file: token_file_path, - role_session_name: 'session-name' + role_session_name: "session-name" ) end @@ -142,16 +142,16 @@ module Aws expect(client).to receive(:assume_role_with_web_identity).with({ role_arn: 'arn', web_identity_token: '', - role_session_name: 'session-name', - provider_id: 'urlType', - policy: 'sessionPolicyDocumentType' + role_session_name: "session-name", + provider_id: "urlType", + policy: "sessionPolicyDocumentType" }) AssumeRoleWebIdentityCredentials.new( role_arn: 'arn', web_identity_token_file: token_file_path, - role_session_name: 'session-name', - provider_id: 'urlType', - policy: 'sessionPolicyDocumentType' + role_session_name: "session-name", + provider_id: "urlType", + policy: "sessionPolicyDocumentType" ) end From ad3e569ad2a87848ecdb70132c2a114957fb461b Mon Sep 17 00:00:00 2001 From: Richard Wang Date: Tue, 1 Apr 2025 09:37:15 -0700 Subject: [PATCH 39/59] Make changes from PR feedback --- .../aws-sdk-core/assume_role_credentials.rb | 6 +++--- .../assume_role_web_identity_credentials.rb | 11 ++++++----- .../aws-sdk-core/credential_provider_chain.rb | 18 +++++++++++------- .../lib/aws-sdk-core/credentials.rb | 4 ++-- .../lib/aws-sdk-core/plugins/sign.rb | 10 ++++++---- .../lib/aws-sdk-core/plugins/user_agent.rb | 5 +++-- .../lib/aws-sdk-core/process_credentials.rb | 12 +++++++++++- .../lib/aws-sdk-core/shared_config.rb | 8 ++++++-- .../lib/aws-sdk-core/sso_credentials.rb | 4 ++-- .../aws/credential_resolution_chain_spec.rb | 2 +- 10 files changed, 51 insertions(+), 29 deletions(-) diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_credentials.rb b/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_credentials.rb index 8d82df5935f..1c93905ee52 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_credentials.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_credentials.rb @@ -50,7 +50,7 @@ def initialize(options = {}) end @client = client_opts[:client] || STS::Client.new(client_opts) @async_refresh = true - @source = :none + @source = :code super end @@ -74,11 +74,11 @@ def metrics end case @source - when :none + when :code ['CREDENTIALS_STS_ASSUME_ROLE'] when :static insert_metric(source_profile, 'CREDENTIALS_PROFILE') - when :webID + when :web_ID insert_metric(source_profile, %w[CREDENTIALS_PROFILE_STS_WEB_ID_TOKEN CREDENTIALS_STS_ASSUME_ROLE_WEB_ID]) when :process insert_metric(source_profile, %w[CREDENTIALS_PROFILE_PROCESS CREDENTIALS_PROCESS]) diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_web_identity_credentials.rb b/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_web_identity_credentials.rb index 81a63bf9064..9108ad37229 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_web_identity_credentials.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_web_identity_credentials.rb @@ -61,7 +61,7 @@ def initialize(options = {}) @assume_role_web_identity_params[:role_session_name] = _session_name end @client = client_opts[:client] || STS::Client.new(client_opts.merge(credentials: nil)) - @source = :none + @source = :code super end @@ -71,13 +71,14 @@ def initialize(options = {}) attr_accessor :source def metrics + base = ['CREDENTIALS_STS_ASSUME_ROLE_WEB_ID'] case @source - when :none - ['CREDENTIALS_STS_ASSUME_ROLE_WEB_ID'] + when :code + base when :profile - %w[CREDENTIALS_PROFILE_STS_WEB_ID_TOKEN CREDENTIALS_STS_ASSUME_ROLE_WEB_ID] + base.unshift('CREDENTIALS_PROFILE_STS_WEB_ID_TOKEN') when :env - %w[CREDENTIALS_ENV_VARS_STS_WEB_ID_TOKEN CREDENTIALS_STS_ASSUME_ROLE_WEB_ID] + base.unshift('CREDENTIALS_ENV_VARS_STS_WEB_ID_TOKEN') end end diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/credential_provider_chain.rb b/gems/aws-sdk-core/lib/aws-sdk-core/credential_provider_chain.rb index 989d5281f05..16c0d05b2b0 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/credential_provider_chain.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/credential_provider_chain.rb @@ -87,7 +87,11 @@ def static_profile_credentials(options) def static_profile_process_credentials(options) if Aws.shared_config.config_enabled? && options[:config] && options[:config].profile process_provider = Aws.shared_config.credential_process(profile: options[:config].profile) - ProcessCredentials.new([process_provider]) if process_provider + if process_provider + credentials = ProcessCredentials.new([process_provider]) + credentials.source = :profile + credentials + end end rescue Errors::NoSuchProfileError nil @@ -131,7 +135,11 @@ def process_credentials(options) profile_name = determine_profile_name(options) if Aws.shared_config.config_enabled? process_provider = Aws.shared_config.credential_process(profile: profile_name) - ProcessCredentials.new([process_provider]) if process_provider + if process_provider + credentials = ProcessCredentials.new([process_provider]) + credentials.source = :profile + credentials + end end rescue Errors::NoSuchProfileError nil @@ -161,7 +169,7 @@ def assume_role_web_identity_credentials(options) role_session_name: ENV['AWS_ROLE_SESSION_NAME'] } cfg[:region] = region if region - with_metrics('CREDENTIALS_ENV_VARS_STS_WEB_ID_TOKEN') do + Aws::Plugins::UserAgent.metric('CREDENTIALS_ENV_VARS_STS_WEB_ID_TOKEN') do credentials = AssumeRoleWebIdentityCredentials.new(cfg) credentials.source = :env credentials @@ -195,9 +203,5 @@ def assume_role_with_profile(options, profile_name) end Aws.shared_config.assume_role_credentials_from_config(assume_opts) end - - def with_metrics(metric, &block) - Aws::Plugins::UserAgent.metric(metric, &block) - end end end diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/credentials.rb b/gems/aws-sdk-core/lib/aws-sdk-core/credentials.rb index 1b202b8916b..210670c75ce 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/credentials.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/credentials.rb @@ -14,7 +14,7 @@ def initialize(access_key_id, secret_access_key, session_token = nil, @secret_access_key = secret_access_key @session_token = session_token @account_id = kwargs[:account_id] - @source = :none + @source = :code end # @return [String] @@ -53,7 +53,7 @@ def inspect def metrics case @source - when :none + when :code ['CREDENTIALS_CODE'] when :profile ['CREDENTIALS_PROFILE'] diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/plugins/sign.rb b/gems/aws-sdk-core/lib/aws-sdk-core/plugins/sign.rb index 5a036c7aef8..cfd1b35aa14 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/plugins/sign.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/plugins/sign.rb @@ -49,7 +49,7 @@ def call(context) context[:sigv4_region], context[:sigv4_credentials] ) - credentials = signer.signer.credentials_provider if signer.is_a?(SignatureV4) + credentials = signer.credentials if signer.is_a?(SignatureV4) signer.sign(context) end with_metrics(credentials) { @handler.call(context) } @@ -62,9 +62,7 @@ def with_metrics(credentials, &block) return block.call end - metrics = [] - (metrics << credentials.metrics).flatten! - Aws::Plugins::UserAgent.metric(*metrics, &block) + Aws::Plugins::UserAgent.metric(*credentials.metrics, &block) end def v2_signing?(config) @@ -169,6 +167,10 @@ def sign_event(*args) @signer.sign_event(*args) end + def credentials + @signer.credentials_provider + end + private def apply_authtype(context, req) diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/plugins/user_agent.rb b/gems/aws-sdk-core/lib/aws-sdk-core/plugins/user_agent.rb index ae62ef04c00..7ffbb08f247 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/plugins/user_agent.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/plugins/user_agent.rb @@ -216,8 +216,8 @@ def metric_metadata Thread.current[:aws_sdk_core_user_agent_metric].uniq! metrics = Thread.current[:aws_sdk_core_user_agent_metric].join(',') - # puts "User agent metrics" - # puts metrics + puts "User agent metrics" + puts metrics # Metric metadata is limited to 1024 bytes return "m/#{metrics}" if metrics.bytesize <= 1024 @@ -228,6 +228,7 @@ def metric_metadata end end + # Priority set to 5 in order to add credentials related metrics from Sign plugin handler(Handler, step: :sign, priority: 5) end end diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/process_credentials.rb b/gems/aws-sdk-core/lib/aws-sdk-core/process_credentials.rb index f50110bb3ab..5bc2f5d7fe4 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/process_credentials.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/process_credentials.rb @@ -36,12 +36,22 @@ def initialize(process) @process = process @credentials = credentials_from_process @async_refresh = false + @source = :code super end + attr_accessor :source + def metrics - %w[CREDENTIALS_PROFILE_PROCESS CREDENTIALS_PROCESS] + base = ['CREDENTIALS_PROCESS'] + + case @source + when :code + base + when :profile + base.unshift('CREDENTIALS_PROFILE_PROCESS') + end end private diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/shared_config.rb b/gems/aws-sdk-core/lib/aws-sdk-core/shared_config.rb index 56fe15a2f07..d66b38b2e26 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/shared_config.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/shared_config.rb @@ -342,7 +342,7 @@ def resolve_source_profile(profile, opts = {}) [creds, creds, creds.source] elsif (provider = assume_role_web_identity_credentials_from_config(opts.merge(profile: profile))) provider.credentials.source = :assume_role_resolution - [provider.credentials, provider, :webID] if provider.credentials.set? + [provider.credentials, provider, :web_ID] if provider.credentials.set? elsif (provider = assume_role_process_credentials_from_config(profile)) provider.credentials.source = :assume_role_resolution [provider.credentials, provider, :process] if provider.credentials.set? @@ -374,7 +374,11 @@ def assume_role_process_credentials_from_config(profile) if @parsed_config credential_process ||= @parsed_config.fetch(profile, {})['credential_process'] end - ProcessCredentials.new([credential_process]) if credential_process + if credential_process + credentials = ProcessCredentials.new([credential_process]) + credentials.source = :profile + credentials + end end def credentials_from_shared(profile, _opts) diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/sso_credentials.rb b/gems/aws-sdk-core/lib/aws-sdk-core/sso_credentials.rb index 5dc91c367e9..b0b4b1e7e2b 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/sso_credentials.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/sso_credentials.rb @@ -114,7 +114,7 @@ def initialize(options = {}) end @async_refresh = true - @source = :none + @source = :code super end @@ -130,7 +130,7 @@ def metrics when :legacy %w[CREDENTIALS_PROFILE_SSO_LEGACY CREDENTIALS_SSO_LEGACY] # TODO: Check if Ruby has "source-less" SSO credentials - when :none + when :code if @legacy ['CREDENTIALS_SSO_LEGACY'] else diff --git a/gems/aws-sdk-core/spec/aws/credential_resolution_chain_spec.rb b/gems/aws-sdk-core/spec/aws/credential_resolution_chain_spec.rb index 23c0b3cd759..e3ad5172fa1 100644 --- a/gems/aws-sdk-core/spec/aws/credential_resolution_chain_spec.rb +++ b/gems/aws-sdk-core/spec/aws/credential_resolution_chain_spec.rb @@ -453,7 +453,7 @@ module Aws ).to eq('AR_AKID') expect( client.config.credentials.source - ).to eq(:webID) + ).to eq(:web_ID) expect( client.config.credentials.metrics ).to eq(%w[CREDENTIALS_PROFILE_SOURCE_PROFILE CREDENTIALS_PROFILE_STS_WEB_ID_TOKEN From bf62f37d12c0230209c74282fb514c04af4852b5 Mon Sep 17 00:00:00 2001 From: Richard Wang Date: Tue, 1 Apr 2025 14:56:20 -0700 Subject: [PATCH 40/59] Fix tests --- .../aws-sdk-core/assume_role_credentials.rb | 6 +- .../assume_role_web_identity_credentials.rb | 6 +- .../aws-sdk-core/credential_provider_chain.rb | 10 +- .../lib/aws-sdk-core/credentials.rb | 6 +- .../lib/aws-sdk-core/plugins/user_agent.rb | 4 +- .../lib/aws-sdk-core/process_credentials.rb | 6 +- .../lib/aws-sdk-core/shared_config.rb | 34 ++- .../lib/aws-sdk-core/sso_credentials.rb | 6 +- .../spec/aws/assume_role_credentials_spec.rb | 79 ++++--- ...sume_role_web_identity_credentials_spec.rb | 28 +-- .../aws/credential_resolution_chain_spec.rb | 205 +++--------------- .../aws-sdk-core/spec/aws/credentials_spec.rb | 10 +- .../spec/aws/plugins/sign_spec.rb | 18 +- .../spec/aws/process_credentials_spec.rb | 9 +- .../spec/aws/sso_credentials_spec.rb | 8 +- gems/aws-sdk-core/spec/sigv4_helper.rb | 2 +- 16 files changed, 147 insertions(+), 290 deletions(-) diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_credentials.rb b/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_credentials.rb index 1c93905ee52..48fbf30f371 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_credentials.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_credentials.rb @@ -50,7 +50,7 @@ def initialize(options = {}) end @client = client_opts[:client] || STS::Client.new(client_opts) @async_refresh = true - @source = :code + @metrics_source = :code super end @@ -60,7 +60,7 @@ def initialize(options = {}) # @return [Hash] attr_reader :assume_role_params - attr_accessor :source + attr_accessor :metrics_source attr_accessor :resolving @@ -73,7 +73,7 @@ def metrics credential_source.pop end - case @source + case @metrics_source when :code ['CREDENTIALS_STS_ASSUME_ROLE'] when :static diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_web_identity_credentials.rb b/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_web_identity_credentials.rb index 9108ad37229..dcdc75845fd 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_web_identity_credentials.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_web_identity_credentials.rb @@ -61,18 +61,18 @@ def initialize(options = {}) @assume_role_web_identity_params[:role_session_name] = _session_name end @client = client_opts[:client] || STS::Client.new(client_opts.merge(credentials: nil)) - @source = :code + @metrics_source = :code super end # @return [STS::Client] attr_reader :client - attr_accessor :source + attr_accessor :metrics_source def metrics base = ['CREDENTIALS_STS_ASSUME_ROLE_WEB_ID'] - case @source + case @metrics_source when :code base when :profile diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/credential_provider_chain.rb b/gems/aws-sdk-core/lib/aws-sdk-core/credential_provider_chain.rb index 16c0d05b2b0..89547bcbedb 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/credential_provider_chain.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/credential_provider_chain.rb @@ -48,7 +48,7 @@ def static_credentials(options) options[:config].session_token, account_id: options[:config].account_id ) - credentials.source = :profile + credentials.metrics_source = :profile credentials end end @@ -89,7 +89,7 @@ def static_profile_process_credentials(options) process_provider = Aws.shared_config.credential_process(profile: options[:config].profile) if process_provider credentials = ProcessCredentials.new([process_provider]) - credentials.source = :profile + credentials.metrics_source = :profile credentials end end @@ -109,7 +109,7 @@ def env_credentials(_options) envar(token), account_id: envar(account_id) ) - credentials.source = :env + credentials.metrics_source = :env credentials end @@ -137,7 +137,7 @@ def process_credentials(options) process_provider = Aws.shared_config.credential_process(profile: profile_name) if process_provider credentials = ProcessCredentials.new([process_provider]) - credentials.source = :profile + credentials.metrics_source = :profile credentials end end @@ -171,7 +171,7 @@ def assume_role_web_identity_credentials(options) cfg[:region] = region if region Aws::Plugins::UserAgent.metric('CREDENTIALS_ENV_VARS_STS_WEB_ID_TOKEN') do credentials = AssumeRoleWebIdentityCredentials.new(cfg) - credentials.source = :env + credentials.metrics_source = :env credentials end elsif Aws.shared_config.config_enabled? diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/credentials.rb b/gems/aws-sdk-core/lib/aws-sdk-core/credentials.rb index 210670c75ce..a833aa1a311 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/credentials.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/credentials.rb @@ -14,7 +14,7 @@ def initialize(access_key_id, secret_access_key, session_token = nil, @secret_access_key = secret_access_key @session_token = session_token @account_id = kwargs[:account_id] - @source = :code + @metrics_source = :code end # @return [String] @@ -29,7 +29,7 @@ def initialize(access_key_id, secret_access_key, session_token = nil, # @return [String, nil] attr_reader :account_id - attr_accessor :source + attr_accessor :metrics_source # @return [Credentials] def credentials @@ -52,7 +52,7 @@ def inspect end def metrics - case @source + case @metrics_source when :code ['CREDENTIALS_CODE'] when :profile diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/plugins/user_agent.rb b/gems/aws-sdk-core/lib/aws-sdk-core/plugins/user_agent.rb index 7ffbb08f247..df99b8c7e3b 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/plugins/user_agent.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/plugins/user_agent.rb @@ -216,8 +216,8 @@ def metric_metadata Thread.current[:aws_sdk_core_user_agent_metric].uniq! metrics = Thread.current[:aws_sdk_core_user_agent_metric].join(',') - puts "User agent metrics" - puts metrics + # puts "User agent metrics" + # puts metrics # Metric metadata is limited to 1024 bytes return "m/#{metrics}" if metrics.bytesize <= 1024 diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/process_credentials.rb b/gems/aws-sdk-core/lib/aws-sdk-core/process_credentials.rb index 5bc2f5d7fe4..c859a7be39e 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/process_credentials.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/process_credentials.rb @@ -36,17 +36,17 @@ def initialize(process) @process = process @credentials = credentials_from_process @async_refresh = false - @source = :code + @metrics_source = :code super end - attr_accessor :source + attr_accessor :metrics_source def metrics base = ['CREDENTIALS_PROCESS'] - case @source + case @metrics_source when :code base when :profile diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/shared_config.rb b/gems/aws-sdk-core/lib/aws-sdk-core/shared_config.rb index d66b38b2e26..f53b5a17ca8 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/shared_config.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/shared_config.rb @@ -140,7 +140,7 @@ def assume_role_web_identity_credentials_from_config(opts = {}) cfg[:region] = opts[:region] if opts[:region] with_metrics('CREDENTIALS_PROFILE_STS_WEB_ID_TOKEN') do credentials = AssumeRoleWebIdentityCredentials.new(cfg) - credentials.source = :profile + credentials.metrics_source = :profile credentials end end @@ -281,7 +281,7 @@ def assume_role_from_profile(cfg, profile, opts, chain_config) end with_metrics(metrics) do credentials = AssumeRoleCredentials.new(opts) - credentials.source = source + credentials.metrics_source = source credentials end else @@ -308,7 +308,7 @@ def assume_role_from_profile(cfg, profile, opts, chain_config) metrics.unshift('CREDENTIALS_PROFILE_NAMED_PROVIDER') if metrics.first != 'CREDENTIALS_PROFILE_NAMED_PROVIDER' with_metrics(metrics) do credentials = AssumeRoleCredentials.new(opts) - credentials.source = source + credentials.metrics_source = source credentials end else @@ -334,33 +334,35 @@ def resolve_source_profile(profile, opts = {}) end if (creds = credentials(profile: profile)) - creds.source = :profile + creds.metrics_source = :profile [creds, creds, :static] # static credentials elsif profile_config && profile_config['source_profile'] opts.delete(:source_profile) creds = assume_role_credentials_from_config(opts.merge(profile: profile)) - [creds, creds, creds.source] + [creds, creds, creds.metrics_source] elsif (provider = assume_role_web_identity_credentials_from_config(opts.merge(profile: profile))) - provider.credentials.source = :assume_role_resolution + provider.credentials.metrics_source = :assume_role_resolution [provider.credentials, provider, :web_ID] if provider.credentials.set? elsif (provider = assume_role_process_credentials_from_config(profile)) - provider.credentials.source = :assume_role_resolution + provider.credentials.metrics_source = :assume_role_resolution [provider.credentials, provider, :process] if provider.credentials.set? elsif (provider = sso_credentials_from_config(profile: profile)) - provider.credentials.source = :assume_role_resolution - [provider.credentials, provider, provider.source] + provider.credentials.metrics_source = :assume_role_resolution + [provider.credentials, provider, provider.metrics_source] end end def credentials_from_source(credential_source, config) case credential_source when 'Ec2InstanceMetadata' - [InstanceProfileCredentials.new( + [ + InstanceProfileCredentials.new( retries: config ? config.instance_profile_credentials_retries : 0, http_open_timeout: config ? config.instance_profile_credentials_timeout : 1, http_read_timeout: config ? config.instance_profile_credentials_timeout : 1, ), - :instance] + :instance + ] when 'EcsContainer' [ECSCredentials.new, :ecs] else @@ -376,7 +378,7 @@ def assume_role_process_credentials_from_config(profile) end if credential_process credentials = ProcessCredentials.new([credential_process]) - credentials.source = :profile + credentials.metrics_source = :profile credentials end end @@ -431,7 +433,7 @@ def sso_credentials_from_profile(cfg, profile) sso_region: sso_region, sso_start_url: sso_start_url, ) - credentials.source = prof_config['sso_session'] ? :new : :legacy + credentials.metrics_source = prof_config['sso_session'] ? :new : :legacy credentials end end @@ -523,11 +525,7 @@ def sso_session(cfg, profile, sso_session_name) end def with_metrics(metrics, &block) - if metrics.is_a?(Array) - Aws::Plugins::UserAgent.metric(*metrics, &block) - else - Aws::Plugins::UserAgent.metric(metrics, &block) - end + Aws::Plugins::UserAgent.metric(*metrics, &block) end end end diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/sso_credentials.rb b/gems/aws-sdk-core/lib/aws-sdk-core/sso_credentials.rb index b0b4b1e7e2b..9e4379a3ad9 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/sso_credentials.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/sso_credentials.rb @@ -114,17 +114,17 @@ def initialize(options = {}) end @async_refresh = true - @source = :code + @metrics_source = :code super end # @return [SSO::Client] attr_reader :client - attr_accessor :source + attr_accessor :metrics_source def metrics - case @source + case @metrics_source when :new %w[CREDENTIALS_PROFILE_SSO CREDENTIALS_SSO] when :legacy diff --git a/gems/aws-sdk-core/spec/aws/assume_role_credentials_spec.rb b/gems/aws-sdk-core/spec/aws/assume_role_credentials_spec.rb index 46e02d7b3bf..b53cb53fd48 100644 --- a/gems/aws-sdk-core/spec/aws/assume_role_credentials_spec.rb +++ b/gems/aws-sdk-core/spec/aws/assume_role_credentials_spec.rb @@ -174,127 +174,122 @@ module Aws expect(before_refresh_called).to be(true) end - it 'defaults the source to none' do + it 'defaults the source to code' do c = AssumeRoleCredentials.new( role_arn: 'arn', role_session_name: 'session' ) - expect(c.source).to eq(:none) + expect(c.metrics_source).to eq(:code) end describe '#metrics' do + let(:creds) do + AssumeRoleCredentials.new( + role_arn: 'arn', + role_session_name: 'session' + ) + end + + let(:resolving_creds) do + c = creds + c.resolving = true + c + end + context 'from code' do it 'returns the correct metrics when the source is none' do - c = AssumeRoleCredentials.new( - role_arn: 'arn', - role_session_name: 'session' - ) + c = creds expect(c.metrics).to eq(['CREDENTIALS_STS_ASSUME_ROLE']) end end context 'while resolving' do - let(:creds) { - c = AssumeRoleCredentials.new( - role_arn: 'arn', - role_session_name: 'session' - ) - c.resolving = true - c - } it 'returns the correct metrics when the source is static' do - c = creds - c.source = :static + c = resolving_creds + c.metrics_source = :static expect(c.metrics).to eq(%w[CREDENTIALS_PROFILE_SOURCE_PROFILE CREDENTIALS_PROFILE]) end it 'returns the correct metrics when the source is webID' do - c = creds - c.source = :webID + c = resolving_creds + c.metrics_source = :web_ID expect(c.metrics).to eq(%w[CREDENTIALS_PROFILE_SOURCE_PROFILE CREDENTIALS_PROFILE_STS_WEB_ID_TOKEN CREDENTIALS_STS_ASSUME_ROLE_WEB_ID]) end it 'returns the correct metrics when the source is process' do - c = creds - c.source = :process + c = resolving_creds + c.metrics_source = :process expect(c.metrics).to eq(%w[CREDENTIALS_PROFILE_SOURCE_PROFILE CREDENTIALS_PROFILE_PROCESS CREDENTIALS_PROCESS]) end it 'returns the correct metrics when the source is new SSO' do - c = creds - c.source = :new + c = resolving_creds + c.metrics_source = :new expect(c.metrics).to eq(%w[CREDENTIALS_PROFILE_SOURCE_PROFILE CREDENTIALS_PROFILE_SSO CREDENTIALS_SSO]) end it 'returns the correct metrics when the source is legacy SSO' do - c = creds - c.source = :legacy + c = resolving_creds + c.metrics_source = :legacy expect(c.metrics).to eq(%w[CREDENTIALS_PROFILE_SOURCE_PROFILE CREDENTIALS_PROFILE_SSO_LEGACY CREDENTIALS_SSO_LEGACY]) end it 'returns the correct metrics when the source is instance' do - c = creds - c.source = :instance + c = resolving_creds + c.metrics_source = :instance expect(c.metrics).to eq(%w[CREDENTIALS_PROFILE_NAMED_PROVIDER CREDENTIALS_IMDS]) end it 'returns the correct metrics when the source is ecs' do - c = creds - c.source = :ecs + c = resolving_creds + c.metrics_source = :ecs expect(c.metrics).to eq(%w[CREDENTIALS_PROFILE_NAMED_PROVIDER CREDENTIALS_HTTP]) end end context 'when resolved' do - let(:creds) { - c = AssumeRoleCredentials.new( - role_arn: 'arn', - role_session_name: 'session' - ) - c - } it 'returns the correct metrics when the source is static' do c = creds - c.source = :static + c.metrics_source = :static expect(c.metrics).to eq(%w[CREDENTIALS_PROFILE_SOURCE_PROFILE CREDENTIALS_PROFILE CREDENTIALS_STS_ASSUME_ROLE]) end it 'returns the correct metrics when the source is webID' do c = creds - c.source = :webID + c.metrics_source = :web_ID expect(c.metrics).to eq(%w[CREDENTIALS_PROFILE_SOURCE_PROFILE CREDENTIALS_PROFILE_STS_WEB_ID_TOKEN CREDENTIALS_STS_ASSUME_ROLE_WEB_ID CREDENTIALS_STS_ASSUME_ROLE]) end it 'returns the correct metrics when the source is process' do c = creds - c.source = :process + c.metrics_source = :process expect(c.metrics).to eq(%w[CREDENTIALS_PROFILE_SOURCE_PROFILE CREDENTIALS_PROFILE_PROCESS CREDENTIALS_PROCESS CREDENTIALS_STS_ASSUME_ROLE]) end it 'returns the correct metrics when the source is new SSO' do c = creds - c.source = :new + c.metrics_source = :new expect(c.metrics).to eq(%w[CREDENTIALS_PROFILE_SOURCE_PROFILE CREDENTIALS_PROFILE_SSO CREDENTIALS_SSO CREDENTIALS_STS_ASSUME_ROLE]) end it 'returns the correct metrics when the source is legacy SSO' do c = creds - c.source = :legacy + c.metrics_source = :legacy expect(c.metrics).to eq(%w[CREDENTIALS_PROFILE_SOURCE_PROFILE CREDENTIALS_PROFILE_SSO_LEGACY CREDENTIALS_SSO_LEGACY CREDENTIALS_STS_ASSUME_ROLE]) end it 'returns the correct metrics when the source is instance' do c = creds - c.source = :instance + c.metrics_source = :instance expect(c.metrics).to eq(%w[CREDENTIALS_PROFILE_NAMED_PROVIDER CREDENTIALS_IMDS CREDENTIALS_STS_ASSUME_ROLE]) end it 'returns the correct metrics when the source is ecs' do c = creds - c.source = :ecs + c.metrics_source = :ecs expect(c.metrics).to eq(%w[CREDENTIALS_PROFILE_NAMED_PROVIDER CREDENTIALS_HTTP CREDENTIALS_STS_ASSUME_ROLE]) end end diff --git a/gems/aws-sdk-core/spec/aws/assume_role_web_identity_credentials_spec.rb b/gems/aws-sdk-core/spec/aws/assume_role_web_identity_credentials_spec.rb index 4adc78d4f1c..7f2e714daab 100644 --- a/gems/aws-sdk-core/spec/aws/assume_role_web_identity_credentials_spec.rb +++ b/gems/aws-sdk-core/spec/aws/assume_role_web_identity_credentials_spec.rb @@ -214,43 +214,39 @@ module Aws c.credentials end - it 'defaults the source to none' do + it 'defaults the source to code' do c = AssumeRoleWebIdentityCredentials.new( role_arn: 'arn', web_identity_token_file: token_file_path, role_session_name: 'session' ) - expect(c.source).to eq(:none) + expect(c.metrics_source).to eq(:code) end describe '#metrics' do - it 'returns the correct metrics when the source is none' do - c = AssumeRoleWebIdentityCredentials.new( + let(:creds) do + AssumeRoleWebIdentityCredentials.new( role_arn: 'arn', web_identity_token_file: token_file_path, role_session_name: 'session' ) + end + + it 'returns the correct metrics when the source is none' do + c = creds expect(c.metrics).to eq(['CREDENTIALS_STS_ASSUME_ROLE_WEB_ID']) end it 'returns the correct metrics when the source is profile' do - c = AssumeRoleWebIdentityCredentials.new( - role_arn: 'arn', - web_identity_token_file: token_file_path, - role_session_name: 'session' - ) - c.source = :profile + c = creds + c.metrics_source = :profile expect(c.metrics).to eq(%w[CREDENTIALS_PROFILE_STS_WEB_ID_TOKEN CREDENTIALS_STS_ASSUME_ROLE_WEB_ID]) end it 'returns the correct metrics when the source is env' do - c = AssumeRoleWebIdentityCredentials.new( - role_arn: 'arn', - web_identity_token_file: token_file_path, - role_session_name: 'session' - ) - c.source = :env + c = creds + c.metrics_source = :env expect(c.metrics).to eq(%w[CREDENTIALS_ENV_VARS_STS_WEB_ID_TOKEN CREDENTIALS_STS_ASSUME_ROLE_WEB_ID]) end end diff --git a/gems/aws-sdk-core/spec/aws/credential_resolution_chain_spec.rb b/gems/aws-sdk-core/spec/aws/credential_resolution_chain_spec.rb index e3ad5172fa1..22b57b0ba44 100644 --- a/gems/aws-sdk-core/spec/aws/credential_resolution_chain_spec.rb +++ b/gems/aws-sdk-core/spec/aws/credential_resolution_chain_spec.rb @@ -58,8 +58,7 @@ module Aws region: 'us-east-1' ) expect(client.config.credentials.access_key_id).to eq('ACCESS_DIRECT') - expect(client.config.credentials.source).to eq(:profile) - expect(client.config.credentials.metrics).to eq(['CREDENTIALS_PROFILE']) + expect(client.config.credentials.metrics_source).to eq(:profile) end it 'prefers assume role credentials when profile explicitly set over ENV credentials' do @@ -79,10 +78,7 @@ module Aws profile: 'assumerole_sc', region: 'us-east-1' ) expect(client.config.credentials.credentials.access_key_id).to eq('AR_AKID') - expect(client.config.credentials.source).to eq(:static) - expect( - client.config.credentials.metrics - ).to eq(%w[CREDENTIALS_PROFILE_SOURCE_PROFILE CREDENTIALS_PROFILE CREDENTIALS_STS_ASSUME_ROLE]) + expect(client.config.credentials.metrics_source).to eq(:static) end it 'prefers assume role web identity from profile over sso' do @@ -98,11 +94,7 @@ module Aws expect( client.config.credentials.credentials.access_key_id ).to eq('AR_AKID') - - expect(client.config.credentials.source).to eq(:profile) - expect( - client.config.credentials.metrics - ).to eq(%w[CREDENTIALS_PROFILE_STS_WEB_ID_TOKEN CREDENTIALS_STS_ASSUME_ROLE_WEB_ID]) + expect(client.config.credentials.metrics_source).to eq(:profile) end it 'prefers assume role web identity from ENV over sso' do @@ -120,14 +112,9 @@ module Aws client = ApiHelper.sample_rest_xml::Client.new( region: 'us-east-1' ) - expect( - client.config.credentials.credentials.access_key_id - ).to eq('AR_AKID') - - expect(client.config.credentials.source).to eq(:env) - expect( - client.config.credentials.metrics - ).to eq(%w[CREDENTIALS_ENV_VARS_STS_WEB_ID_TOKEN CREDENTIALS_STS_ASSUME_ROLE_WEB_ID]) + expect(client.config.credentials.credentials.access_key_id) + .to eq('AR_AKID') + expect(client.config.credentials.metrics_source).to eq(:env) end it 'prefers sso credentials over assume role' do @@ -140,7 +127,7 @@ module Aws sso_role_name: 'SSO_ROLE_NAME', sso_session: 'sso-test-session' ).and_return(creds) - expect(creds).to receive(:source=).with(:new) + expect(creds).to receive(:metrics_source=).with(:new) client = ApiHelper.sample_rest_xml::Client.new( profile: 'sso_creds', token_provider: nil @@ -148,9 +135,6 @@ module Aws expect( client.config.credentials.credentials.access_key_id ).to eq('SSO_AKID') - expect( - client.config.credentials.metrics - ).to eq(%w[CREDENTIALS_PROFILE_SSO CREDENTIALS_SSO]) end it 'loads SSO credentials from a legacy profile' do @@ -163,16 +147,13 @@ module Aws sso_role_name: 'SSO_ROLE_NAME', sso_session: nil ).and_return(creds) - expect(creds).to receive(:source=).with(:legacy) + expect(creds).to receive(:metrics_source=).with(:legacy) client = ApiHelper.sample_rest_xml::Client.new( profile: 'sso_creds_legacy' ) expect( client.config.credentials.credentials.access_key_id ).to eq('SSO_AKID') - expect( - client.config.credentials.metrics - ).to eq(%w[CREDENTIALS_PROFILE_SSO_LEGACY CREDENTIALS_SSO_LEGACY]) end it 'loads SSO credentials from a mixed legacy profile when values match' do @@ -185,7 +166,7 @@ module Aws sso_role_name: 'SSO_ROLE_NAME', sso_session: 'sso-test-session' ).and_return(creds) - expect(creds).to receive(:source=).with(:new) + expect(creds).to receive(:metrics_source=).with(:new) client = ApiHelper.sample_rest_xml::Client.new( profile: 'sso_creds_mixed_legacy', token_provider: nil, @@ -193,9 +174,6 @@ module Aws expect( client.config.credentials.credentials.access_key_id ).to eq('SSO_AKID') - expect( - client.config.credentials.metrics - ).to eq(%w[CREDENTIALS_PROFILE_SSO CREDENTIALS_SSO]) end it 'loads SSO credentials from when the session name has quotes' do @@ -208,7 +186,7 @@ module Aws sso_role_name: 'SSO_ROLE_NAME', sso_session: 'sso test session' ).and_return(creds) - expect(creds).to receive(:source=).with(:new) + expect(creds).to receive(:metrics_source=).with(:new) client = ApiHelper.sample_rest_xml::Client.new( profile: 'sso_creds_session_with_quotes', token_provider: nil @@ -216,9 +194,6 @@ module Aws expect( client.config.credentials.credentials.access_key_id ).to eq('SSO_AKID') - expect( - client.config.credentials.metrics - ).to eq(%w[CREDENTIALS_PROFILE_SSO CREDENTIALS_SSO]) end it 'raises when attempting to load an incomplete SSO Profile' do @@ -264,12 +239,7 @@ module Aws expect( client.config.credentials.credentials.access_key_id ).to eq('AR_AKID') - expect( - client.config.credentials.source - ).to eq(:static) - expect( - client.config.credentials.metrics - ).to eq(%w[CREDENTIALS_PROFILE_SOURCE_PROFILE CREDENTIALS_PROFILE CREDENTIALS_STS_ASSUME_ROLE]) + expect(client.config.credentials.metrics_source).to eq(:static) sts_client = client.config.credentials.client expect( @@ -284,9 +254,6 @@ module Aws expect( client.config.credentials.credentials.access_key_id ).to eq('ACCESS_KEY_CRD') - expect( - client.config.credentials.metrics - ).to eq(['CREDENTIALS_PROFILE']) end it 'will source static credentials from shared config after shared credentials' do @@ -296,9 +263,6 @@ module Aws expect( client.config.credentials.credentials.access_key_id ).to eq('ACCESS_KEY_SC1') - expect( - client.config.credentials.metrics - ).to eq(['CREDENTIALS_PROFILE']) end it 'prefers process credentials over metadata credentials' do @@ -308,9 +272,6 @@ module Aws expect( client.config.credentials.credentials.access_key_id ).to eq('AK_PROC1') - expect( - client.config.credentials.metrics - ).to eq(%w[CREDENTIALS_PROFILE_PROCESS CREDENTIALS_PROCESS]) end it 'prefers direct credentials over process credentials when profile not set' do @@ -325,12 +286,7 @@ module Aws expect( client.config.credentials.credentials.access_key_id ).to eq('AKID_ENV_STUB') - expect( - client.config.credentials.source - ).to eq(:env) - expect( - client.config.credentials.metrics - ).to eq(['CREDENTIALS_ENV_VARS']) + expect(client.config.credentials.metrics_source).to eq(:env) end it 'prefers process credentials from direct profile over env' do @@ -345,12 +301,9 @@ module Aws expect( client.config.credentials.credentials.access_key_id ).to eq('AK_PROC1') - expect( - client.config.credentials.metrics - ).to eq(%w[CREDENTIALS_PROFILE_PROCESS CREDENTIALS_PROCESS]) end - it 'attempts to fetch metadata credentials last IMDS' do + it 'attempts to fetch metadata credentials last using IMDS' do allow(InstanceProfileCredentials).to receive(:new).and_call_original stub_request(:put, 'http://169.254.169.254/latest/api/token') @@ -385,12 +338,9 @@ module Aws expect( client.config.credentials.credentials.access_key_id ).to eq('akid-md') - expect( - client.config.credentials.metrics - ).to eq(['CREDENTIALS_IMDS']) end - it 'attempts to fetch metadata credentials last HTTP' do + it 'attempts to fetch metadata credentials last using ECS' do path = '/latest/credentials?id=foobarbaz' resp = <<-JSON.strip { @@ -409,9 +359,7 @@ module Aws profile: 'nonexistent', region: 'us-east-1' ) - expect( - client.config.credentials.metrics - ).to eq(['CREDENTIALS_HTTP']) + expect(client.config.credentials.credentials.access_key_id).to eq('ACCESS_KEY_ECS') end describe 'Assume Role Resolution' do @@ -451,13 +399,7 @@ module Aws expect( client.config.credentials.credentials.access_key_id ).to eq('AR_AKID') - expect( - client.config.credentials.source - ).to eq(:web_ID) - expect( - client.config.credentials.metrics - ).to eq(%w[CREDENTIALS_PROFILE_SOURCE_PROFILE CREDENTIALS_PROFILE_STS_WEB_ID_TOKEN - CREDENTIALS_STS_ASSUME_ROLE_WEB_ID CREDENTIALS_STS_ASSUME_ROLE]) + expect(client.config.credentials.metrics_source).to eq(:web_ID) sts_client = client.config.credentials.client expect( @@ -480,13 +422,7 @@ module Aws expect( client.config.credentials.credentials.access_key_id ).to eq('AK_PROC1') - expect( - client.config.credentials.source - ).to eq(:process) - expect( - client.config.credentials.metrics - ).to eq(%w[CREDENTIALS_PROFILE_SOURCE_PROFILE CREDENTIALS_PROFILE_PROCESS CREDENTIALS_PROCESS - CREDENTIALS_STS_ASSUME_ROLE]) + expect(client.config.credentials.metrics_source).to eq(:process) end it 'supports :source_profile from sso credentials' do @@ -499,8 +435,8 @@ module Aws sso_role_name: 'SSO_ROLE_NAME', sso_session: 'sso-test-session' ).and_return(creds) - expect(creds).to receive(:source=).with(:new) - expect(creds).to receive(:source).and_return(:new) + expect(creds).to receive(:metrics_source=).with(:new) + expect(creds).to receive(:metrics_source).and_return(:new) allow(SSOTokenProvider).to receive(:new) .and_return(double('SSOToken', set?: true)) @@ -519,13 +455,7 @@ module Aws expect( client.config.credentials.credentials.access_key_id ).to eq('AR_AKID') - expect( - client.config.credentials.source - ).to eq(:new) - expect( - client.config.credentials.metrics - ).to eq(%w[CREDENTIALS_PROFILE_SOURCE_PROFILE CREDENTIALS_PROFILE_SSO CREDENTIALS_SSO - CREDENTIALS_STS_ASSUME_ROLE]) + expect(client.config.credentials.metrics_source).to eq(:new) end it 'supports :source_profile from legacy sso credentials' do @@ -538,8 +468,8 @@ module Aws sso_role_name: 'SSO_ROLE_NAME', sso_session: nil ).and_return(creds) - expect(creds).to receive(:source=).with(:legacy) - expect(creds).to receive(:source).and_return(:legacy) + expect(creds).to receive(:metrics_source=).with(:legacy) + expect(creds).to receive(:metrics_source).and_return(:legacy) allow(SSOTokenProvider).to receive(:new) .and_return(double('SSOToken', set?: true)) @@ -558,13 +488,7 @@ module Aws expect( client.config.credentials.credentials.access_key_id ).to eq('AR_AKID') - expect( - client.config.credentials.source - ).to eq(:legacy) - expect( - client.config.credentials.metrics - ).to eq(%w[CREDENTIALS_PROFILE_SOURCE_PROFILE CREDENTIALS_PROFILE_SSO_LEGACY CREDENTIALS_SSO_LEGACY - CREDENTIALS_STS_ASSUME_ROLE]) + expect(client.config.credentials.metrics_source).to eq(:legacy) end it 'supports assume role chaining' do @@ -590,12 +514,7 @@ module Aws expect( client.config.credentials.credentials.access_key_id ).to eq('AK_2') - expect( - client.config.credentials.source - ).to eq(:static) - expect( - client.config.credentials.metrics - ).to eq(%w[CREDENTIALS_PROFILE_SOURCE_PROFILE CREDENTIALS_PROFILE CREDENTIALS_STS_ASSUME_ROLE]) + expect(client.config.credentials.metrics_source).to eq(:static) end it 'uses source credentials when source and static are both set' do @@ -613,12 +532,7 @@ module Aws expect( client.config.credentials.credentials.access_key_id ).to eq('AK_2') - expect( - client.config.credentials.source - ).to eq(:static) - expect( - client.config.credentials.metrics - ).to eq(%w[CREDENTIALS_PROFILE_SOURCE_PROFILE CREDENTIALS_PROFILE CREDENTIALS_STS_ASSUME_ROLE]) + expect(client.config.credentials.metrics_source).to eq(:static) end it 'uses static credentials when the profile self references' do @@ -636,12 +550,7 @@ module Aws expect( client.config.credentials.credentials.access_key_id ).to eq('AK_2') - expect( - client.config.credentials.source - ).to eq(:static) - expect( - client.config.credentials.metrics - ).to eq(%w[CREDENTIALS_PROFILE_SOURCE_PROFILE CREDENTIALS_PROFILE CREDENTIALS_STS_ASSUME_ROLE]) + expect(client.config.credentials.metrics_source).to eq(:static) end it 'raises if there is a loop in chained profiles' do @@ -683,12 +592,7 @@ module Aws expect( client.config.credentials.credentials.access_key_id ).to eq('AR_AKID') - expect( - client.config.credentials.source - ).to eq(:static) - expect( - client.config.credentials.metrics - ).to eq(%w[CREDENTIALS_PROFILE_SOURCE_PROFILE CREDENTIALS_PROFILE CREDENTIALS_STS_ASSUME_ROLE]) + expect(client.config.credentials.metrics_source).to eq(:static) end it 'will then try to assume a role from shared config' do @@ -705,12 +609,7 @@ module Aws expect( client.config.credentials.credentials.access_key_id ).to eq('AR_AKID') - expect( - client.config.credentials.source - ).to eq(:static) - expect( - client.config.credentials.metrics - ).to eq(%w[CREDENTIALS_PROFILE_SOURCE_PROFILE CREDENTIALS_PROFILE CREDENTIALS_STS_ASSUME_ROLE]) + expect(client.config.credentials.metrics_source).to eq(:static) end it 'assumes a role from config using source in shared credentials' do @@ -727,12 +626,7 @@ module Aws expect( client.config.credentials.credentials.access_key_id ).to eq('AR_AKID') - expect( - client.config.credentials.source - ).to eq(:static) - expect( - client.config.credentials.metrics - ).to eq(%w[CREDENTIALS_PROFILE_SOURCE_PROFILE CREDENTIALS_PROFILE CREDENTIALS_STS_ASSUME_ROLE]) + expect(client.config.credentials.metrics_source).to eq(:static) end it 'allows region to be resolved when unspecified' do @@ -753,12 +647,7 @@ module Aws expect( credentials.credentials.access_key_id ).to eq('AR_AKID') - expect( - credentials.source - ).to eq(:static) - expect( - credentials.metrics - ).to eq(%w[CREDENTIALS_PROFILE_SOURCE_PROFILE CREDENTIALS_PROFILE CREDENTIALS_STS_ASSUME_ROLE]) + expect(credentials.metrics_source).to eq(:static) end end @@ -803,12 +692,7 @@ module Aws expect( client.config.credentials.credentials.access_key_id ).to eq('AR_AKID') - expect( - client.config.credentials.source - ).to eq(:instance) - expect( - client.config.credentials.metrics - ).to eq(%w[CREDENTIALS_PROFILE_NAMED_PROVIDER CREDENTIALS_IMDS CREDENTIALS_STS_ASSUME_ROLE]) + expect(client.config.credentials.metrics_source).to eq(:instance) end it 'can assume a role with ECS Credentials as a source' do @@ -841,12 +725,7 @@ module Aws expect( client.config.credentials.credentials.access_key_id ).to eq('AR_AKID') - expect( - client.config.credentials.source - ).to eq(:ecs) - expect( - client.config.credentials.metrics - ).to eq(%w[CREDENTIALS_PROFILE_NAMED_PROVIDER CREDENTIALS_HTTP CREDENTIALS_STS_ASSUME_ROLE]) + expect(client.config.credentials.metrics_source).to eq(:ecs) end end @@ -876,12 +755,7 @@ module Aws expect( client.config.credentials.credentials.access_key_id ).to eq('ACCESS_DIRECT') - expect( - client.config.credentials.source - ).to eq(:profile) - expect( - client.config.credentials.metrics - ).to eq(['CREDENTIALS_PROFILE']) + expect(client.config.credentials.metrics_source).to eq(:profile) end it 'prefers ENV credentials over shared config when profile not set' do @@ -896,12 +770,7 @@ module Aws expect( client.config.credentials.credentials.access_key_id ).to eq('AKID_ENV_STUB') - expect( - client.config.credentials.source - ).to eq(:env) - expect( - client.config.credentials.metrics - ).to eq(['CREDENTIALS_ENV_VARS']) + expect(client.config.credentials.metrics_source).to eq(:env) end it 'prefers config from profile over ENV credentials when profile is set on client' do @@ -916,9 +785,6 @@ module Aws expect( client.config.credentials.credentials.access_key_id ).to eq('ACCESS_KEY_1') - expect( - client.config.credentials.metrics - ).to eq(['CREDENTIALS_PROFILE']) end it 'will not load credentials from shared config' do @@ -970,9 +836,6 @@ module Aws expect( client.config.credentials.credentials.access_key_id ).to eq('akid-md') - expect( - client.config.credentials.metrics - ).to eq(['CREDENTIALS_IMDS']) end end diff --git a/gems/aws-sdk-core/spec/aws/credentials_spec.rb b/gems/aws-sdk-core/spec/aws/credentials_spec.rb index 42f58fa2c3c..93f850c7657 100644 --- a/gems/aws-sdk-core/spec/aws/credentials_spec.rb +++ b/gems/aws-sdk-core/spec/aws/credentials_spec.rb @@ -37,8 +37,8 @@ module Aws expect(Credentials.new('akid', 'secret').account_id).to be(nil) end - it 'defaults the source to none' do - expect(Credentials.new('akid', 'secret').source).to eq(:none) + it 'defaults the source to code' do + expect(Credentials.new('akid', 'secret').metrics_source).to eq(:code) end describe '#set?' do @@ -73,19 +73,19 @@ module Aws it 'returns the correct metrics when the source is profile' do creds = Credentials.new('akid', 'secret') - creds.source = :profile + creds.metrics_source = :profile expect(creds.metrics).to eq(['CREDENTIALS_PROFILE']) end it 'returns the correct metrics when the source is env' do creds = Credentials.new('akid', 'secret') - creds.source = :env + creds.metrics_source = :env expect(creds.metrics).to eq(['CREDENTIALS_ENV_VARS']) end it 'returns no metrics when the source is assume_role_resolution' do creds = Credentials.new('akid', 'secret') - creds.source = :assume_role_resolution + creds.metrics_source = :assume_role_resolution expect(creds.metrics).to eq([]) end end diff --git a/gems/aws-sdk-core/spec/aws/plugins/sign_spec.rb b/gems/aws-sdk-core/spec/aws/plugins/sign_spec.rb index e9edea5d233..db87f440dcd 100644 --- a/gems/aws-sdk-core/spec/aws/plugins/sign_spec.rb +++ b/gems/aws-sdk-core/spec/aws/plugins/sign_spec.rb @@ -203,16 +203,14 @@ def call(context) end end - describe 'UserAgent header' do - it 'Adds metrics from the credential providers' do - creds = Aws::Credentials.new('akid', 'secret') - client = TestClient.new(client_options.merge(credentials: creds)) - resp = client.operation - req = resp.context.http_request - header = req.headers['User-Agent'] - metrics = header[(header.index('m/')+2)..] - expect(metrics).to include('e') - end + it 'Adds metrics from the credential providers' do + creds = Aws::Credentials.new('akid', 'secret') + client = TestClient.new(client_options.merge(credentials: creds)) + resp = client.operation + req = resp.context.http_request + header = req.headers['User-Agent'] + metrics = header[(header.index('m/')+2)..] + expect(metrics).to include('e') end end diff --git a/gems/aws-sdk-core/spec/aws/process_credentials_spec.rb b/gems/aws-sdk-core/spec/aws/process_credentials_spec.rb index 2e659fb23df..bd80973c55f 100644 --- a/gems/aws-sdk-core/spec/aws/process_credentials_spec.rb +++ b/gems/aws-sdk-core/spec/aws/process_credentials_spec.rb @@ -46,9 +46,16 @@ module Aws }.to raise_error(Errors::InvalidProcessCredentialsPayload) end - it 'will return the correct metrics' do + it 'will return the correct metrics when source is code' do process = %w[echo {"Version":1,"AccessKeyId":"AK_PROC1","SecretAccessKey":"SECRET_AK_PROC1","SessionToken":"TOKEN_PROC1","AccountId":"ACCOUNT_ID_PROC1"}] c = ProcessCredentials.new(process) + expect(c.metrics).to eq(['CREDENTIALS_PROCESS']) + end + + it 'will return the correct metrics when source is profile' do + process = %w[echo {"Version":1,"AccessKeyId":"AK_PROC1","SecretAccessKey":"SECRET_AK_PROC1","SessionToken":"TOKEN_PROC1","AccountId":"ACCOUNT_ID_PROC1"}] + c = ProcessCredentials.new(process) + c.metrics_source = :profile expect(c.metrics).to eq(%w[CREDENTIALS_PROFILE_PROCESS CREDENTIALS_PROCESS]) end diff --git a/gems/aws-sdk-core/spec/aws/sso_credentials_spec.rb b/gems/aws-sdk-core/spec/aws/sso_credentials_spec.rb index 0f0812fc98f..939ed8e3fd0 100644 --- a/gems/aws-sdk-core/spec/aws/sso_credentials_spec.rb +++ b/gems/aws-sdk-core/spec/aws/sso_credentials_spec.rb @@ -151,14 +151,14 @@ def mock_token_file(start_url, cached_token) describe '#metrics' do - it 'returns the correct metrics when the source is none' do + it 'returns the correct metrics when the source is code' do c = SSOCredentials.new(sso_opts) expect(c.metrics).to eq(['CREDENTIALS_SSO']) end it 'returns the correct metrics when the source is new' do c = SSOCredentials.new(sso_opts) - c.source = :new + c.metrics_source = :new expect(c.metrics).to eq(%w[CREDENTIALS_PROFILE_SSO CREDENTIALS_SSO]) end @@ -309,7 +309,7 @@ def mock_token_file(start_url, cached_token) describe '#metrics' do - it 'returns the correct metrics when the source is none' do + it 'returns the correct metrics when the source is code' do expect(SSO::Client).to receive(:new) .with({region: sso_region, credentials: nil}) .and_return(client) @@ -326,7 +326,7 @@ def mock_token_file(start_url, cached_token) mock_token_file(sso_start_url, cached_token) c = SSOCredentials.new(sso_opts) - c.source = :legacy + c.metrics_source = :legacy expect(c.metrics).to eq(%w[CREDENTIALS_PROFILE_SSO_LEGACY CREDENTIALS_SSO_LEGACY]) end end diff --git a/gems/aws-sdk-core/spec/sigv4_helper.rb b/gems/aws-sdk-core/spec/sigv4_helper.rb index 0ee993d4c9b..c909eae3bc0 100644 --- a/gems/aws-sdk-core/spec/sigv4_helper.rb +++ b/gems/aws-sdk-core/spec/sigv4_helper.rb @@ -20,7 +20,7 @@ def expect_auth(auth_scheme, region: nil, credentials: nil) expect(Aws::Sigv4::Signer).to receive(:new) .with(hash_including(signing_algorithm: :sigv4a, region: region)) .and_return(signer) - expect(signer).to receive(:credentials_provider) + expect(signer).to receive(:credentials_provider).and_return(credentials) end m.call(*args) From 57e0889148db177e749a0cc41cb731499d204e41 Mon Sep 17 00:00:00 2001 From: Richard Wang Date: Tue, 1 Apr 2025 15:14:07 -0700 Subject: [PATCH 41/59] Add some documentation --- .../aws-sdk-core/lib/aws-sdk-core/assume_role_credentials.rb | 5 +++++ .../lib/aws-sdk-core/assume_role_web_identity_credentials.rb | 2 ++ gems/aws-sdk-core/lib/aws-sdk-core/credentials.rb | 2 ++ gems/aws-sdk-core/lib/aws-sdk-core/process_credentials.rb | 2 ++ gems/aws-sdk-core/lib/aws-sdk-core/sso_credentials.rb | 2 ++ 5 files changed, 13 insertions(+) diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_credentials.rb b/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_credentials.rb index 48fbf30f371..33230b6984e 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_credentials.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_credentials.rb @@ -60,8 +60,13 @@ def initialize(options = {}) # @return [Hash] attr_reader :assume_role_params + # @return [String] Returns the credentials source. Used for + # tracking credentials related UserAgent metrics. attr_accessor :metrics_source + # @return [Boolean] Returns `true` if instance is created + # during source profile resolution. Used for tracking + # credentials related UserAgent metrics. attr_accessor :resolving def metrics diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_web_identity_credentials.rb b/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_web_identity_credentials.rb index dcdc75845fd..67e1a801834 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_web_identity_credentials.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_web_identity_credentials.rb @@ -68,6 +68,8 @@ def initialize(options = {}) # @return [STS::Client] attr_reader :client + # @return [String] Returns the credentials source. Used for + # tracking credentials related UserAgent metrics. attr_accessor :metrics_source def metrics diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/credentials.rb b/gems/aws-sdk-core/lib/aws-sdk-core/credentials.rb index a833aa1a311..4ea4cad572a 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/credentials.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/credentials.rb @@ -29,6 +29,8 @@ def initialize(access_key_id, secret_access_key, session_token = nil, # @return [String, nil] attr_reader :account_id + # @return [String] Returns the credentials source. Used for + # tracking credentials related UserAgent metrics. attr_accessor :metrics_source # @return [Credentials] diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/process_credentials.rb b/gems/aws-sdk-core/lib/aws-sdk-core/process_credentials.rb index c859a7be39e..9e47366a203 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/process_credentials.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/process_credentials.rb @@ -41,6 +41,8 @@ def initialize(process) super end + # @return [String] Returns the credentials source. Used for + # tracking credentials related UserAgent metrics. attr_accessor :metrics_source def metrics diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/sso_credentials.rb b/gems/aws-sdk-core/lib/aws-sdk-core/sso_credentials.rb index 9e4379a3ad9..354d48e32a0 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/sso_credentials.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/sso_credentials.rb @@ -121,6 +121,8 @@ def initialize(options = {}) # @return [SSO::Client] attr_reader :client + # @return [String] Returns the credentials source. Used for + # tracking credentials related UserAgent metrics. attr_accessor :metrics_source def metrics From 1408d575e1510543e0da9036dc2405eedbc5d8f3 Mon Sep 17 00:00:00 2001 From: Richard Wang Date: Tue, 1 Apr 2025 19:08:09 -0700 Subject: [PATCH 42/59] Add testing for service call metrics --- .../lib/seahorse/client/handler.rb | 2 + .../aws/credential_resolution_chain_spec.rb | 295 ++++++++++++++++++ 2 files changed, 297 insertions(+) diff --git a/gems/aws-sdk-core/lib/seahorse/client/handler.rb b/gems/aws-sdk-core/lib/seahorse/client/handler.rb index 68fcb0d192b..d63b8b800c0 100644 --- a/gems/aws-sdk-core/lib/seahorse/client/handler.rb +++ b/gems/aws-sdk-core/lib/seahorse/client/handler.rb @@ -17,7 +17,9 @@ def initialize(handler = nil) # @param [RequestContext] context # @return [Seahorse::Response] def call(context) + puts "Calling" @handler.call(context) + puts "Called" end def inspect diff --git a/gems/aws-sdk-core/spec/aws/credential_resolution_chain_spec.rb b/gems/aws-sdk-core/spec/aws/credential_resolution_chain_spec.rb index 22b57b0ba44..8caa0aebbfe 100644 --- a/gems/aws-sdk-core/spec/aws/credential_resolution_chain_spec.rb +++ b/gems/aws-sdk-core/spec/aws/credential_resolution_chain_spec.rb @@ -81,6 +81,30 @@ module Aws expect(client.config.credentials.metrics_source).to eq(:static) end + it 'emits correct UserAgent metrics during STS call for assume role credentials' do + stub_const( + 'ENV', + 'AWS_ACCESS_KEY_ID' => 'AKID_ENV_STUB', + 'AWS_SECRET_ACCESS_KEY' => 'SECRET_ENV_STUB' + ) + assume_role_stub( + 'arn:aws:iam::123456789012:role/foo', + 'ACCESS_KEY_1', # from 'fooprofile' + 'AR_AKID', + 'AR_SECRET', + 'AR_TOKEN' + ) + expect_any_instance_of(STS::Client).to receive(:assume_role).and_wrap_original do |m, *args| + resp = m.call(*args) + metrics = metrics_from_user_agent_header(resp.context.http_request.headers['User-Agent']) + expect(metrics).to include('o,n') + resp + end + client = ApiHelper.sample_rest_xml::Client.new( + profile: 'assumerole_sc', region: 'us-east-1' + ) + end + it 'prefers assume role web identity from profile over sso' do assume_role_web_identity_stub( 'arn:aws:iam::123456789012:role/foo', @@ -97,6 +121,24 @@ module Aws expect(client.config.credentials.metrics_source).to eq(:profile) end + it 'emits correct UserAgent metrics during STS call for assume role web identity from profile' do + assume_role_web_identity_stub( + 'arn:aws:iam::123456789012:role/foo', + 'AR_AKID', + 'AR_SECRET', + 'AR_TOKEN' + ) + expect_any_instance_of(STS::Client).to receive(:assume_role_with_web_identity).and_wrap_original do |m, *args| + resp = m.call(*args) + metrics = metrics_from_user_agent_header(resp.context.http_request.headers['User-Agent']) + expect(metrics).to include('q') + resp + end + client = ApiHelper.sample_rest_xml::Client.new( + profile: 'ar_web_identity', region: 'us-east-1' + ) + end + it 'prefers assume role web identity from ENV over sso' do stub_const( 'ENV', @@ -117,6 +159,29 @@ module Aws expect(client.config.credentials.metrics_source).to eq(:env) end + it 'emits correct UserAgent metrics during STS call for assume role web identity from env' do + stub_const( + 'ENV', + 'AWS_ROLE_ARN' => 'arn:aws:iam::123456789012:role/foo', + 'AWS_WEB_IDENTITY_TOKEN_FILE' => 'my-token.jwt' + ) + assume_role_web_identity_stub( + 'arn:aws:iam::123456789012:role/foo', + 'AR_AKID', + 'AR_SECRET', + 'AR_TOKEN' + ) + expect_any_instance_of(STS::Client).to receive(:assume_role_with_web_identity).and_wrap_original do |m, *args| + resp = m.call(*args) + metrics = metrics_from_user_agent_header(resp.context.http_request.headers['User-Agent']) + expect(metrics).to include('h') + resp + end + client = ApiHelper.sample_rest_xml::Client.new( + region: 'us-east-1' + ) + end + it 'prefers sso credentials over assume role' do creds = double('creds', set?: true, credentials: double(access_key_id: 'SSO_AKID')) allow(creds).to receive(:metrics).and_return(%w[CREDENTIALS_PROFILE_SSO CREDENTIALS_SSO]) @@ -407,6 +472,37 @@ module Aws ).to eq('us-east-1') end + it 'emits correct UserAgent metrics during STS calls for :source_profile from assume_role_web_identity' do + assume_role_web_identity_stub( + 'arn:aws:iam::123456789012:role/foo', + 'AR_AKID_WEB', + 'AR_SECRET', + 'AR_TOKEN' + ) + assume_role_stub( + 'arn:aws:iam::123456789012:role/bar', + 'AR_AKID_WEB', # from web_only + 'AR_AKID', + 'AR_SECRET', + 'AR_TOKEN' + ) + expect_any_instance_of(STS::Client).to receive(:assume_role_with_web_identity).and_wrap_original do |m, *args| + resp = m.call(*args) + metrics = metrics_from_user_agent_header(resp.context.http_request.headers['User-Agent']) + expect(metrics).to include('o,q') + resp + end + expect_any_instance_of(STS::Client).to receive(:assume_role).and_wrap_original do |m, *args| + resp = m.call(*args) + metrics = metrics_from_user_agent_header(resp.context.http_request.headers['User-Agent']) + expect(metrics).to include('o,q,k') + resp + end + client = ApiHelper.sample_rest_xml::Client.new( + profile: 'ar_web_src', region: 'us-east-1' + ) + end + it 'supports :source_profile from process credentials' do assume_role_stub( 'arn:aws:iam::123456789012:role/foo', @@ -425,6 +521,25 @@ module Aws expect(client.config.credentials.metrics_source).to eq(:process) end + it 'emits correct UserAgent metrics during STS calls for :source_profile from process credentials' do + assume_role_stub( + 'arn:aws:iam::123456789012:role/foo', + 'AK_PROC1', + 'AK_PROC1', + 'SECRET_AK_PROC1', + 'TOKEN_PROC1' + ) + expect_any_instance_of(STS::Client).to receive(:assume_role).and_wrap_original do |m, *args| + resp = m.call(*args) + metrics = metrics_from_user_agent_header(resp.context.http_request.headers['User-Agent']) + expect(metrics).to include('o,v,w') + resp + end + client = ApiHelper.sample_rest_xml::Client.new( + profile: 'creds_from_sc_process', region: 'us-east-1' + ) + end + it 'supports :source_profile from sso credentials' do creds = double('creds', set?: true, credentials: Credentials.new('SSO_AKID', 'sak')) allow(creds).to receive(:metrics).and_return(%w[CREDENTIALS_PROFILE_SSO CREDENTIALS_SSO]) @@ -458,6 +573,40 @@ module Aws expect(client.config.credentials.metrics_source).to eq(:new) end + it 'emits correct UserAgent metrics during STS calls for :source_profile from sso credentials' do + creds = double('creds', set?: true, credentials: Credentials.new('SSO_AKID', 'sak')) + allow(creds).to receive(:metrics).and_return(%w[CREDENTIALS_PROFILE_SSO CREDENTIALS_SSO]) + expect(SSOCredentials).to receive(:new).with( + sso_start_url: 'START_URL', + sso_region: 'us-east-1', + sso_account_id: 'SSO_ACCOUNT_ID', + sso_role_name: 'SSO_ROLE_NAME', + sso_session: 'sso-test-session' + ).and_return(creds) + expect(creds).to receive(:metrics_source=).with(:new) + expect(creds).to receive(:metrics_source).and_return(:new) + + allow(SSOTokenProvider).to receive(:new) + .and_return(double('SSOToken', set?: true)) + + assume_role_stub( + 'arn:aws:iam::123456789012:role/foo', + 'SSO_AKID', + 'AR_AKID', + 'SECRET_AK', + 'TOKEN' + ) + expect_any_instance_of(STS::Client).to receive(:assume_role).and_wrap_original do |m, *args| + resp = m.call(*args) + metrics = metrics_from_user_agent_header(resp.context.http_request.headers['User-Agent']) + expect(metrics).to include('o,r,s') + resp + end + client = ApiHelper.sample_rest_xml::Client.new( + profile: 'ar_sso_src', region: 'us-east-1' + ) + end + it 'supports :source_profile from legacy sso credentials' do creds = double('creds', set?: true, credentials: Credentials.new('SSO_AKID', 'sak')) allow(creds).to receive(:metrics).and_return(%w[CREDENTIALS_PROFILE_SSO_LEGACY CREDENTIALS_SSO_LEGACY]) @@ -491,6 +640,40 @@ module Aws expect(client.config.credentials.metrics_source).to eq(:legacy) end + it 'emits correct UserAgent metrics during STS calls for :source_profile from legacy sso credentials' do + creds = double('creds', set?: true, credentials: Credentials.new('SSO_AKID', 'sak')) + allow(creds).to receive(:metrics).and_return(%w[CREDENTIALS_PROFILE_SSO_LEGACY CREDENTIALS_SSO_LEGACY]) + expect(SSOCredentials).to receive(:new).with( + sso_start_url: 'START_URL', + sso_region: 'us-east-1', + sso_account_id: 'SSO_ACCOUNT_ID', + sso_role_name: 'SSO_ROLE_NAME', + sso_session: nil + ).and_return(creds) + expect(creds).to receive(:metrics_source=).with(:legacy) + expect(creds).to receive(:metrics_source).and_return(:legacy) + + allow(SSOTokenProvider).to receive(:new) + .and_return(double('SSOToken', set?: true)) + + assume_role_stub( + 'arn:aws:iam::123456789012:role/foo', + 'SSO_AKID', + 'AR_AKID', + 'SECRET_AK', + 'TOKEN' + ) + expect_any_instance_of(STS::Client).to receive(:assume_role).and_wrap_original do |m, *args| + resp = m.call(*args) + metrics = metrics_from_user_agent_header(resp.context.http_request.headers['User-Agent']) + expect(metrics).to include('o,t,u') + resp + end + client = ApiHelper.sample_rest_xml::Client.new( + profile: 'ar_sso_legacy_src', region: 'us-east-1' + ) + end + it 'supports assume role chaining' do assume_role_stub( 'arn:aws:iam::123456789012:role/role_b', @@ -517,6 +700,33 @@ module Aws expect(client.config.credentials.metrics_source).to eq(:static) end + it 'emits correct UserAgent metrics during STS calls for assume role chaining' do + assume_role_stub( + 'arn:aws:iam::123456789012:role/role_b', + 'ACCESS_KEY_BASE', + 'AK_1', + 'SECRET_AK_1', + 'TOKEN_1' + ) + + assume_role_stub( + 'arn:aws:iam::123456789012:role/role_a', + 'AK_1', + 'AK_2', + 'SECRET_AK_2', + 'TOKEN_2' + ) + allow_any_instance_of(STS::Client).to receive(:assume_role).and_wrap_original do |m, *args| + resp = m.call(*args) + metrics = metrics_from_user_agent_header(resp.context.http_request.headers['User-Agent']) + expect(metrics).to include('o,n') + resp + end + client = ApiHelper.sample_rest_xml::Client.new( + profile: 'assume_role_chain_b', region: 'us-east-1' + ) + end + it 'uses source credentials when source and static are both set' do assume_role_stub( 'arn:aws:iam::123456789012:role/role_a', @@ -695,6 +905,52 @@ module Aws expect(client.config.credentials.metrics_source).to eq(:instance) end + it 'emits correct UserAgent metrics during STS calls for EC2 Instance Metadata as a source' do + allow(InstanceProfileCredentials).to receive(:new).and_call_original + + profile = 'ar_ec2_src' + resp = <<-JSON.strip + { + "Code" : "Success", + "LastUpdated" : "2013-11-22T20:03:48Z", + "Type" : "AWS-HMAC", + "AccessKeyId" : "ACCESS_KEY_EC2", + "SecretAccessKey" : "secret", + "Token" : "session-token", + "Expiration" : "#{(Time.now.utc + 3600).strftime('%Y-%m-%dT%H:%M:%SZ')}" + } + JSON + assume_role_stub( + 'arn:aws:iam::123456789012:role/foo', + 'ACCESS_KEY_EC2', + 'AR_AKID', + 'AR_SECRET', + 'AR_TOKEN' + ) + stub_request(:put, 'http://169.254.169.254/latest/api/token') + .to_return( + status: 200, + body: "my-token\n", + headers: { 'x-aws-ec2-metadata-token-ttl-seconds' => '21600' } + ) + stub_request(:get, 'http://169.254.169.254/latest/meta-data/iam/security-credentials/') + .with(headers: { 'x-aws-ec2-metadata-token' => 'my-token' }) + .to_return(status: 200, body: "profile-name\n") + stub_request(:get, 'http://169.254.169.254/latest/meta-data/iam/security-credentials/profile-name') + .with(headers: { 'x-aws-ec2-metadata-token' => 'my-token' }) + .to_return(status: 200, body: resp) + expect_any_instance_of(STS::Client).to receive(:assume_role).and_wrap_original do |m, *args| + resp = m.call(*args) + metrics = metrics_from_user_agent_header(resp.context.http_request.headers['User-Agent']) + expect(metrics).to include('p,0') + resp + end + client = ApiHelper.sample_rest_xml::Client.new( + profile: profile, + region: 'us-east-1' + ) + end + it 'can assume a role with ECS Credentials as a source' do profile = 'ar_ecs_src' path = '/latest/credentials?id=foobarbaz' @@ -727,6 +983,41 @@ module Aws ).to eq('AR_AKID') expect(client.config.credentials.metrics_source).to eq(:ecs) end + + it 'emits correct UserAgent metrics during STS calls for ECS Credentials as a source' do + profile = 'ar_ecs_src' + path = '/latest/credentials?id=foobarbaz' + resp = <<-JSON.strip + { + "RoleArn" : "arn:aws:iam::123456789012:role/BarFooRole", + "AccessKeyId" : "ACCESS_KEY_ECS", + "SecretAccessKey" : "secret", + "Token" : "session-token", + "Expiration" : "#{(Time.now.utc + 3600).strftime('%Y-%m-%dT%H:%M:%SZ')}" + } + JSON + stub_const('ENV', + 'AWS_CONTAINER_CREDENTIALS_RELATIVE_URI' => path) + stub_request(:get, "http://169.254.170.2#{path}") + .to_return(status: 200, body: resp) + assume_role_stub( + 'arn:aws:iam::123456789012:role/foo', + 'ACCESS_KEY_ECS', + 'AR_AKID', + 'AR_SECRET', + 'AR_TOKEN' + ) + expect_any_instance_of(STS::Client).to receive(:assume_role).and_wrap_original do |m, *args| + resp = m.call(*args) + metrics = metrics_from_user_agent_header(resp.context.http_request.headers['User-Agent']) + expect(metrics).to include('p,z') + resp + end + client = ApiHelper.sample_rest_xml::Client.new( + profile: profile, + region: 'us-east-1' + ) + end end describe 'AWS_SDK_CONFIG_OPT_OUT set' do @@ -897,5 +1188,9 @@ def stub_token_file(token) allow(File).to receive(:read).and_call_original allow(File).to receive(:read).with('my-token.jwt').and_return(token) end + + def metrics_from_user_agent_header(header) + header[(header.index('m/')+2)..] + end end end From d975eab84760a502059b3c660bc8e943a8e199ac Mon Sep 17 00:00:00 2001 From: Richard Wang Date: Wed, 2 Apr 2025 14:12:53 -0700 Subject: [PATCH 43/59] Initial fix to simplify return --- .../lib/aws-sdk-core/plugins/user_agent.rb | 6 +- .../lib/aws-sdk-core/shared_config.rb | 64 ++++++++++--------- 2 files changed, 37 insertions(+), 33 deletions(-) diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/plugins/user_agent.rb b/gems/aws-sdk-core/lib/aws-sdk-core/plugins/user_agent.rb index df99b8c7e3b..8f6d3409fac 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/plugins/user_agent.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/plugins/user_agent.rb @@ -213,11 +213,11 @@ def metric_metadata end # Needed for AssumeRoleCredentials feature id tracking - Thread.current[:aws_sdk_core_user_agent_metric].uniq! + # Thread.current[:aws_sdk_core_user_agent_metric].uniq! metrics = Thread.current[:aws_sdk_core_user_agent_metric].join(',') - # puts "User agent metrics" - # puts metrics + puts "User agent metrics" + puts metrics # Metric metadata is limited to 1024 bytes return "m/#{metrics}" if metrics.bytesize <= 1024 diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/shared_config.rb b/gems/aws-sdk-core/lib/aws-sdk-core/shared_config.rb index f53b5a17ca8..c61dd945ecb 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/shared_config.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/shared_config.rb @@ -259,9 +259,18 @@ def assume_role_from_profile(cfg, profile, opts, chain_config) 'provide only source_profile or credential_source, not both.' elsif opts[:source_profile] opts[:visited_profiles] ||= Set.new - opts[:credentials], provider, source = with_metrics('CREDENTIALS_PROFILE_SOURCE_PROFILE') do + provider = with_metrics('CREDENTIALS_PROFILE_SOURCE_PROFILE') do resolve_source_profile(opts[:source_profile], opts) end + metrics = provider ? provider.metrics : nil + if provider.is_a? AssumeRoleCredentials + opts[:credentials] = provider + opts[:credentials].resolving = true + metrics.pop + else + opts[:credentials] = provider ? provider.credentials : nil + metrics.unshift('CREDENTIALS_PROFILE_SOURCE_PROFILE') if metrics + end if opts[:credentials] opts[:role_session_name] ||= prof_cfg['role_session_name'] opts[:role_session_name] ||= 'default_session' @@ -271,17 +280,17 @@ def assume_role_from_profile(cfg, profile, opts, chain_config) opts[:serial_number] ||= prof_cfg['mfa_serial'] opts[:profile] = opts.delete(:source_profile) opts.delete(:visited_profiles) - metrics = provider.metrics - # Add the AssumeRole metric to the front if it isn't there - metrics.unshift('CREDENTIALS_PROFILE_SOURCE_PROFILE') if metrics.first != 'CREDENTIALS_PROFILE_SOURCE_PROFILE' - # Remove the service call metric if it's already there - if metrics.last == 'CREDENTIALS_STS_ASSUME_ROLE' - metrics.pop - opts[:credentials].resolving = true - end with_metrics(metrics) do credentials = AssumeRoleCredentials.new(opts) - credentials.metrics_source = source + if provider.is_a? Credentials + credentials.metrics_source = :static + elsif provider.is_a? AssumeRoleWebIdentityCredentials + credentials.metrics_source = :web_ID + elsif provider.is_a? ProcessCredentials + credentials.metrics_source = :process + else + credentials.metrics_source = provider.metrics_source + end credentials end else @@ -290,12 +299,7 @@ def assume_role_from_profile(cfg, profile, opts, chain_config) ' source_profile does not have credentials.' end elsif credential_source - opts[:credentials], source = with_metrics('CREDENTIALS_PROFILE_NAMED_PROVIDER') do - credentials_from_source( - credential_source, - chain_config - ) - end + opts[:credentials] = credentials_from_source(credential_source, chain_config) if opts[:credentials] opts[:role_session_name] ||= prof_cfg['role_session_name'] opts[:role_session_name] ||= 'default_session' @@ -305,10 +309,14 @@ def assume_role_from_profile(cfg, profile, opts, chain_config) opts[:serial_number] ||= prof_cfg['mfa_serial'] opts.delete(:source_profile) # Cleanup metrics = opts[:credentials].metrics - metrics.unshift('CREDENTIALS_PROFILE_NAMED_PROVIDER') if metrics.first != 'CREDENTIALS_PROFILE_NAMED_PROVIDER' + metrics.unshift('CREDENTIALS_PROFILE_NAMED_PROVIDER') with_metrics(metrics) do credentials = AssumeRoleCredentials.new(opts) - credentials.metrics_source = source + if opts[:credentials].is_a? InstanceProfileCredentials + credentials.metrics_source = :instance + elsif opts[:credentials].is_a? ECSCredentials + credentials.metrics_source = :ecs + end credentials end else @@ -335,36 +343,32 @@ def resolve_source_profile(profile, opts = {}) if (creds = credentials(profile: profile)) creds.metrics_source = :profile - [creds, creds, :static] # static credentials + creds # static credentials elsif profile_config && profile_config['source_profile'] opts.delete(:source_profile) - creds = assume_role_credentials_from_config(opts.merge(profile: profile)) - [creds, creds, creds.metrics_source] + assume_role_credentials_from_config(opts.merge(profile: profile)) elsif (provider = assume_role_web_identity_credentials_from_config(opts.merge(profile: profile))) provider.credentials.metrics_source = :assume_role_resolution - [provider.credentials, provider, :web_ID] if provider.credentials.set? + provider if provider.credentials.set? elsif (provider = assume_role_process_credentials_from_config(profile)) provider.credentials.metrics_source = :assume_role_resolution - [provider.credentials, provider, :process] if provider.credentials.set? + provider if provider.credentials.set? elsif (provider = sso_credentials_from_config(profile: profile)) provider.credentials.metrics_source = :assume_role_resolution - [provider.credentials, provider, provider.metrics_source] + provider if provider.credentials.set? end end def credentials_from_source(credential_source, config) case credential_source when 'Ec2InstanceMetadata' - [ - InstanceProfileCredentials.new( + InstanceProfileCredentials.new( retries: config ? config.instance_profile_credentials_retries : 0, http_open_timeout: config ? config.instance_profile_credentials_timeout : 1, http_read_timeout: config ? config.instance_profile_credentials_timeout : 1, - ), - :instance - ] + ) when 'EcsContainer' - [ECSCredentials.new, :ecs] + ECSCredentials.new else raise Errors::InvalidCredentialSourceError, "Unsupported credential_source: #{credential_source}" end From acf8375c4d955e4bce07d22e0414cbd7825b24b2 Mon Sep 17 00:00:00 2001 From: Richard Wang Date: Wed, 2 Apr 2025 16:59:06 -0700 Subject: [PATCH 44/59] Fix duplicate metrics issue with AssumeRoleCredentials --- .../aws-sdk-core/assume_role_credentials.rb | 11 ++- .../lib/aws-sdk-core/credentials.rb | 9 ++- .../lib/aws-sdk-core/ecs_credentials.rb | 7 ++ .../instance_profile_credentials.rb | 7 ++ .../lib/aws-sdk-core/plugins/user_agent.rb | 7 +- .../lib/aws-sdk-core/shared_config.rb | 68 ++++++++++--------- .../lib/seahorse/client/handler.rb | 2 - .../spec/aws/assume_role_credentials_spec.rb | 40 +---------- .../aws-sdk-core/spec/aws/credentials_spec.rb | 4 +- .../spec/aws/ecs_credentials_spec.rb | 6 ++ .../aws/instance_profile_credentials_spec.rb | 6 ++ 11 files changed, 79 insertions(+), 88 deletions(-) diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_credentials.rb b/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_credentials.rb index 33230b6984e..73325f153cd 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_credentials.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_credentials.rb @@ -65,19 +65,16 @@ def initialize(options = {}) attr_accessor :metrics_source # @return [Boolean] Returns `true` if instance is created - # during source profile resolution. Used for tracking - # credentials related UserAgent metrics. + # during source profile resolution for AssumeRoleCredentials. + # Used for tracking credentials related UserAgent metrics. attr_accessor :resolving def metrics + return [] if @resolving + source_profile = %w[CREDENTIALS_PROFILE_SOURCE_PROFILE CREDENTIALS_STS_ASSUME_ROLE] credential_source = %w[CREDENTIALS_PROFILE_NAMED_PROVIDER CREDENTIALS_STS_ASSUME_ROLE] - if @resolving - source_profile.pop - credential_source.pop - end - case @metrics_source when :code ['CREDENTIALS_STS_ASSUME_ROLE'] diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/credentials.rb b/gems/aws-sdk-core/lib/aws-sdk-core/credentials.rb index 4ea4cad572a..25ef2956ab4 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/credentials.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/credentials.rb @@ -33,6 +33,11 @@ def initialize(access_key_id, secret_access_key, session_token = nil, # tracking credentials related UserAgent metrics. attr_accessor :metrics_source + # @return [Boolean] Returns `true` if instance is created + # during source profile resolution for AssumeRoleCredentials. + # Used for tracking credentials related UserAgent metrics. + attr_accessor :resolving + # @return [Credentials] def credentials self @@ -54,6 +59,8 @@ def inspect end def metrics + return [] if @resolving + case @metrics_source when :code ['CREDENTIALS_CODE'] @@ -61,8 +68,6 @@ def metrics ['CREDENTIALS_PROFILE'] when :env ['CREDENTIALS_ENV_VARS'] - when :assume_role_resolution - [] end end diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/ecs_credentials.rb b/gems/aws-sdk-core/lib/aws-sdk-core/ecs_credentials.rb index 578708d699f..5a0ffa8754b 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/ecs_credentials.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/ecs_credentials.rb @@ -84,7 +84,14 @@ def initialize(options = {}) # fetch credentials from the instance metadata service. Defaults to 0. attr_reader :retries + # @return [Boolean] Returns `true` if instance is created + # during source profile resolution for AssumeRoleCredentials. + # Used for tracking credentials related UserAgent metrics. + attr_accessor :resolving + def metrics + return [] if @resolving + ['CREDENTIALS_HTTP'] end diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/instance_profile_credentials.rb b/gems/aws-sdk-core/lib/aws-sdk-core/instance_profile_credentials.rb index 52e2154181d..7566304f0e0 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/instance_profile_credentials.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/instance_profile_credentials.rb @@ -98,7 +98,14 @@ def initialize(options = {}) # the default credential chain ({Aws::CredentialProviderChain}). attr_reader :retries + # @return [Boolean] Returns `true` if instance is created + # during source profile resolution for AssumeRoleCredentials. + # Used for tracking credentials related UserAgent metrics. + attr_accessor :resolving + def metrics + return [] if @resolving + ['CREDENTIALS_IMDS'] end diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/plugins/user_agent.rb b/gems/aws-sdk-core/lib/aws-sdk-core/plugins/user_agent.rb index 8f6d3409fac..a6b0494bef7 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/plugins/user_agent.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/plugins/user_agent.rb @@ -212,12 +212,9 @@ def metric_metadata return end - # Needed for AssumeRoleCredentials feature id tracking - # Thread.current[:aws_sdk_core_user_agent_metric].uniq! - metrics = Thread.current[:aws_sdk_core_user_agent_metric].join(',') - puts "User agent metrics" - puts metrics + # puts "User agent metrics" + # puts metrics # Metric metadata is limited to 1024 bytes return "m/#{metrics}" if metrics.bytesize <= 1024 diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/shared_config.rb b/gems/aws-sdk-core/lib/aws-sdk-core/shared_config.rb index c61dd945ecb..48e347d0e26 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/shared_config.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/shared_config.rb @@ -259,19 +259,8 @@ def assume_role_from_profile(cfg, profile, opts, chain_config) 'provide only source_profile or credential_source, not both.' elsif opts[:source_profile] opts[:visited_profiles] ||= Set.new - provider = with_metrics('CREDENTIALS_PROFILE_SOURCE_PROFILE') do - resolve_source_profile(opts[:source_profile], opts) - end - metrics = provider ? provider.metrics : nil - if provider.is_a? AssumeRoleCredentials - opts[:credentials] = provider - opts[:credentials].resolving = true - metrics.pop - else - opts[:credentials] = provider ? provider.credentials : nil - metrics.unshift('CREDENTIALS_PROFILE_SOURCE_PROFILE') if metrics - end - if opts[:credentials] + provider = resolve_source_profile(opts[:source_profile], opts) + if provider && (opts[:credentials] = provider.credentials) opts[:role_session_name] ||= prof_cfg['role_session_name'] opts[:role_session_name] ||= 'default_session' opts[:role_arn] ||= prof_cfg['role_arn'] @@ -280,17 +269,28 @@ def assume_role_from_profile(cfg, profile, opts, chain_config) opts[:serial_number] ||= prof_cfg['mfa_serial'] opts[:profile] = opts.delete(:source_profile) opts.delete(:visited_profiles) + + metrics = provider.metrics + if provider.is_a? AssumeRoleCredentials + opts[:credentials] = provider + metrics.pop + else + opts[:credentials] = provider.credentials + metrics.unshift('CREDENTIALS_PROFILE_SOURCE_PROFILE') + end + opts[:credentials].resolving = true with_metrics(metrics) do credentials = AssumeRoleCredentials.new(opts) - if provider.is_a? Credentials - credentials.metrics_source = :static - elsif provider.is_a? AssumeRoleWebIdentityCredentials - credentials.metrics_source = :web_ID - elsif provider.is_a? ProcessCredentials - credentials.metrics_source = :process - else - credentials.metrics_source = provider.metrics_source - end + credentials.metrics_source = case provider + when Credentials + :static + when AssumeRoleWebIdentityCredentials + :web_ID + when ProcessCredentials + :process + else + provider.metrics_source + end credentials end else @@ -308,15 +308,18 @@ def assume_role_from_profile(cfg, profile, opts, chain_config) opts[:external_id] ||= prof_cfg['external_id'] opts[:serial_number] ||= prof_cfg['mfa_serial'] opts.delete(:source_profile) # Cleanup + metrics = opts[:credentials].metrics metrics.unshift('CREDENTIALS_PROFILE_NAMED_PROVIDER') + opts[:credentials].resolving = true with_metrics(metrics) do credentials = AssumeRoleCredentials.new(opts) - if opts[:credentials].is_a? InstanceProfileCredentials - credentials.metrics_source = :instance - elsif opts[:credentials].is_a? ECSCredentials - credentials.metrics_source = :ecs - end + credentials.metrics_source = case opts[:credentials] + when InstanceProfileCredentials + :instance + when ECSCredentials + :ecs + end credentials end else @@ -347,14 +350,15 @@ def resolve_source_profile(profile, opts = {}) elsif profile_config && profile_config['source_profile'] opts.delete(:source_profile) assume_role_credentials_from_config(opts.merge(profile: profile)) - elsif (provider = assume_role_web_identity_credentials_from_config(opts.merge(profile: profile))) - provider.credentials.metrics_source = :assume_role_resolution + elsif (provider = with_metrics('CREDENTIALS_PROFILE_SOURCE_PROFILE') do + assume_role_web_identity_credentials_from_config(opts.merge(profile: profile)) + end) provider if provider.credentials.set? elsif (provider = assume_role_process_credentials_from_config(profile)) - provider.credentials.metrics_source = :assume_role_resolution provider if provider.credentials.set? - elsif (provider = sso_credentials_from_config(profile: profile)) - provider.credentials.metrics_source = :assume_role_resolution + elsif (provider = with_metrics('CREDENTIALS_PROFILE_SOURCE_PROFILE') do + sso_credentials_from_config(profile: profile) + end) provider if provider.credentials.set? end end diff --git a/gems/aws-sdk-core/lib/seahorse/client/handler.rb b/gems/aws-sdk-core/lib/seahorse/client/handler.rb index d63b8b800c0..68fcb0d192b 100644 --- a/gems/aws-sdk-core/lib/seahorse/client/handler.rb +++ b/gems/aws-sdk-core/lib/seahorse/client/handler.rb @@ -17,9 +17,7 @@ def initialize(handler = nil) # @param [RequestContext] context # @return [Seahorse::Response] def call(context) - puts "Calling" @handler.call(context) - puts "Called" end def inspect diff --git a/gems/aws-sdk-core/spec/aws/assume_role_credentials_spec.rb b/gems/aws-sdk-core/spec/aws/assume_role_credentials_spec.rb index b53cb53fd48..60a3b0533de 100644 --- a/gems/aws-sdk-core/spec/aws/assume_role_credentials_spec.rb +++ b/gems/aws-sdk-core/spec/aws/assume_role_credentials_spec.rb @@ -206,46 +206,10 @@ module Aws context 'while resolving' do - it 'returns the correct metrics when the source is static' do + it 'returns no metrics' do c = resolving_creds c.metrics_source = :static - expect(c.metrics).to eq(%w[CREDENTIALS_PROFILE_SOURCE_PROFILE CREDENTIALS_PROFILE]) - end - - it 'returns the correct metrics when the source is webID' do - c = resolving_creds - c.metrics_source = :web_ID - expect(c.metrics).to eq(%w[CREDENTIALS_PROFILE_SOURCE_PROFILE CREDENTIALS_PROFILE_STS_WEB_ID_TOKEN CREDENTIALS_STS_ASSUME_ROLE_WEB_ID]) - end - - it 'returns the correct metrics when the source is process' do - c = resolving_creds - c.metrics_source = :process - expect(c.metrics).to eq(%w[CREDENTIALS_PROFILE_SOURCE_PROFILE CREDENTIALS_PROFILE_PROCESS CREDENTIALS_PROCESS]) - end - - it 'returns the correct metrics when the source is new SSO' do - c = resolving_creds - c.metrics_source = :new - expect(c.metrics).to eq(%w[CREDENTIALS_PROFILE_SOURCE_PROFILE CREDENTIALS_PROFILE_SSO CREDENTIALS_SSO]) - end - - it 'returns the correct metrics when the source is legacy SSO' do - c = resolving_creds - c.metrics_source = :legacy - expect(c.metrics).to eq(%w[CREDENTIALS_PROFILE_SOURCE_PROFILE CREDENTIALS_PROFILE_SSO_LEGACY CREDENTIALS_SSO_LEGACY]) - end - - it 'returns the correct metrics when the source is instance' do - c = resolving_creds - c.metrics_source = :instance - expect(c.metrics).to eq(%w[CREDENTIALS_PROFILE_NAMED_PROVIDER CREDENTIALS_IMDS]) - end - - it 'returns the correct metrics when the source is ecs' do - c = resolving_creds - c.metrics_source = :ecs - expect(c.metrics).to eq(%w[CREDENTIALS_PROFILE_NAMED_PROVIDER CREDENTIALS_HTTP]) + expect(c.metrics).to eq([]) end end diff --git a/gems/aws-sdk-core/spec/aws/credentials_spec.rb b/gems/aws-sdk-core/spec/aws/credentials_spec.rb index 93f850c7657..82867bbd90d 100644 --- a/gems/aws-sdk-core/spec/aws/credentials_spec.rb +++ b/gems/aws-sdk-core/spec/aws/credentials_spec.rb @@ -83,9 +83,9 @@ module Aws expect(creds.metrics).to eq(['CREDENTIALS_ENV_VARS']) end - it 'returns no metrics when the source is assume_role_resolution' do + it 'returns no metrics when resolving' do creds = Credentials.new('akid', 'secret') - creds.metrics_source = :assume_role_resolution + creds.resolving = true expect(creds.metrics).to eq([]) end end diff --git a/gems/aws-sdk-core/spec/aws/ecs_credentials_spec.rb b/gems/aws-sdk-core/spec/aws/ecs_credentials_spec.rb index 797fb122431..9953b99bf38 100644 --- a/gems/aws-sdk-core/spec/aws/ecs_credentials_spec.rb +++ b/gems/aws-sdk-core/spec/aws/ecs_credentials_spec.rb @@ -92,6 +92,12 @@ module Aws expect(c.metrics).to eq(['CREDENTIALS_HTTP']) end + it 'will return no metrics when resolving' do + c = ECSCredentials.new(backoff: 0, retries: 0) + c.resolving = true + expect(c.metrics).to eq([]) + end + context 'auto refreshing' do # expire in 4 minutes let(:expiration) { Time.now.utc + 299 } diff --git a/gems/aws-sdk-core/spec/aws/instance_profile_credentials_spec.rb b/gems/aws-sdk-core/spec/aws/instance_profile_credentials_spec.rb index 8f2d91b1023..8b3e797421f 100644 --- a/gems/aws-sdk-core/spec/aws/instance_profile_credentials_spec.rb +++ b/gems/aws-sdk-core/spec/aws/instance_profile_credentials_spec.rb @@ -692,5 +692,11 @@ module Aws c = InstanceProfileCredentials.new expect(c.metrics).to eq(['CREDENTIALS_IMDS']) end + + it 'will return no metrics when resolving' do + c = InstanceProfileCredentials.new + c.resolving = true + expect(c.metrics).to eq([]) + end end end From 16301883632a1e489eb4f653b862f993a348d22b Mon Sep 17 00:00:00 2001 From: Richard Wang Date: Thu, 3 Apr 2025 10:20:09 -0700 Subject: [PATCH 45/59] Add keyword argument for metrics_source --- .../aws-sdk-core/assume_role_credentials.rb | 4 +- .../assume_role_web_identity_credentials.rb | 4 +- .../aws-sdk-core/credential_provider_chain.rb | 26 +++------ .../lib/aws-sdk-core/credentials.rb | 4 +- .../lib/aws-sdk-core/process_credentials.rb | 4 +- .../aws-sdk-core/refreshing_credentials.rb | 2 +- .../lib/aws-sdk-core/shared_config.rb | 55 ++++++++----------- .../lib/aws-sdk-core/sso_credentials.rb | 4 +- .../aws/credential_resolution_chain_spec.rb | 32 +++++------ 9 files changed, 57 insertions(+), 78 deletions(-) diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_credentials.rb b/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_credentials.rb index 73325f153cd..3e991c2acb1 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_credentials.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_credentials.rb @@ -38,7 +38,7 @@ class AssumeRoleCredentials # assume_role_credentials.assume_role_params['token_code'] = update_token # end # - def initialize(options = {}) + def initialize(options = {}, metrics_source = nil) client_opts = {} @assume_role_params = {} options.each_pair do |key, value| @@ -50,7 +50,7 @@ def initialize(options = {}) end @client = client_opts[:client] || STS::Client.new(client_opts) @async_refresh = true - @metrics_source = :code + @metrics_source = metrics_source || :code super end diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_web_identity_credentials.rb b/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_web_identity_credentials.rb index 67e1a801834..f1843cecdf7 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_web_identity_credentials.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_web_identity_credentials.rb @@ -43,7 +43,7 @@ class AssumeRoleWebIdentityCredentials # credentials are refreshed. `before_refresh` is called # with an instance of this object when # AWS credentials are required and need to be refreshed. - def initialize(options = {}) + def initialize(options = {}, metrics_source = nil) client_opts = {} @assume_role_web_identity_params = {} @token_file = options.delete(:web_identity_token_file) @@ -61,7 +61,7 @@ def initialize(options = {}) @assume_role_web_identity_params[:role_session_name] = _session_name end @client = client_opts[:client] || STS::Client.new(client_opts.merge(credentials: nil)) - @metrics_source = :code + @metrics_source = metrics_source || :code super end diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/credential_provider_chain.rb b/gems/aws-sdk-core/lib/aws-sdk-core/credential_provider_chain.rb index 89547bcbedb..329e20b1bd1 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/credential_provider_chain.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/credential_provider_chain.rb @@ -42,14 +42,13 @@ def providers def static_credentials(options) if options[:config] - credentials = Credentials.new( + Credentials.new( options[:config].access_key_id, options[:config].secret_access_key, options[:config].session_token, + :profile, account_id: options[:config].account_id ) - credentials.metrics_source = :profile - credentials end end @@ -87,11 +86,7 @@ def static_profile_credentials(options) def static_profile_process_credentials(options) if Aws.shared_config.config_enabled? && options[:config] && options[:config].profile process_provider = Aws.shared_config.credential_process(profile: options[:config].profile) - if process_provider - credentials = ProcessCredentials.new([process_provider]) - credentials.metrics_source = :profile - credentials - end + ProcessCredentials.new([process_provider], :profile) if process_provider end rescue Errors::NoSuchProfileError nil @@ -103,14 +98,13 @@ def env_credentials(_options) secret = %w[AWS_SECRET_ACCESS_KEY AMAZON_SECRET_ACCESS_KEY AWS_SECRET_KEY] token = %w[AWS_SESSION_TOKEN AMAZON_SESSION_TOKEN] account_id = %w[AWS_ACCOUNT_ID] - credentials = Credentials.new( + Credentials.new( envar(key), envar(secret), envar(token), + :env, account_id: envar(account_id) ) - credentials.metrics_source = :env - credentials end def envar(keys) @@ -135,11 +129,7 @@ def process_credentials(options) profile_name = determine_profile_name(options) if Aws.shared_config.config_enabled? process_provider = Aws.shared_config.credential_process(profile: profile_name) - if process_provider - credentials = ProcessCredentials.new([process_provider]) - credentials.metrics_source = :profile - credentials - end + ProcessCredentials.new([process_provider], :profile) if process_provider end rescue Errors::NoSuchProfileError nil @@ -170,9 +160,7 @@ def assume_role_web_identity_credentials(options) } cfg[:region] = region if region Aws::Plugins::UserAgent.metric('CREDENTIALS_ENV_VARS_STS_WEB_ID_TOKEN') do - credentials = AssumeRoleWebIdentityCredentials.new(cfg) - credentials.metrics_source = :env - credentials + AssumeRoleWebIdentityCredentials.new(cfg, :env) end elsif Aws.shared_config.config_enabled? profile = options[:config].profile if options[:config] diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/credentials.rb b/gems/aws-sdk-core/lib/aws-sdk-core/credentials.rb index 25ef2956ab4..753222631f2 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/credentials.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/credentials.rb @@ -8,13 +8,13 @@ class Credentials # @param [String] session_token (nil) # @param [Hash] kwargs # @option kwargs [String] :credential_scope (nil) - def initialize(access_key_id, secret_access_key, session_token = nil, + def initialize(access_key_id, secret_access_key, session_token = nil, metrics_source = nil, **kwargs) @access_key_id = access_key_id @secret_access_key = secret_access_key @session_token = session_token @account_id = kwargs[:account_id] - @metrics_source = :code + @metrics_source = metrics_source || :code end # @return [String] diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/process_credentials.rb b/gems/aws-sdk-core/lib/aws-sdk-core/process_credentials.rb index 9e47366a203..d06e1658555 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/process_credentials.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/process_credentials.rb @@ -28,7 +28,7 @@ class ProcessCredentials # @param [Array, String] process An array of strings including # the process name and its arguments to execute, or a single string to be # executed by the shell (deprecated and insecure). - def initialize(process) + def initialize(process, metrics_source = nil) if process.is_a?(String) warn('Passing a single string to Aws::ProcessCredentials.new '\ 'is insecure, please use use an array of system arguments instead') @@ -36,7 +36,7 @@ def initialize(process) @process = process @credentials = credentials_from_process @async_refresh = false - @metrics_source = :code + @metrics_source = metrics_source || :code super end diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/refreshing_credentials.rb b/gems/aws-sdk-core/lib/aws-sdk-core/refreshing_credentials.rb index c37dc012804..dbbb231a6ac 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/refreshing_credentials.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/refreshing_credentials.rb @@ -20,7 +20,7 @@ module RefreshingCredentials CLIENT_EXCLUDE_OPTIONS = Set.new([:before_refresh]).freeze - def initialize(options = {}) + def initialize(options = {}, metrics_source = nil) @mutex = Mutex.new @before_refresh = options.delete(:before_refresh) if Hash === options diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/shared_config.rb b/gems/aws-sdk-core/lib/aws-sdk-core/shared_config.rb index 48e347d0e26..b80240f5e6a 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/shared_config.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/shared_config.rb @@ -139,9 +139,7 @@ def assume_role_web_identity_credentials_from_config(opts = {}) } cfg[:region] = opts[:region] if opts[:region] with_metrics('CREDENTIALS_PROFILE_STS_WEB_ID_TOKEN') do - credentials = AssumeRoleWebIdentityCredentials.new(cfg) - credentials.metrics_source = :profile - credentials + AssumeRoleWebIdentityCredentials.new(cfg, :profile) end end end @@ -279,19 +277,18 @@ def assume_role_from_profile(cfg, profile, opts, chain_config) metrics.unshift('CREDENTIALS_PROFILE_SOURCE_PROFILE') end opts[:credentials].resolving = true + metrics_source = case provider + when Credentials + :static + when AssumeRoleWebIdentityCredentials + :web_ID + when ProcessCredentials + :process + else + provider.metrics_source + end with_metrics(metrics) do - credentials = AssumeRoleCredentials.new(opts) - credentials.metrics_source = case provider - when Credentials - :static - when AssumeRoleWebIdentityCredentials - :web_ID - when ProcessCredentials - :process - else - provider.metrics_source - end - credentials + AssumeRoleCredentials.new(opts, metrics_source) end else raise Errors::NoSourceProfileError, @@ -312,15 +309,14 @@ def assume_role_from_profile(cfg, profile, opts, chain_config) metrics = opts[:credentials].metrics metrics.unshift('CREDENTIALS_PROFILE_NAMED_PROVIDER') opts[:credentials].resolving = true + metrics_source = case opts[:credentials] + when InstanceProfileCredentials + :instance + when ECSCredentials + :ecs + end with_metrics(metrics) do - credentials = AssumeRoleCredentials.new(opts) - credentials.metrics_source = case opts[:credentials] - when InstanceProfileCredentials - :instance - when ECSCredentials - :ecs - end - credentials + AssumeRoleCredentials.new(opts, metrics_source) end else raise Errors::NoSourceCredentials, @@ -345,7 +341,6 @@ def resolve_source_profile(profile, opts = {}) end if (creds = credentials(profile: profile)) - creds.metrics_source = :profile creds # static credentials elsif profile_config && profile_config['source_profile'] opts.delete(:source_profile) @@ -384,11 +379,7 @@ def assume_role_process_credentials_from_config(profile) if @parsed_config credential_process ||= @parsed_config.fetch(profile, {})['credential_process'] end - if credential_process - credentials = ProcessCredentials.new([credential_process]) - credentials.metrics_source = :profile - credentials - end + ProcessCredentials.new([credential_process], :profile) if credential_process end def credentials_from_shared(profile, _opts) @@ -434,15 +425,14 @@ def sso_credentials_from_profile(cfg, profile) metric = prof_config['sso_session'] ? 'CREDENTIALS_PROFILE_SSO' : 'CREDENTIALS_PROFILE_SSO_LEGACY' with_metrics(metric) do - credentials = SSOCredentials.new( + SSOCredentials.new( sso_account_id: prof_config['sso_account_id'], sso_role_name: prof_config['sso_role_name'], sso_session: prof_config['sso_session'], sso_region: sso_region, sso_start_url: sso_start_url, + metrics_source: prof_config['sso_session'] ? :new : :legacy ) - credentials.metrics_source = prof_config['sso_session'] ? :new : :legacy - credentials end end end @@ -469,6 +459,7 @@ def credentials_from_profile(prof_config) prof_config['aws_access_key_id'], prof_config['aws_secret_access_key'], prof_config['aws_session_token'], + :profile, account_id: prof_config['aws_account_id'] ) creds if creds.set? diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/sso_credentials.rb b/gems/aws-sdk-core/lib/aws-sdk-core/sso_credentials.rb index 354d48e32a0..04c8d2c6bab 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/sso_credentials.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/sso_credentials.rb @@ -66,7 +66,7 @@ class SSOCredentials # credentials are refreshed. `before_refresh` is called # with an instance of this object when # AWS credentials are required and need to be refreshed. - def initialize(options = {}) + def initialize(options = {}, metrics_source = nil) options = options.select {|k, v| !v.nil? } if (options[:sso_session]) missing_keys = TOKEN_PROVIDER_REQUIRED_OPTS.select { |k| options[k].nil? } @@ -114,7 +114,7 @@ def initialize(options = {}) end @async_refresh = true - @metrics_source = :code + @metrics_source = metrics_source || :code super end diff --git a/gems/aws-sdk-core/spec/aws/credential_resolution_chain_spec.rb b/gems/aws-sdk-core/spec/aws/credential_resolution_chain_spec.rb index 8caa0aebbfe..2edcde19e71 100644 --- a/gems/aws-sdk-core/spec/aws/credential_resolution_chain_spec.rb +++ b/gems/aws-sdk-core/spec/aws/credential_resolution_chain_spec.rb @@ -190,9 +190,9 @@ module Aws sso_region: 'us-east-1', sso_account_id: 'SSO_ACCOUNT_ID', sso_role_name: 'SSO_ROLE_NAME', - sso_session: 'sso-test-session' + sso_session: 'sso-test-session', + metrics_source: :new ).and_return(creds) - expect(creds).to receive(:metrics_source=).with(:new) client = ApiHelper.sample_rest_xml::Client.new( profile: 'sso_creds', token_provider: nil @@ -210,9 +210,9 @@ module Aws sso_region: 'us-east-1', sso_account_id: 'SSO_ACCOUNT_ID', sso_role_name: 'SSO_ROLE_NAME', - sso_session: nil + sso_session: nil, + metrics_source: :legacy ).and_return(creds) - expect(creds).to receive(:metrics_source=).with(:legacy) client = ApiHelper.sample_rest_xml::Client.new( profile: 'sso_creds_legacy' ) @@ -229,9 +229,9 @@ module Aws sso_region: 'us-east-1', sso_account_id: 'SSO_ACCOUNT_ID', sso_role_name: 'SSO_ROLE_NAME', - sso_session: 'sso-test-session' + sso_session: 'sso-test-session', + metrics_source: :new ).and_return(creds) - expect(creds).to receive(:metrics_source=).with(:new) client = ApiHelper.sample_rest_xml::Client.new( profile: 'sso_creds_mixed_legacy', token_provider: nil, @@ -249,9 +249,9 @@ module Aws sso_region: 'us-east-1', sso_account_id: 'SSO_ACCOUNT_ID', sso_role_name: 'SSO_ROLE_NAME', - sso_session: 'sso test session' + sso_session: 'sso test session', + metrics_source: :new ).and_return(creds) - expect(creds).to receive(:metrics_source=).with(:new) client = ApiHelper.sample_rest_xml::Client.new( profile: 'sso_creds_session_with_quotes', token_provider: nil @@ -548,9 +548,9 @@ module Aws sso_region: 'us-east-1', sso_account_id: 'SSO_ACCOUNT_ID', sso_role_name: 'SSO_ROLE_NAME', - sso_session: 'sso-test-session' + sso_session: 'sso-test-session', + metrics_source: :new ).and_return(creds) - expect(creds).to receive(:metrics_source=).with(:new) expect(creds).to receive(:metrics_source).and_return(:new) allow(SSOTokenProvider).to receive(:new) @@ -581,9 +581,9 @@ module Aws sso_region: 'us-east-1', sso_account_id: 'SSO_ACCOUNT_ID', sso_role_name: 'SSO_ROLE_NAME', - sso_session: 'sso-test-session' + sso_session: 'sso-test-session', + metrics_source: :new ).and_return(creds) - expect(creds).to receive(:metrics_source=).with(:new) expect(creds).to receive(:metrics_source).and_return(:new) allow(SSOTokenProvider).to receive(:new) @@ -615,9 +615,9 @@ module Aws sso_region: 'us-east-1', sso_account_id: 'SSO_ACCOUNT_ID', sso_role_name: 'SSO_ROLE_NAME', - sso_session: nil + sso_session: nil, + metrics_source: :legacy ).and_return(creds) - expect(creds).to receive(:metrics_source=).with(:legacy) expect(creds).to receive(:metrics_source).and_return(:legacy) allow(SSOTokenProvider).to receive(:new) @@ -648,9 +648,9 @@ module Aws sso_region: 'us-east-1', sso_account_id: 'SSO_ACCOUNT_ID', sso_role_name: 'SSO_ROLE_NAME', - sso_session: nil + sso_session: nil, + metrics_source: :legacy ).and_return(creds) - expect(creds).to receive(:metrics_source=).with(:legacy) expect(creds).to receive(:metrics_source).and_return(:legacy) allow(SSOTokenProvider).to receive(:new) From 4cf1af3098fffb5ed56985c538333a6b774ee2e4 Mon Sep 17 00:00:00 2001 From: Richard Wang Date: Fri, 4 Apr 2025 10:06:52 -0700 Subject: [PATCH 46/59] Clean up code --- gems/aws-sdk-core/lib/aws-sdk-core/plugins/user_agent.rb | 2 -- gems/aws-sdk-core/lib/aws-sdk-core/shared_config.rb | 3 +-- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/plugins/user_agent.rb b/gems/aws-sdk-core/lib/aws-sdk-core/plugins/user_agent.rb index a6b0494bef7..b8c472eddb3 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/plugins/user_agent.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/plugins/user_agent.rb @@ -213,8 +213,6 @@ def metric_metadata end metrics = Thread.current[:aws_sdk_core_user_agent_metric].join(',') - # puts "User agent metrics" - # puts metrics # Metric metadata is limited to 1024 bytes return "m/#{metrics}" if metrics.bytesize <= 1024 diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/shared_config.rb b/gems/aws-sdk-core/lib/aws-sdk-core/shared_config.rb index b80240f5e6a..c3a5b960a70 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/shared_config.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/shared_config.rb @@ -273,7 +273,6 @@ def assume_role_from_profile(cfg, profile, opts, chain_config) opts[:credentials] = provider metrics.pop else - opts[:credentials] = provider.credentials metrics.unshift('CREDENTIALS_PROFILE_SOURCE_PROFILE') end opts[:credentials].resolving = true @@ -364,7 +363,7 @@ def credentials_from_source(credential_source, config) InstanceProfileCredentials.new( retries: config ? config.instance_profile_credentials_retries : 0, http_open_timeout: config ? config.instance_profile_credentials_timeout : 1, - http_read_timeout: config ? config.instance_profile_credentials_timeout : 1, + http_read_timeout: config ? config.instance_profile_credentials_timeout : 1 ) when 'EcsContainer' ECSCredentials.new From 484288b30450b68c8d984a47995f9d0dffae4d99 Mon Sep 17 00:00:00 2001 From: Richard Wang Date: Fri, 4 Apr 2025 10:25:47 -0700 Subject: [PATCH 47/59] 'Disable' client side user-agent metric? --- .../lib/aws-sdk-core/plugins/client_metrics_plugin.rb | 2 +- gems/aws-sdk-core/spec/aws/plugins/client_metrics_spec.rb | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/plugins/client_metrics_plugin.rb b/gems/aws-sdk-core/lib/aws-sdk-core/plugins/client_metrics_plugin.rb index 4b63fd4c6d8..2507075d270 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/plugins/client_metrics_plugin.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/plugins/client_metrics_plugin.rb @@ -180,7 +180,7 @@ def call(context) complete_opts = { latency: end_time - start_time, attempt_count: context.retries + 1, - user_agent: context.http_request.headers["user-agent"], + # user_agent: context.http_request.headers["user-agent"], final_error_retryable: final_error_retryable, final_http_status_code: context.http_response.status_code, final_aws_exception: final_aws_exception, diff --git a/gems/aws-sdk-core/spec/aws/plugins/client_metrics_spec.rb b/gems/aws-sdk-core/spec/aws/plugins/client_metrics_spec.rb index bc40fb5d102..4427cf2949a 100644 --- a/gems/aws-sdk-core/spec/aws/plugins/client_metrics_spec.rb +++ b/gems/aws-sdk-core/spec/aws/plugins/client_metrics_spec.rb @@ -174,7 +174,7 @@ module Plugins expect(api_call.latency).to be_a_kind_of(Integer) expect(api_call.client_id).to eq('') expect(api_call.region).to eq('us-stubbed-1') - expect(api_call.user_agent).to match(/^aws-sdk-ruby3/) + # expect(api_call.user_agent).to match(/^aws-sdk-ruby3/) expect(api_call.final_http_status_code).to eq(200) end end @@ -194,7 +194,7 @@ module Plugins expect(attempt.version).to be_a_kind_of(Integer) expect(attempt.fqdn).to eq('s3.us-stubbed-1.amazonaws.com') expect(attempt.region).to eq('us-stubbed-1') - expect(attempt.user_agent).to match(/^aws-sdk-ruby3/) + # expect(attempt.user_agent).to match(/^aws-sdk-ruby3/) expect(attempt.access_key).to eq('stubbed-akid') expect(attempt.http_status_code).to eq(200) expect(attempt.request_latency).to be_a_kind_of(Integer) From 8d844366d9745475b1f21951e4b136943c9134c7 Mon Sep 17 00:00:00 2001 From: Richard Wang Date: Fri, 4 Apr 2025 11:13:15 -0700 Subject: [PATCH 48/59] Fix syntax error --- gems/aws-sdk-core/spec/aws/credential_resolution_chain_spec.rb | 2 +- gems/aws-sdk-core/spec/aws/plugins/sign_spec.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/gems/aws-sdk-core/spec/aws/credential_resolution_chain_spec.rb b/gems/aws-sdk-core/spec/aws/credential_resolution_chain_spec.rb index 2edcde19e71..5785fff7f1e 100644 --- a/gems/aws-sdk-core/spec/aws/credential_resolution_chain_spec.rb +++ b/gems/aws-sdk-core/spec/aws/credential_resolution_chain_spec.rb @@ -1190,7 +1190,7 @@ def stub_token_file(token) end def metrics_from_user_agent_header(header) - header[(header.index('m/')+2)..] + header[(header.index('m/') + 2)..-1] end end end diff --git a/gems/aws-sdk-core/spec/aws/plugins/sign_spec.rb b/gems/aws-sdk-core/spec/aws/plugins/sign_spec.rb index db87f440dcd..87bcd7e63b5 100644 --- a/gems/aws-sdk-core/spec/aws/plugins/sign_spec.rb +++ b/gems/aws-sdk-core/spec/aws/plugins/sign_spec.rb @@ -209,7 +209,7 @@ def call(context) resp = client.operation req = resp.context.http_request header = req.headers['User-Agent'] - metrics = header[(header.index('m/')+2)..] + metrics = header[(header.index('m/') + 2)..-1] expect(metrics).to include('e') end end From c58aaec582fcd60c26eea87ac92a7efb36de8bc1 Mon Sep 17 00:00:00 2001 From: Richard Wang Date: Mon, 7 Apr 2025 11:56:19 -0700 Subject: [PATCH 49/59] Revert to setter --- .../aws-sdk-core/assume_role_credentials.rb | 8 +-- .../assume_role_web_identity_credentials.rb | 8 +-- .../lib/aws-sdk-core/credential_provider.rb | 5 ++ .../aws-sdk-core/credential_provider_chain.rb | 26 ++++++--- .../lib/aws-sdk-core/credentials.rb | 6 +- .../lib/aws-sdk-core/process_credentials.rb | 8 +-- .../aws-sdk-core/refreshing_credentials.rb | 2 +- .../lib/aws-sdk-core/shared_config.rb | 57 +++++++++++-------- .../lib/aws-sdk-core/sso_credentials.rb | 8 +-- .../aws/credential_resolution_chain_spec.rb | 16 +++--- 10 files changed, 78 insertions(+), 66 deletions(-) diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_credentials.rb b/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_credentials.rb index 3e991c2acb1..25a677cc0af 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_credentials.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_credentials.rb @@ -38,7 +38,7 @@ class AssumeRoleCredentials # assume_role_credentials.assume_role_params['token_code'] = update_token # end # - def initialize(options = {}, metrics_source = nil) + def initialize(options = {}) client_opts = {} @assume_role_params = {} options.each_pair do |key, value| @@ -50,7 +50,7 @@ def initialize(options = {}, metrics_source = nil) end @client = client_opts[:client] || STS::Client.new(client_opts) @async_refresh = true - @metrics_source = metrics_source || :code + @metrics_source = :code super end @@ -60,10 +60,6 @@ def initialize(options = {}, metrics_source = nil) # @return [Hash] attr_reader :assume_role_params - # @return [String] Returns the credentials source. Used for - # tracking credentials related UserAgent metrics. - attr_accessor :metrics_source - # @return [Boolean] Returns `true` if instance is created # during source profile resolution for AssumeRoleCredentials. # Used for tracking credentials related UserAgent metrics. diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_web_identity_credentials.rb b/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_web_identity_credentials.rb index f1843cecdf7..8792f5d80fe 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_web_identity_credentials.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_web_identity_credentials.rb @@ -43,7 +43,7 @@ class AssumeRoleWebIdentityCredentials # credentials are refreshed. `before_refresh` is called # with an instance of this object when # AWS credentials are required and need to be refreshed. - def initialize(options = {}, metrics_source = nil) + def initialize(options = {}) client_opts = {} @assume_role_web_identity_params = {} @token_file = options.delete(:web_identity_token_file) @@ -61,17 +61,13 @@ def initialize(options = {}, metrics_source = nil) @assume_role_web_identity_params[:role_session_name] = _session_name end @client = client_opts[:client] || STS::Client.new(client_opts.merge(credentials: nil)) - @metrics_source = metrics_source || :code + @metrics_source = :code super end # @return [STS::Client] attr_reader :client - # @return [String] Returns the credentials source. Used for - # tracking credentials related UserAgent metrics. - attr_accessor :metrics_source - def metrics base = ['CREDENTIALS_STS_ASSUME_ROLE_WEB_ID'] case @metrics_source diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/credential_provider.rb b/gems/aws-sdk-core/lib/aws-sdk-core/credential_provider.rb index 7f3a20c5708..c39ed0e23c3 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/credential_provider.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/credential_provider.rb @@ -9,6 +9,11 @@ module CredentialProvider # @return [Time] attr_reader :expiration + # @api private + # @return [String] Returns the credentials source. Used for + # tracking credentials related UserAgent metrics. + attr_accessor :metrics_source + # @return [Boolean] def set? !!@credentials && @credentials.set? diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/credential_provider_chain.rb b/gems/aws-sdk-core/lib/aws-sdk-core/credential_provider_chain.rb index 329e20b1bd1..117e37daa59 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/credential_provider_chain.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/credential_provider_chain.rb @@ -42,13 +42,14 @@ def providers def static_credentials(options) if options[:config] - Credentials.new( + creds = Credentials.new( options[:config].access_key_id, options[:config].secret_access_key, options[:config].session_token, - :profile, account_id: options[:config].account_id ) + creds.metrics_source = :profile + creds end end @@ -86,7 +87,11 @@ def static_profile_credentials(options) def static_profile_process_credentials(options) if Aws.shared_config.config_enabled? && options[:config] && options[:config].profile process_provider = Aws.shared_config.credential_process(profile: options[:config].profile) - ProcessCredentials.new([process_provider], :profile) if process_provider + if process_provider + creds = ProcessCredentials.new([process_provider]) + creds.metrics_source = :profile + creds + end end rescue Errors::NoSuchProfileError nil @@ -98,13 +103,14 @@ def env_credentials(_options) secret = %w[AWS_SECRET_ACCESS_KEY AMAZON_SECRET_ACCESS_KEY AWS_SECRET_KEY] token = %w[AWS_SESSION_TOKEN AMAZON_SESSION_TOKEN] account_id = %w[AWS_ACCOUNT_ID] - Credentials.new( + creds = Credentials.new( envar(key), envar(secret), envar(token), - :env, account_id: envar(account_id) ) + creds.metrics_source = :env + creds end def envar(keys) @@ -129,7 +135,11 @@ def process_credentials(options) profile_name = determine_profile_name(options) if Aws.shared_config.config_enabled? process_provider = Aws.shared_config.credential_process(profile: profile_name) - ProcessCredentials.new([process_provider], :profile) if process_provider + if process_provider + creds = ProcessCredentials.new([process_provider]) + creds.metrics_source = :profile + creds + end end rescue Errors::NoSuchProfileError nil @@ -160,7 +170,9 @@ def assume_role_web_identity_credentials(options) } cfg[:region] = region if region Aws::Plugins::UserAgent.metric('CREDENTIALS_ENV_VARS_STS_WEB_ID_TOKEN') do - AssumeRoleWebIdentityCredentials.new(cfg, :env) + creds = AssumeRoleWebIdentityCredentials.new(cfg) + creds.metrics_source = :env + creds end elsif Aws.shared_config.config_enabled? profile = options[:config].profile if options[:config] diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/credentials.rb b/gems/aws-sdk-core/lib/aws-sdk-core/credentials.rb index 753222631f2..293ca07054b 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/credentials.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/credentials.rb @@ -8,13 +8,13 @@ class Credentials # @param [String] session_token (nil) # @param [Hash] kwargs # @option kwargs [String] :credential_scope (nil) - def initialize(access_key_id, secret_access_key, session_token = nil, metrics_source = nil, + def initialize(access_key_id, secret_access_key, session_token = nil, **kwargs) @access_key_id = access_key_id @secret_access_key = secret_access_key @session_token = session_token @account_id = kwargs[:account_id] - @metrics_source = metrics_source || :code + @metrics_source = :code end # @return [String] @@ -29,10 +29,12 @@ def initialize(access_key_id, secret_access_key, session_token = nil, metrics_so # @return [String, nil] attr_reader :account_id + # @api private # @return [String] Returns the credentials source. Used for # tracking credentials related UserAgent metrics. attr_accessor :metrics_source + # @api private # @return [Boolean] Returns `true` if instance is created # during source profile resolution for AssumeRoleCredentials. # Used for tracking credentials related UserAgent metrics. diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/process_credentials.rb b/gems/aws-sdk-core/lib/aws-sdk-core/process_credentials.rb index d06e1658555..2ddb3d209fb 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/process_credentials.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/process_credentials.rb @@ -28,7 +28,7 @@ class ProcessCredentials # @param [Array, String] process An array of strings including # the process name and its arguments to execute, or a single string to be # executed by the shell (deprecated and insecure). - def initialize(process, metrics_source = nil) + def initialize(process) if process.is_a?(String) warn('Passing a single string to Aws::ProcessCredentials.new '\ 'is insecure, please use use an array of system arguments instead') @@ -36,15 +36,11 @@ def initialize(process, metrics_source = nil) @process = process @credentials = credentials_from_process @async_refresh = false - @metrics_source = metrics_source || :code + @metrics_source = :code super end - # @return [String] Returns the credentials source. Used for - # tracking credentials related UserAgent metrics. - attr_accessor :metrics_source - def metrics base = ['CREDENTIALS_PROCESS'] diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/refreshing_credentials.rb b/gems/aws-sdk-core/lib/aws-sdk-core/refreshing_credentials.rb index dbbb231a6ac..c37dc012804 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/refreshing_credentials.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/refreshing_credentials.rb @@ -20,7 +20,7 @@ module RefreshingCredentials CLIENT_EXCLUDE_OPTIONS = Set.new([:before_refresh]).freeze - def initialize(options = {}, metrics_source = nil) + def initialize(options = {}) @mutex = Mutex.new @before_refresh = options.delete(:before_refresh) if Hash === options diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/shared_config.rb b/gems/aws-sdk-core/lib/aws-sdk-core/shared_config.rb index c3a5b960a70..61a6bc7c064 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/shared_config.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/shared_config.rb @@ -139,7 +139,9 @@ def assume_role_web_identity_credentials_from_config(opts = {}) } cfg[:region] = opts[:region] if opts[:region] with_metrics('CREDENTIALS_PROFILE_STS_WEB_ID_TOKEN') do - AssumeRoleWebIdentityCredentials.new(cfg, :profile) + creds = AssumeRoleWebIdentityCredentials.new(cfg) + creds.metrics_source = :profile + creds end end end @@ -276,18 +278,19 @@ def assume_role_from_profile(cfg, profile, opts, chain_config) metrics.unshift('CREDENTIALS_PROFILE_SOURCE_PROFILE') end opts[:credentials].resolving = true - metrics_source = case provider - when Credentials - :static - when AssumeRoleWebIdentityCredentials - :web_ID - when ProcessCredentials - :process - else - provider.metrics_source - end with_metrics(metrics) do - AssumeRoleCredentials.new(opts, metrics_source) + creds = AssumeRoleCredentials.new(opts) + creds.metrics_source = case provider + when Credentials + :static + when AssumeRoleWebIdentityCredentials + :web_ID + when ProcessCredentials + :process + else + provider.metrics_source + end + creds end else raise Errors::NoSourceProfileError, @@ -308,14 +311,15 @@ def assume_role_from_profile(cfg, profile, opts, chain_config) metrics = opts[:credentials].metrics metrics.unshift('CREDENTIALS_PROFILE_NAMED_PROVIDER') opts[:credentials].resolving = true - metrics_source = case opts[:credentials] - when InstanceProfileCredentials - :instance - when ECSCredentials - :ecs - end with_metrics(metrics) do - AssumeRoleCredentials.new(opts, metrics_source) + creds = AssumeRoleCredentials.new(opts) + creds.metrics_source = case opts[:credentials] + when InstanceProfileCredentials + :instance + when ECSCredentials + :ecs + end + creds end else raise Errors::NoSourceCredentials, @@ -378,7 +382,11 @@ def assume_role_process_credentials_from_config(profile) if @parsed_config credential_process ||= @parsed_config.fetch(profile, {})['credential_process'] end - ProcessCredentials.new([credential_process], :profile) if credential_process + if credential_process + creds = ProcessCredentials.new([credential_process]) + creds.metrics_source = :profile + creds + end end def credentials_from_shared(profile, _opts) @@ -424,14 +432,15 @@ def sso_credentials_from_profile(cfg, profile) metric = prof_config['sso_session'] ? 'CREDENTIALS_PROFILE_SSO' : 'CREDENTIALS_PROFILE_SSO_LEGACY' with_metrics(metric) do - SSOCredentials.new( + creds = SSOCredentials.new( sso_account_id: prof_config['sso_account_id'], sso_role_name: prof_config['sso_role_name'], sso_session: prof_config['sso_session'], sso_region: sso_region, sso_start_url: sso_start_url, - metrics_source: prof_config['sso_session'] ? :new : :legacy ) + creds.metrics_source = prof_config['sso_session'] ? :new : :legacy + creds end end end @@ -458,10 +467,10 @@ def credentials_from_profile(prof_config) prof_config['aws_access_key_id'], prof_config['aws_secret_access_key'], prof_config['aws_session_token'], - :profile, account_id: prof_config['aws_account_id'] ) - creds if creds.set? + creds.metrics_source = :profile + creds if creds.set? end def load_credentials_file diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/sso_credentials.rb b/gems/aws-sdk-core/lib/aws-sdk-core/sso_credentials.rb index 04c8d2c6bab..84f28943cc4 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/sso_credentials.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/sso_credentials.rb @@ -66,7 +66,7 @@ class SSOCredentials # credentials are refreshed. `before_refresh` is called # with an instance of this object when # AWS credentials are required and need to be refreshed. - def initialize(options = {}, metrics_source = nil) + def initialize(options = {}) options = options.select {|k, v| !v.nil? } if (options[:sso_session]) missing_keys = TOKEN_PROVIDER_REQUIRED_OPTS.select { |k| options[k].nil? } @@ -114,17 +114,13 @@ def initialize(options = {}, metrics_source = nil) end @async_refresh = true - @metrics_source = metrics_source || :code + @metrics_source = :code super end # @return [SSO::Client] attr_reader :client - # @return [String] Returns the credentials source. Used for - # tracking credentials related UserAgent metrics. - attr_accessor :metrics_source - def metrics case @metrics_source when :new diff --git a/gems/aws-sdk-core/spec/aws/credential_resolution_chain_spec.rb b/gems/aws-sdk-core/spec/aws/credential_resolution_chain_spec.rb index 5785fff7f1e..3c451704912 100644 --- a/gems/aws-sdk-core/spec/aws/credential_resolution_chain_spec.rb +++ b/gems/aws-sdk-core/spec/aws/credential_resolution_chain_spec.rb @@ -191,8 +191,8 @@ module Aws sso_account_id: 'SSO_ACCOUNT_ID', sso_role_name: 'SSO_ROLE_NAME', sso_session: 'sso-test-session', - metrics_source: :new ).and_return(creds) + expect(creds).to receive(:metrics_source=).with(:new) client = ApiHelper.sample_rest_xml::Client.new( profile: 'sso_creds', token_provider: nil @@ -211,8 +211,8 @@ module Aws sso_account_id: 'SSO_ACCOUNT_ID', sso_role_name: 'SSO_ROLE_NAME', sso_session: nil, - metrics_source: :legacy ).and_return(creds) + expect(creds).to receive(:metrics_source=).with(:legacy) client = ApiHelper.sample_rest_xml::Client.new( profile: 'sso_creds_legacy' ) @@ -230,8 +230,8 @@ module Aws sso_account_id: 'SSO_ACCOUNT_ID', sso_role_name: 'SSO_ROLE_NAME', sso_session: 'sso-test-session', - metrics_source: :new ).and_return(creds) + expect(creds).to receive(:metrics_source=).with(:new) client = ApiHelper.sample_rest_xml::Client.new( profile: 'sso_creds_mixed_legacy', token_provider: nil, @@ -250,8 +250,8 @@ module Aws sso_account_id: 'SSO_ACCOUNT_ID', sso_role_name: 'SSO_ROLE_NAME', sso_session: 'sso test session', - metrics_source: :new ).and_return(creds) + expect(creds).to receive(:metrics_source=).with(:new) client = ApiHelper.sample_rest_xml::Client.new( profile: 'sso_creds_session_with_quotes', token_provider: nil @@ -549,8 +549,8 @@ module Aws sso_account_id: 'SSO_ACCOUNT_ID', sso_role_name: 'SSO_ROLE_NAME', sso_session: 'sso-test-session', - metrics_source: :new ).and_return(creds) + expect(creds).to receive(:metrics_source=).with(:new) expect(creds).to receive(:metrics_source).and_return(:new) allow(SSOTokenProvider).to receive(:new) @@ -582,8 +582,8 @@ module Aws sso_account_id: 'SSO_ACCOUNT_ID', sso_role_name: 'SSO_ROLE_NAME', sso_session: 'sso-test-session', - metrics_source: :new ).and_return(creds) + expect(creds).to receive(:metrics_source=).with(:new) expect(creds).to receive(:metrics_source).and_return(:new) allow(SSOTokenProvider).to receive(:new) @@ -616,8 +616,8 @@ module Aws sso_account_id: 'SSO_ACCOUNT_ID', sso_role_name: 'SSO_ROLE_NAME', sso_session: nil, - metrics_source: :legacy ).and_return(creds) + expect(creds).to receive(:metrics_source=).with(:legacy) expect(creds).to receive(:metrics_source).and_return(:legacy) allow(SSOTokenProvider).to receive(:new) @@ -649,8 +649,8 @@ module Aws sso_account_id: 'SSO_ACCOUNT_ID', sso_role_name: 'SSO_ROLE_NAME', sso_session: nil, - metrics_source: :legacy ).and_return(creds) + expect(creds).to receive(:metrics_source=).with(:legacy) expect(creds).to receive(:metrics_source).and_return(:legacy) allow(SSOTokenProvider).to receive(:new) From abf7e56af72337dd6816e8e2cdd6c29827db0669 Mon Sep 17 00:00:00 2001 From: Richard Wang Date: Tue, 8 Apr 2025 14:16:11 -0700 Subject: [PATCH 50/59] Add sso stub --- .../lib/aws-sdk-core/shared_config.rb | 2 +- .../aws/credential_resolution_chain_spec.rb | 70 ++++++++++++++++++- 2 files changed, 69 insertions(+), 3 deletions(-) diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/shared_config.rb b/gems/aws-sdk-core/lib/aws-sdk-core/shared_config.rb index 61a6bc7c064..10426294edf 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/shared_config.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/shared_config.rb @@ -470,7 +470,7 @@ def credentials_from_profile(prof_config) account_id: prof_config['aws_account_id'] ) creds.metrics_source = :profile - creds if creds.set? + creds if creds.set? end def load_credentials_file diff --git a/gems/aws-sdk-core/spec/aws/credential_resolution_chain_spec.rb b/gems/aws-sdk-core/spec/aws/credential_resolution_chain_spec.rb index 3c451704912..9beb97ff186 100644 --- a/gems/aws-sdk-core/spec/aws/credential_resolution_chain_spec.rb +++ b/gems/aws-sdk-core/spec/aws/credential_resolution_chain_spec.rb @@ -202,6 +202,20 @@ module Aws ).to eq('SSO_AKID') end + it 'emits correct UserAgent metrics during SSO call for SSO' do + sso_stub + expect_any_instance_of(SSO::Client).to receive(:get_role_credentials).and_wrap_original do |m, *args| + resp = m.call(*args) + metrics = metrics_from_user_agent_header(resp.context.http_request.headers['User-Agent']) + expect(metrics).to include('r') + resp + end + client = ApiHelper.sample_rest_xml::Client.new( + profile: 'sso_creds', + token_provider: nil + ) + end + it 'loads SSO credentials from a legacy profile' do creds = double('creds', set?: true, credentials: double(access_key_id: 'SSO_AKID')) allow(creds).to receive(:metrics).and_return(%w[CREDENTIALS_PROFILE_SSO_LEGACY CREDENTIALS_SSO_LEGACY]) @@ -221,6 +235,19 @@ module Aws ).to eq('SSO_AKID') end + it 'emits correct UserAgent metrics during SSO call for legacy SSO' do + legacy_sso_stub + expect_any_instance_of(SSO::Client).to receive(:get_role_credentials).and_wrap_original do |m, *args| + resp = m.call(*args) + metrics = metrics_from_user_agent_header(resp.context.http_request.headers['User-Agent']) + expect(metrics).to include('t') + resp + end + client = ApiHelper.sample_rest_xml::Client.new( + profile: 'sso_creds_legacy' + ) + end + it 'loads SSO credentials from a mixed legacy profile when values match' do creds = double('creds', set?: true, credentials: double(access_key_id: 'SSO_AKID')) allow(creds).to receive(:metrics).and_return(%w[CREDENTIALS_PROFILE_SSO CREDENTIALS_SSO]) @@ -396,7 +423,7 @@ module Aws "Token" : "session-token-md", "Expiration" : "#{(Time.now.utc + 3600).strftime('%Y-%m-%dT%H:%M:%SZ')}" } - JSON + JSON client = ApiHelper.sample_rest_xml::Client.new( profile: 'nonexistant', region: 'us-east-1' ) @@ -1120,7 +1147,7 @@ module Aws "Token" : "session-token-md", "Expiration" : "#{(Time.now.utc + 3600).strftime('%Y-%m-%dT%H:%M:%SZ')}" } - JSON + JSON client = ApiHelper.sample_rest_xml::Client.new( profile: 'nonexistant', region: 'us-east-1' ) @@ -1183,6 +1210,45 @@ def assume_role_web_identity_stub(role_arn, access_key, secret_key, token) RESP end + def sso_stub + token = double('token') + allow(token).to receive(:token).and_return('token') + token_provider = double('token_provider', token: token) + allow(Aws::SSOTokenProvider).to receive(:new).and_return(token_provider) + allow(token_provider).to receive(:set?).and_return(true) + stub_request(:get, 'https://portal.sso.us-east-1.amazonaws.com/federation/credentials?account_id=SSO_ACCOUNT_ID&role_name=SSO_ROLE_NAME') + .to_return(body: <<-RESP) + { + "roleCredentials": { + "accessKeyId": "SSO_AKID", + "secretAccessKey": "secret_key", + "sessionToken": "token", + "expiration": #{(Time.now + 3600).to_i} + } + } + RESP + end + + def mock_sso_cached_token + cached_token = { + 'accessToken' => 'legacy_token', + 'expiresAt' => Time.now + 3600 + } + start_url_sha1 = OpenSSL::Digest::SHA1.hexdigest('START_URL'.encode('utf-8')) + allow(Dir).to receive(:home).and_return('HOME') + path = File.join(Dir.home, '.aws', 'sso', 'cache', "#{start_url_sha1}.json") + + allow(File).to receive(:read).and_call_original + allow(File).to receive(:read).with(path).and_return( + JSON.dump(cached_token) + ) + end + + def legacy_sso_stub + mock_sso_cached_token + sso_stub + end + def stub_token_file(token) allow(File).to receive(:exist?).with('my-token.jwt').and_return(true) allow(File).to receive(:read).and_call_original From 734b436a120fea38c6fb42d9fd54deff1c210a5f Mon Sep 17 00:00:00 2001 From: Richard Wang Date: Wed, 9 Apr 2025 13:24:10 -0700 Subject: [PATCH 51/59] Update based on PR comments --- .../aws-sdk-core/assume_role_credentials.rb | 33 +-- .../assume_role_web_identity_credentials.rb | 14 +- .../lib/aws-sdk-core/credential_provider.rb | 5 +- .../aws-sdk-core/credential_provider_chain.rb | 18 +- .../lib/aws-sdk-core/credentials.rb | 27 +- .../lib/aws-sdk-core/ecs_credentials.rb | 12 +- .../instance_profile_credentials.rb | 12 +- .../plugins/client_metrics_plugin.rb | 1 - .../lib/aws-sdk-core/process_credentials.rb | 14 +- .../lib/aws-sdk-core/shared_config.rb | 42 ++-- .../lib/aws-sdk-core/shared_credentials.rb | 5 +- .../lib/aws-sdk-core/sso_credentials.rb | 19 +- .../spec/aws/assume_role_credentials_spec.rb | 85 ------- ...sume_role_web_identity_credentials_spec.rb | 37 --- .../aws/credential_provider_chain_spec.rb | 2 - .../aws/credential_resolution_chain_spec.rb | 238 ++++++++++++------ .../aws-sdk-core/spec/aws/credentials_spec.rb | 29 --- .../spec/aws/ecs_credentials_spec.rb | 11 - .../aws/instance_profile_credentials_spec.rb | 11 - .../spec/aws/plugins/client_metrics_spec.rb | 2 - .../spec/aws/plugins/sign_spec.rb | 9 +- .../spec/aws/process_credentials_spec.rb | 13 - .../spec/aws/shared_credentials_spec.rb | 6 - .../spec/aws/sso_credentials_spec.rb | 40 --- 24 files changed, 202 insertions(+), 483 deletions(-) diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_credentials.rb b/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_credentials.rb index 25a677cc0af..bc53b3d329e 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_credentials.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_credentials.rb @@ -50,7 +50,7 @@ def initialize(options = {}) end @client = client_opts[:client] || STS::Client.new(client_opts) @async_refresh = true - @metrics_source = :code + @metrics = ['CREDENTIALS_STS_ASSUME_ROLE'] super end @@ -60,37 +60,6 @@ def initialize(options = {}) # @return [Hash] attr_reader :assume_role_params - # @return [Boolean] Returns `true` if instance is created - # during source profile resolution for AssumeRoleCredentials. - # Used for tracking credentials related UserAgent metrics. - attr_accessor :resolving - - def metrics - return [] if @resolving - - source_profile = %w[CREDENTIALS_PROFILE_SOURCE_PROFILE CREDENTIALS_STS_ASSUME_ROLE] - credential_source = %w[CREDENTIALS_PROFILE_NAMED_PROVIDER CREDENTIALS_STS_ASSUME_ROLE] - - case @metrics_source - when :code - ['CREDENTIALS_STS_ASSUME_ROLE'] - when :static - insert_metric(source_profile, 'CREDENTIALS_PROFILE') - when :web_ID - insert_metric(source_profile, %w[CREDENTIALS_PROFILE_STS_WEB_ID_TOKEN CREDENTIALS_STS_ASSUME_ROLE_WEB_ID]) - when :process - insert_metric(source_profile, %w[CREDENTIALS_PROFILE_PROCESS CREDENTIALS_PROCESS]) - when :new - insert_metric(source_profile, %w[CREDENTIALS_PROFILE_SSO CREDENTIALS_SSO]) - when :legacy - insert_metric(source_profile, %w[CREDENTIALS_PROFILE_SSO_LEGACY CREDENTIALS_SSO_LEGACY]) - when :instance - insert_metric(credential_source, 'CREDENTIALS_IMDS') - when :ecs - insert_metric(credential_source, 'CREDENTIALS_HTTP') - end - end - private def refresh diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_web_identity_credentials.rb b/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_web_identity_credentials.rb index 8792f5d80fe..bcf0554ba17 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_web_identity_credentials.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_web_identity_credentials.rb @@ -61,25 +61,13 @@ def initialize(options = {}) @assume_role_web_identity_params[:role_session_name] = _session_name end @client = client_opts[:client] || STS::Client.new(client_opts.merge(credentials: nil)) - @metrics_source = :code + @metrics = ['CREDENTIALS_STS_ASSUME_ROLE_WEB_ID'] super end # @return [STS::Client] attr_reader :client - def metrics - base = ['CREDENTIALS_STS_ASSUME_ROLE_WEB_ID'] - case @metrics_source - when :code - base - when :profile - base.unshift('CREDENTIALS_PROFILE_STS_WEB_ID_TOKEN') - when :env - base.unshift('CREDENTIALS_ENV_VARS_STS_WEB_ID_TOKEN') - end - end - private def refresh diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/credential_provider.rb b/gems/aws-sdk-core/lib/aws-sdk-core/credential_provider.rb index c39ed0e23c3..ccf066b8b85 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/credential_provider.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/credential_provider.rb @@ -10,9 +10,8 @@ module CredentialProvider attr_reader :expiration # @api private - # @return [String] Returns the credentials source. Used for - # tracking credentials related UserAgent metrics. - attr_accessor :metrics_source + # Returns UserAgent metrics for credentials. + attr_accessor :metrics # @return [Boolean] def set? diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/credential_provider_chain.rb b/gems/aws-sdk-core/lib/aws-sdk-core/credential_provider_chain.rb index 117e37daa59..f90b04ae016 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/credential_provider_chain.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/credential_provider_chain.rb @@ -48,7 +48,7 @@ def static_credentials(options) options[:config].session_token, account_id: options[:config].account_id ) - creds.metrics_source = :profile + creds.metrics = ['CREDENTIALS_PROFILE'] creds end end @@ -78,7 +78,9 @@ def static_profile_assume_role_credentials(options) def static_profile_credentials(options) if options[:config] && options[:config].profile - SharedCredentials.new(profile_name: options[:config].profile) + creds = SharedCredentials.new(profile_name: options[:config].profile) + creds.metrics = ['CREDENTIALS_PROFILE'] + creds end rescue Errors::NoSuchProfileError nil @@ -89,7 +91,7 @@ def static_profile_process_credentials(options) process_provider = Aws.shared_config.credential_process(profile: options[:config].profile) if process_provider creds = ProcessCredentials.new([process_provider]) - creds.metrics_source = :profile + creds.metrics << 'CREDENTIALS_PROFILE_PROCESS' creds end end @@ -109,7 +111,7 @@ def env_credentials(_options) envar(token), account_id: envar(account_id) ) - creds.metrics_source = :env + creds.metrics = ['CREDENTIALS_ENV_VARS'] creds end @@ -126,7 +128,9 @@ def determine_profile_name(options) def shared_credentials(options) profile_name = determine_profile_name(options) - SharedCredentials.new(profile_name: profile_name) + creds = SharedCredentials.new(profile_name: profile_name) + creds.metrics = ['CREDENTIALS_PROFILE'] + creds rescue Errors::NoSuchProfileError nil end @@ -137,7 +141,7 @@ def process_credentials(options) process_provider = Aws.shared_config.credential_process(profile: profile_name) if process_provider creds = ProcessCredentials.new([process_provider]) - creds.metrics_source = :profile + creds.metrics << 'CREDENTIALS_PROFILE_PROCESS' creds end end @@ -171,7 +175,7 @@ def assume_role_web_identity_credentials(options) cfg[:region] = region if region Aws::Plugins::UserAgent.metric('CREDENTIALS_ENV_VARS_STS_WEB_ID_TOKEN') do creds = AssumeRoleWebIdentityCredentials.new(cfg) - creds.metrics_source = :env + creds.metrics << 'CREDENTIALS_ENV_VARS_STS_WEB_ID_TOKEN' creds end elsif Aws.shared_config.config_enabled? diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/credentials.rb b/gems/aws-sdk-core/lib/aws-sdk-core/credentials.rb index 293ca07054b..865e22800ed 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/credentials.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/credentials.rb @@ -14,7 +14,7 @@ def initialize(access_key_id, secret_access_key, session_token = nil, @secret_access_key = secret_access_key @session_token = session_token @account_id = kwargs[:account_id] - @metrics_source = :code + @metrics = ['CREDENTIALS_CODE'] end # @return [String] @@ -30,15 +30,9 @@ def initialize(access_key_id, secret_access_key, session_token = nil, attr_reader :account_id # @api private - # @return [String] Returns the credentials source. Used for - # tracking credentials related UserAgent metrics. - attr_accessor :metrics_source - - # @api private - # @return [Boolean] Returns `true` if instance is created - # during source profile resolution for AssumeRoleCredentials. - # Used for tracking credentials related UserAgent metrics. - attr_accessor :resolving + # Returns the credentials source. Used for tracking credentials + # related UserAgent metrics. + attr_accessor :metrics # @return [Credentials] def credentials @@ -60,18 +54,5 @@ def inspect "#<#{self.class.name} access_key_id=#{access_key_id.inspect}>" end - def metrics - return [] if @resolving - - case @metrics_source - when :code - ['CREDENTIALS_CODE'] - when :profile - ['CREDENTIALS_PROFILE'] - when :env - ['CREDENTIALS_ENV_VARS'] - end - end - end end diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/ecs_credentials.rb b/gems/aws-sdk-core/lib/aws-sdk-core/ecs_credentials.rb index 5a0ffa8754b..97ff646ba7b 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/ecs_credentials.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/ecs_credentials.rb @@ -77,6 +77,7 @@ def initialize(options = {}) @http_debug_output = options[:http_debug_output] @backoff = backoff(options[:backoff]) @async_refresh = false + @metrics = ['CREDENTIALS_HTTP'] super end @@ -84,17 +85,6 @@ def initialize(options = {}) # fetch credentials from the instance metadata service. Defaults to 0. attr_reader :retries - # @return [Boolean] Returns `true` if instance is created - # during source profile resolution for AssumeRoleCredentials. - # Used for tracking credentials related UserAgent metrics. - attr_accessor :resolving - - def metrics - return [] if @resolving - - ['CREDENTIALS_HTTP'] - end - private def initialize_uri(options, credential_path, endpoint) diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/instance_profile_credentials.rb b/gems/aws-sdk-core/lib/aws-sdk-core/instance_profile_credentials.rb index 7566304f0e0..be47a8f87e6 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/instance_profile_credentials.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/instance_profile_credentials.rb @@ -90,6 +90,7 @@ def initialize(options = {}) @token = nil @no_refresh_until = nil @async_refresh = false + @metrics = ['CREDENTIALS_IMDS'] super end @@ -98,17 +99,6 @@ def initialize(options = {}) # the default credential chain ({Aws::CredentialProviderChain}). attr_reader :retries - # @return [Boolean] Returns `true` if instance is created - # during source profile resolution for AssumeRoleCredentials. - # Used for tracking credentials related UserAgent metrics. - attr_accessor :resolving - - def metrics - return [] if @resolving - - ['CREDENTIALS_IMDS'] - end - private def resolve_endpoint_mode(options) diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/plugins/client_metrics_plugin.rb b/gems/aws-sdk-core/lib/aws-sdk-core/plugins/client_metrics_plugin.rb index 2507075d270..b11230ddd00 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/plugins/client_metrics_plugin.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/plugins/client_metrics_plugin.rb @@ -180,7 +180,6 @@ def call(context) complete_opts = { latency: end_time - start_time, attempt_count: context.retries + 1, - # user_agent: context.http_request.headers["user-agent"], final_error_retryable: final_error_retryable, final_http_status_code: context.http_response.status_code, final_aws_exception: final_aws_exception, diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/process_credentials.rb b/gems/aws-sdk-core/lib/aws-sdk-core/process_credentials.rb index 2ddb3d209fb..9c60aab0a4c 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/process_credentials.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/process_credentials.rb @@ -36,22 +36,10 @@ def initialize(process) @process = process @credentials = credentials_from_process @async_refresh = false - @metrics_source = :code - + @metrics = ['CREDENTIALS_PROCESS'] super end - def metrics - base = ['CREDENTIALS_PROCESS'] - - case @metrics_source - when :code - base - when :profile - base.unshift('CREDENTIALS_PROFILE_PROCESS') - end - end - private def credentials_from_process diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/shared_config.rb b/gems/aws-sdk-core/lib/aws-sdk-core/shared_config.rb index 10426294edf..98c957d0411 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/shared_config.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/shared_config.rb @@ -140,7 +140,7 @@ def assume_role_web_identity_credentials_from_config(opts = {}) cfg[:region] = opts[:region] if opts[:region] with_metrics('CREDENTIALS_PROFILE_STS_WEB_ID_TOKEN') do creds = AssumeRoleWebIdentityCredentials.new(cfg) - creds.metrics_source = :profile + creds.metrics << 'CREDENTIALS_PROFILE_STS_WEB_ID_TOKEN' creds end end @@ -270,26 +270,17 @@ def assume_role_from_profile(cfg, profile, opts, chain_config) opts[:profile] = opts.delete(:source_profile) opts.delete(:visited_profiles) - metrics = provider.metrics + metrics = provider.metrics.dup if provider.is_a? AssumeRoleCredentials opts[:credentials] = provider - metrics.pop + metrics.delete('CREDENTIALS_STS_ASSUME_ROLE') else - metrics.unshift('CREDENTIALS_PROFILE_SOURCE_PROFILE') + metrics << 'CREDENTIALS_PROFILE_SOURCE_PROFILE' end - opts[:credentials].resolving = true + opts[:credentials].metrics = [] with_metrics(metrics) do creds = AssumeRoleCredentials.new(opts) - creds.metrics_source = case provider - when Credentials - :static - when AssumeRoleWebIdentityCredentials - :web_ID - when ProcessCredentials - :process - else - provider.metrics_source - end + creds.metrics.push(*metrics) creds end else @@ -308,17 +299,12 @@ def assume_role_from_profile(cfg, profile, opts, chain_config) opts[:serial_number] ||= prof_cfg['mfa_serial'] opts.delete(:source_profile) # Cleanup - metrics = opts[:credentials].metrics - metrics.unshift('CREDENTIALS_PROFILE_NAMED_PROVIDER') - opts[:credentials].resolving = true + metrics = Marshal.load(Marshal.dump(opts[:credentials].metrics)) + metrics << ('CREDENTIALS_PROFILE_NAMED_PROVIDER') + opts[:credentials].metrics = [] with_metrics(metrics) do creds = AssumeRoleCredentials.new(opts) - creds.metrics_source = case opts[:credentials] - when InstanceProfileCredentials - :instance - when ECSCredentials - :ecs - end + creds.metrics.push(*metrics) creds end else @@ -384,7 +370,7 @@ def assume_role_process_credentials_from_config(profile) end if credential_process creds = ProcessCredentials.new([credential_process]) - creds.metrics_source = :profile + creds.metrics << 'CREDENTIALS_PROFILE_PROCESS' creds end end @@ -437,9 +423,9 @@ def sso_credentials_from_profile(cfg, profile) sso_role_name: prof_config['sso_role_name'], sso_session: prof_config['sso_session'], sso_region: sso_region, - sso_start_url: sso_start_url, + sso_start_url: sso_start_url ) - creds.metrics_source = prof_config['sso_session'] ? :new : :legacy + creds.metrics << metric creds end end @@ -469,7 +455,7 @@ def credentials_from_profile(prof_config) prof_config['aws_session_token'], account_id: prof_config['aws_account_id'] ) - creds.metrics_source = :profile + creds.metrics = ['CREDENTIALS_PROFILE'] creds if creds.set? end diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/shared_credentials.rb b/gems/aws-sdk-core/lib/aws-sdk-core/shared_credentials.rb index c66225655f9..31fb1f7030d 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/shared_credentials.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/shared_credentials.rb @@ -40,6 +40,7 @@ def initialize(options = {}) ) @credentials = config.credentials(profile: @profile_name) end + @metrics = ['CREDENTIALS_CODE'] end # @return [String] @@ -61,10 +62,6 @@ def inspect "#<#{parts.join(' ')}>" end - def metrics - ['CREDENTIALS_PROFILE'] - end - # @deprecated This method is no longer used. # @return [Boolean] Returns `true` if a credential file # exists and has appropriate read permissions at {#path}. diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/sso_credentials.rb b/gems/aws-sdk-core/lib/aws-sdk-core/sso_credentials.rb index 84f28943cc4..59389a4f7e4 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/sso_credentials.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/sso_credentials.rb @@ -91,6 +91,7 @@ def initialize(options = {}) client_opts[:credentials] = nil @client = Aws::SSO::Client.new(client_opts) end + @metrics = ['CREDENTIALS_SSO'] else # legacy behavior missing_keys = LEGACY_REQUIRED_OPTS.select { |k| options[k].nil? } unless missing_keys.empty? @@ -111,32 +112,16 @@ def initialize(options = {}) client_opts[:credentials] = nil @client = options[:client] || Aws::SSO::Client.new(client_opts) + @metrics = ['CREDENTIALS_SSO_LEGACY'] end @async_refresh = true - @metrics_source = :code super end # @return [SSO::Client] attr_reader :client - def metrics - case @metrics_source - when :new - %w[CREDENTIALS_PROFILE_SSO CREDENTIALS_SSO] - when :legacy - %w[CREDENTIALS_PROFILE_SSO_LEGACY CREDENTIALS_SSO_LEGACY] - # TODO: Check if Ruby has "source-less" SSO credentials - when :code - if @legacy - ['CREDENTIALS_SSO_LEGACY'] - else - ['CREDENTIALS_SSO'] - end - end - end - private def read_cached_token diff --git a/gems/aws-sdk-core/spec/aws/assume_role_credentials_spec.rb b/gems/aws-sdk-core/spec/aws/assume_role_credentials_spec.rb index 60a3b0533de..745d098330c 100644 --- a/gems/aws-sdk-core/spec/aws/assume_role_credentials_spec.rb +++ b/gems/aws-sdk-core/spec/aws/assume_role_credentials_spec.rb @@ -173,90 +173,5 @@ module Aws expect(before_refresh_called).to be(true) end - - it 'defaults the source to code' do - c = AssumeRoleCredentials.new( - role_arn: 'arn', - role_session_name: 'session' - ) - expect(c.metrics_source).to eq(:code) - end - - describe '#metrics' do - - let(:creds) do - AssumeRoleCredentials.new( - role_arn: 'arn', - role_session_name: 'session' - ) - end - - let(:resolving_creds) do - c = creds - c.resolving = true - c - end - - context 'from code' do - it 'returns the correct metrics when the source is none' do - c = creds - expect(c.metrics).to eq(['CREDENTIALS_STS_ASSUME_ROLE']) - end - end - - context 'while resolving' do - - it 'returns no metrics' do - c = resolving_creds - c.metrics_source = :static - expect(c.metrics).to eq([]) - end - end - - context 'when resolved' do - - it 'returns the correct metrics when the source is static' do - c = creds - c.metrics_source = :static - expect(c.metrics).to eq(%w[CREDENTIALS_PROFILE_SOURCE_PROFILE CREDENTIALS_PROFILE CREDENTIALS_STS_ASSUME_ROLE]) - end - - it 'returns the correct metrics when the source is webID' do - c = creds - c.metrics_source = :web_ID - expect(c.metrics).to eq(%w[CREDENTIALS_PROFILE_SOURCE_PROFILE CREDENTIALS_PROFILE_STS_WEB_ID_TOKEN CREDENTIALS_STS_ASSUME_ROLE_WEB_ID CREDENTIALS_STS_ASSUME_ROLE]) - end - - it 'returns the correct metrics when the source is process' do - c = creds - c.metrics_source = :process - expect(c.metrics).to eq(%w[CREDENTIALS_PROFILE_SOURCE_PROFILE CREDENTIALS_PROFILE_PROCESS CREDENTIALS_PROCESS CREDENTIALS_STS_ASSUME_ROLE]) - end - - it 'returns the correct metrics when the source is new SSO' do - c = creds - c.metrics_source = :new - expect(c.metrics).to eq(%w[CREDENTIALS_PROFILE_SOURCE_PROFILE CREDENTIALS_PROFILE_SSO CREDENTIALS_SSO CREDENTIALS_STS_ASSUME_ROLE]) - end - - it 'returns the correct metrics when the source is legacy SSO' do - c = creds - c.metrics_source = :legacy - expect(c.metrics).to eq(%w[CREDENTIALS_PROFILE_SOURCE_PROFILE CREDENTIALS_PROFILE_SSO_LEGACY CREDENTIALS_SSO_LEGACY CREDENTIALS_STS_ASSUME_ROLE]) - end - - it 'returns the correct metrics when the source is instance' do - c = creds - c.metrics_source = :instance - expect(c.metrics).to eq(%w[CREDENTIALS_PROFILE_NAMED_PROVIDER CREDENTIALS_IMDS CREDENTIALS_STS_ASSUME_ROLE]) - end - - it 'returns the correct metrics when the source is ecs' do - c = creds - c.metrics_source = :ecs - expect(c.metrics).to eq(%w[CREDENTIALS_PROFILE_NAMED_PROVIDER CREDENTIALS_HTTP CREDENTIALS_STS_ASSUME_ROLE]) - end - end - end end end diff --git a/gems/aws-sdk-core/spec/aws/assume_role_web_identity_credentials_spec.rb b/gems/aws-sdk-core/spec/aws/assume_role_web_identity_credentials_spec.rb index 7f2e714daab..546097f2034 100644 --- a/gems/aws-sdk-core/spec/aws/assume_role_web_identity_credentials_spec.rb +++ b/gems/aws-sdk-core/spec/aws/assume_role_web_identity_credentials_spec.rb @@ -213,42 +213,5 @@ module Aws c.credentials c.credentials end - - it 'defaults the source to code' do - c = AssumeRoleWebIdentityCredentials.new( - role_arn: 'arn', - web_identity_token_file: token_file_path, - role_session_name: 'session' - ) - expect(c.metrics_source).to eq(:code) - end - - describe '#metrics' do - - let(:creds) do - AssumeRoleWebIdentityCredentials.new( - role_arn: 'arn', - web_identity_token_file: token_file_path, - role_session_name: 'session' - ) - end - - it 'returns the correct metrics when the source is none' do - c = creds - expect(c.metrics).to eq(['CREDENTIALS_STS_ASSUME_ROLE_WEB_ID']) - end - - it 'returns the correct metrics when the source is profile' do - c = creds - c.metrics_source = :profile - expect(c.metrics).to eq(%w[CREDENTIALS_PROFILE_STS_WEB_ID_TOKEN CREDENTIALS_STS_ASSUME_ROLE_WEB_ID]) - end - - it 'returns the correct metrics when the source is env' do - c = creds - c.metrics_source = :env - expect(c.metrics).to eq(%w[CREDENTIALS_ENV_VARS_STS_WEB_ID_TOKEN CREDENTIALS_STS_ASSUME_ROLE_WEB_ID]) - end - end end end diff --git a/gems/aws-sdk-core/spec/aws/credential_provider_chain_spec.rb b/gems/aws-sdk-core/spec/aws/credential_provider_chain_spec.rb index 408ce8a31ad..80d77139a61 100644 --- a/gems/aws-sdk-core/spec/aws/credential_provider_chain_spec.rb +++ b/gems/aws-sdk-core/spec/aws/credential_provider_chain_spec.rb @@ -136,7 +136,6 @@ def validate_metrics(expected_metrics) it 'hydrates credentials from ECS when AWS_CONTAINER_CREDENTIALS_RELATIVE_URI is set' do ENV['AWS_CONTAINER_CREDENTIALS_RELATIVE_URI'] = 'test_uri' mock_ecs_creds = double('ECSCredentials') - allow(mock_ecs_creds).to receive(:source=).with(:set) allow(mock_ecs_creds).to receive(:metrics).and_return(['CREDENTIALS_HTTP']) expect(ECSCredentials).to receive(:new).and_return(mock_ecs_creds) expect(mock_ecs_creds).to receive(:set?).and_return(true) @@ -147,7 +146,6 @@ def validate_metrics(expected_metrics) it 'hydrates credentials from ECS when AWS_CONTAINER_CREDENTIALS_FULL_URI is set' do ENV['AWS_CONTAINER_CREDENTIALS_FULL_URI'] = 'test_uri' mock_ecs_creds = double('ECSCredentials') - allow(mock_ecs_creds).to receive(:source=).with(:set) allow(mock_ecs_creds).to receive(:metrics).and_return(['CREDENTIALS_HTTP']) expect(ECSCredentials).to receive(:new).and_return(mock_ecs_creds) expect(mock_ecs_creds).to receive(:set?).and_return(true) diff --git a/gems/aws-sdk-core/spec/aws/credential_resolution_chain_spec.rb b/gems/aws-sdk-core/spec/aws/credential_resolution_chain_spec.rb index 9beb97ff186..0011d7458ec 100644 --- a/gems/aws-sdk-core/spec/aws/credential_resolution_chain_spec.rb +++ b/gems/aws-sdk-core/spec/aws/credential_resolution_chain_spec.rb @@ -24,6 +24,28 @@ module Aws let(:mock_instance_creds) { double('InstanceProfileCredentials', set?: false) } + let(:metrics_hash) { + { + 'e': 'CREDENTIALS_CODE', + 'g': 'CREDENTIALS_ENV_VARS', + 'h': 'CREDENTIALS_ENV_VARS_STS_WEB_ID_TOKEN', + 'i': 'CREDENTIALS_STS_ASSUME_ROLE', + 'k': 'CREDENTIALS_STS_ASSUME_ROLE_WEB_ID', + "n": 'CREDENTIALS_PROFILE', + 'o': 'CREDENTIALS_PROFILE_SOURCE_PROFILE', + 'p': 'CREDENTIALS_PROFILE_NAMED_PROVIDER', + 'q': 'CREDENTIALS_PROFILE_STS_WEB_ID_TOKEN', + 'r': 'CREDENTIALS_PROFILE_SSO', + 's': 'CREDENTIALS_SSO', + 't': 'CREDENTIALS_PROFILE_SSO_LEGACY', + 'u': 'CREDENTIALS_SSO_LEGACY', + 'v': 'CREDENTIALS_PROFILE_PROCESS', + 'w': 'CREDENTIALS_PROCESS', + 'z': 'CREDENTIALS_HTTP', + '0': 'CREDENTIALS_IMDS' + } + } + before(:all) do # Ensure the sample_rest_xml is built before any mocks occur ApiHelper.sample_rest_xml @@ -58,7 +80,8 @@ module Aws region: 'us-east-1' ) expect(client.config.credentials.access_key_id).to eq('ACCESS_DIRECT') - expect(client.config.credentials.metrics_source).to eq(:profile) + expected_metrics = metrics_list_from_code(%w[n]) + expect(client.config.credentials.metrics).to contain_exactly(*expected_metrics) end it 'prefers assume role credentials when profile explicitly set over ENV credentials' do @@ -78,7 +101,8 @@ module Aws profile: 'assumerole_sc', region: 'us-east-1' ) expect(client.config.credentials.credentials.access_key_id).to eq('AR_AKID') - expect(client.config.credentials.metrics_source).to eq(:static) + expected_metrics = metrics_list_from_code(%w[o n i]) + expect(client.config.credentials.metrics).to contain_exactly(*expected_metrics) end it 'emits correct UserAgent metrics during STS call for assume role credentials' do @@ -96,8 +120,9 @@ module Aws ) expect_any_instance_of(STS::Client).to receive(:assume_role).and_wrap_original do |m, *args| resp = m.call(*args) - metrics = metrics_from_user_agent_header(resp.context.http_request.headers['User-Agent']) - expect(metrics).to include('o,n') + metrics = metrics_from_user_agent_header(resp) + expected_metrics = %w[o n] + expect(metrics).to include(*expected_metrics) resp end client = ApiHelper.sample_rest_xml::Client.new( @@ -118,7 +143,8 @@ module Aws expect( client.config.credentials.credentials.access_key_id ).to eq('AR_AKID') - expect(client.config.credentials.metrics_source).to eq(:profile) + expected_metrics = metrics_list_from_code(%w[q k]) + expect(client.config.credentials.metrics).to contain_exactly(*expected_metrics) end it 'emits correct UserAgent metrics during STS call for assume role web identity from profile' do @@ -130,8 +156,9 @@ module Aws ) expect_any_instance_of(STS::Client).to receive(:assume_role_with_web_identity).and_wrap_original do |m, *args| resp = m.call(*args) - metrics = metrics_from_user_agent_header(resp.context.http_request.headers['User-Agent']) - expect(metrics).to include('q') + metrics = metrics_from_user_agent_header(resp) + expected_metrics = %w[q] + expect(metrics).to include(*expected_metrics) resp end client = ApiHelper.sample_rest_xml::Client.new( @@ -156,7 +183,8 @@ module Aws ) expect(client.config.credentials.credentials.access_key_id) .to eq('AR_AKID') - expect(client.config.credentials.metrics_source).to eq(:env) + expected_metrics = metrics_list_from_code(%w[h k]) + expect(client.config.credentials.metrics).to contain_exactly(*expected_metrics) end it 'emits correct UserAgent metrics during STS call for assume role web identity from env' do @@ -173,8 +201,9 @@ module Aws ) expect_any_instance_of(STS::Client).to receive(:assume_role_with_web_identity).and_wrap_original do |m, *args| resp = m.call(*args) - metrics = metrics_from_user_agent_header(resp.context.http_request.headers['User-Agent']) - expect(metrics).to include('h') + metrics = metrics_from_user_agent_header(resp) + expected_metrics = %w[h] + expect(metrics).to include(*expected_metrics) resp end client = ApiHelper.sample_rest_xml::Client.new( @@ -183,8 +212,8 @@ module Aws end it 'prefers sso credentials over assume role' do - creds = double('creds', set?: true, credentials: double(access_key_id: 'SSO_AKID')) - allow(creds).to receive(:metrics).and_return(%w[CREDENTIALS_PROFILE_SSO CREDENTIALS_SSO]) + creds = double('creds', set?: true, credentials: double(access_key_id: 'SSO_AKID'), + metrics: %w[CREDENTIALS_SSO]) expect(SSOCredentials).to receive(:new).with( sso_start_url: 'START_URL', sso_region: 'us-east-1', @@ -192,7 +221,6 @@ module Aws sso_role_name: 'SSO_ROLE_NAME', sso_session: 'sso-test-session', ).and_return(creds) - expect(creds).to receive(:metrics_source=).with(:new) client = ApiHelper.sample_rest_xml::Client.new( profile: 'sso_creds', token_provider: nil @@ -200,14 +228,17 @@ module Aws expect( client.config.credentials.credentials.access_key_id ).to eq('SSO_AKID') + expected_metrics = metrics_list_from_code(%w[r s]) + expect(client.config.credentials.metrics).to contain_exactly(*expected_metrics) end it 'emits correct UserAgent metrics during SSO call for SSO' do sso_stub expect_any_instance_of(SSO::Client).to receive(:get_role_credentials).and_wrap_original do |m, *args| resp = m.call(*args) - metrics = metrics_from_user_agent_header(resp.context.http_request.headers['User-Agent']) - expect(metrics).to include('r') + metrics = metrics_from_user_agent_header(resp) + expected_metrics = %w[r] + expect(metrics).to include(*expected_metrics) resp end client = ApiHelper.sample_rest_xml::Client.new( @@ -217,8 +248,8 @@ module Aws end it 'loads SSO credentials from a legacy profile' do - creds = double('creds', set?: true, credentials: double(access_key_id: 'SSO_AKID')) - allow(creds).to receive(:metrics).and_return(%w[CREDENTIALS_PROFILE_SSO_LEGACY CREDENTIALS_SSO_LEGACY]) + creds = double('creds', set?: true, credentials: double(access_key_id: 'SSO_AKID'), + metrics: %w[CREDENTIALS_SSO_LEGACY]) expect(SSOCredentials).to receive(:new).with( sso_start_url: 'START_URL', sso_region: 'us-east-1', @@ -226,21 +257,23 @@ module Aws sso_role_name: 'SSO_ROLE_NAME', sso_session: nil, ).and_return(creds) - expect(creds).to receive(:metrics_source=).with(:legacy) client = ApiHelper.sample_rest_xml::Client.new( profile: 'sso_creds_legacy' ) expect( client.config.credentials.credentials.access_key_id ).to eq('SSO_AKID') + expected_metrics = metrics_list_from_code(%w[t u]) + expect(client.config.credentials.metrics).to contain_exactly(*expected_metrics) end it 'emits correct UserAgent metrics during SSO call for legacy SSO' do legacy_sso_stub expect_any_instance_of(SSO::Client).to receive(:get_role_credentials).and_wrap_original do |m, *args| resp = m.call(*args) - metrics = metrics_from_user_agent_header(resp.context.http_request.headers['User-Agent']) - expect(metrics).to include('t') + metrics = metrics_from_user_agent_header(resp) + expected_metrics = %w[t] + expect(metrics).to include(*expected_metrics) resp end client = ApiHelper.sample_rest_xml::Client.new( @@ -249,8 +282,8 @@ module Aws end it 'loads SSO credentials from a mixed legacy profile when values match' do - creds = double('creds', set?: true, credentials: double(access_key_id: 'SSO_AKID')) - allow(creds).to receive(:metrics).and_return(%w[CREDENTIALS_PROFILE_SSO CREDENTIALS_SSO]) + creds = double('creds', set?: true, credentials: double(access_key_id: 'SSO_AKID'), + metrics: %w[CREDENTIALS_SSO]) expect(SSOCredentials).to receive(:new).with( sso_start_url: 'START_URL', sso_region: 'us-east-1', @@ -258,7 +291,6 @@ module Aws sso_role_name: 'SSO_ROLE_NAME', sso_session: 'sso-test-session', ).and_return(creds) - expect(creds).to receive(:metrics_source=).with(:new) client = ApiHelper.sample_rest_xml::Client.new( profile: 'sso_creds_mixed_legacy', token_provider: nil, @@ -266,11 +298,13 @@ module Aws expect( client.config.credentials.credentials.access_key_id ).to eq('SSO_AKID') + expected_metrics = metrics_list_from_code(%w[r s]) + expect(client.config.credentials.metrics).to contain_exactly(*expected_metrics) end it 'loads SSO credentials from when the session name has quotes' do - creds = double('creds', set?: true, credentials: double(access_key_id: 'SSO_AKID')) - allow(creds).to receive(:metrics).and_return(%w[CREDENTIALS_PROFILE_SSO CREDENTIALS_SSO]) + creds = double('creds', set?: true, credentials: double(access_key_id: 'SSO_AKID'), + metrics: %w[CREDENTIALS_SSO]) expect(SSOCredentials).to receive(:new).with( sso_start_url: 'START_URL', sso_region: 'us-east-1', @@ -278,7 +312,6 @@ module Aws sso_role_name: 'SSO_ROLE_NAME', sso_session: 'sso test session', ).and_return(creds) - expect(creds).to receive(:metrics_source=).with(:new) client = ApiHelper.sample_rest_xml::Client.new( profile: 'sso_creds_session_with_quotes', token_provider: nil @@ -286,6 +319,8 @@ module Aws expect( client.config.credentials.credentials.access_key_id ).to eq('SSO_AKID') + expected_metrics = metrics_list_from_code(%w[r s]) + expect(client.config.credentials.metrics).to contain_exactly(*expected_metrics) end it 'raises when attempting to load an incomplete SSO Profile' do @@ -331,7 +366,8 @@ module Aws expect( client.config.credentials.credentials.access_key_id ).to eq('AR_AKID') - expect(client.config.credentials.metrics_source).to eq(:static) + expected_metrics = metrics_list_from_code(%w[o n i]) + expect(client.config.credentials.metrics).to contain_exactly(*expected_metrics) sts_client = client.config.credentials.client expect( @@ -346,6 +382,8 @@ module Aws expect( client.config.credentials.credentials.access_key_id ).to eq('ACCESS_KEY_CRD') + expected_metrics = metrics_list_from_code(%w[n]) + expect(client.config.credentials.metrics).to contain_exactly(*expected_metrics) end it 'will source static credentials from shared config after shared credentials' do @@ -355,6 +393,8 @@ module Aws expect( client.config.credentials.credentials.access_key_id ).to eq('ACCESS_KEY_SC1') + expected_metrics = metrics_list_from_code(%w[n]) + expect(client.config.credentials.metrics).to contain_exactly(*expected_metrics) end it 'prefers process credentials over metadata credentials' do @@ -364,6 +404,8 @@ module Aws expect( client.config.credentials.credentials.access_key_id ).to eq('AK_PROC1') + expected_metrics = metrics_list_from_code(%w[v w]) + expect(client.config.credentials.metrics).to contain_exactly(*expected_metrics) end it 'prefers direct credentials over process credentials when profile not set' do @@ -378,7 +420,8 @@ module Aws expect( client.config.credentials.credentials.access_key_id ).to eq('AKID_ENV_STUB') - expect(client.config.credentials.metrics_source).to eq(:env) + expected_metrics = metrics_list_from_code(%w[g]) + expect(client.config.credentials.metrics).to contain_exactly(*expected_metrics) end it 'prefers process credentials from direct profile over env' do @@ -393,6 +436,8 @@ module Aws expect( client.config.credentials.credentials.access_key_id ).to eq('AK_PROC1') + expected_metrics = metrics_list_from_code(%w[v w]) + expect(client.config.credentials.metrics).to contain_exactly(*expected_metrics) end it 'attempts to fetch metadata credentials last using IMDS' do @@ -430,6 +475,8 @@ module Aws expect( client.config.credentials.credentials.access_key_id ).to eq('akid-md') + expected_metrics = metrics_list_from_code(%w[0]) + expect(client.config.credentials.metrics).to contain_exactly(*expected_metrics) end it 'attempts to fetch metadata credentials last using ECS' do @@ -452,6 +499,8 @@ module Aws region: 'us-east-1' ) expect(client.config.credentials.credentials.access_key_id).to eq('ACCESS_KEY_ECS') + expected_metrics = metrics_list_from_code(%w[z]) + expect(client.config.credentials.metrics).to contain_exactly(*expected_metrics) end describe 'Assume Role Resolution' do @@ -491,7 +540,8 @@ module Aws expect( client.config.credentials.credentials.access_key_id ).to eq('AR_AKID') - expect(client.config.credentials.metrics_source).to eq(:web_ID) + expected_metrics = metrics_list_from_code(%w[o q k i]) + expect(client.config.credentials.metrics).to contain_exactly(*expected_metrics) sts_client = client.config.credentials.client expect( @@ -515,14 +565,16 @@ module Aws ) expect_any_instance_of(STS::Client).to receive(:assume_role_with_web_identity).and_wrap_original do |m, *args| resp = m.call(*args) - metrics = metrics_from_user_agent_header(resp.context.http_request.headers['User-Agent']) - expect(metrics).to include('o,q') + metrics = metrics_from_user_agent_header(resp) + expected_metrics = %w[o q] + expect(metrics).to include(*expected_metrics) resp end expect_any_instance_of(STS::Client).to receive(:assume_role).and_wrap_original do |m, *args| resp = m.call(*args) - metrics = metrics_from_user_agent_header(resp.context.http_request.headers['User-Agent']) - expect(metrics).to include('o,q,k') + metrics = metrics_from_user_agent_header(resp) + expected_metrics = %w[o q k] + expect(metrics).to include(*expected_metrics) resp end client = ApiHelper.sample_rest_xml::Client.new( @@ -545,7 +597,8 @@ module Aws expect( client.config.credentials.credentials.access_key_id ).to eq('AK_PROC1') - expect(client.config.credentials.metrics_source).to eq(:process) + expected_metrics = metrics_list_from_code(%w[o v w i]) + expect(client.config.credentials.metrics).to contain_exactly(*expected_metrics) end it 'emits correct UserAgent metrics during STS calls for :source_profile from process credentials' do @@ -558,8 +611,9 @@ module Aws ) expect_any_instance_of(STS::Client).to receive(:assume_role).and_wrap_original do |m, *args| resp = m.call(*args) - metrics = metrics_from_user_agent_header(resp.context.http_request.headers['User-Agent']) - expect(metrics).to include('o,v,w') + metrics = metrics_from_user_agent_header(resp) + expected_metrics = %w[o v w] + expect(metrics).to include(*expected_metrics) resp end client = ApiHelper.sample_rest_xml::Client.new( @@ -568,17 +622,15 @@ module Aws end it 'supports :source_profile from sso credentials' do - creds = double('creds', set?: true, credentials: Credentials.new('SSO_AKID', 'sak')) - allow(creds).to receive(:metrics).and_return(%w[CREDENTIALS_PROFILE_SSO CREDENTIALS_SSO]) + creds = double('creds', set?: true, credentials: Credentials.new('SSO_AKID', 'sak'), + metrics: %w[CREDENTIALS_SSO]) expect(SSOCredentials).to receive(:new).with( sso_start_url: 'START_URL', sso_region: 'us-east-1', sso_account_id: 'SSO_ACCOUNT_ID', sso_role_name: 'SSO_ROLE_NAME', - sso_session: 'sso-test-session', + sso_session: 'sso-test-session' ).and_return(creds) - expect(creds).to receive(:metrics_source=).with(:new) - expect(creds).to receive(:metrics_source).and_return(:new) allow(SSOTokenProvider).to receive(:new) .and_return(double('SSOToken', set?: true)) @@ -597,12 +649,13 @@ module Aws expect( client.config.credentials.credentials.access_key_id ).to eq('AR_AKID') - expect(client.config.credentials.metrics_source).to eq(:new) + expected_metrics = metrics_list_from_code(%w[o r s i]) + expect(client.config.credentials.metrics).to contain_exactly(*expected_metrics) end it 'emits correct UserAgent metrics during STS calls for :source_profile from sso credentials' do - creds = double('creds', set?: true, credentials: Credentials.new('SSO_AKID', 'sak')) - allow(creds).to receive(:metrics).and_return(%w[CREDENTIALS_PROFILE_SSO CREDENTIALS_SSO]) + creds = double('creds', set?: true, credentials: Credentials.new('SSO_AKID', 'sak'), + metrics: %w[CREDENTIALS_SSO]) expect(SSOCredentials).to receive(:new).with( sso_start_url: 'START_URL', sso_region: 'us-east-1', @@ -610,8 +663,6 @@ module Aws sso_role_name: 'SSO_ROLE_NAME', sso_session: 'sso-test-session', ).and_return(creds) - expect(creds).to receive(:metrics_source=).with(:new) - expect(creds).to receive(:metrics_source).and_return(:new) allow(SSOTokenProvider).to receive(:new) .and_return(double('SSOToken', set?: true)) @@ -625,8 +676,9 @@ module Aws ) expect_any_instance_of(STS::Client).to receive(:assume_role).and_wrap_original do |m, *args| resp = m.call(*args) - metrics = metrics_from_user_agent_header(resp.context.http_request.headers['User-Agent']) - expect(metrics).to include('o,r,s') + metrics = metrics_from_user_agent_header(resp) + expected_metrics = %w[o r s] + expect(metrics).to include(*expected_metrics) resp end client = ApiHelper.sample_rest_xml::Client.new( @@ -635,8 +687,8 @@ module Aws end it 'supports :source_profile from legacy sso credentials' do - creds = double('creds', set?: true, credentials: Credentials.new('SSO_AKID', 'sak')) - allow(creds).to receive(:metrics).and_return(%w[CREDENTIALS_PROFILE_SSO_LEGACY CREDENTIALS_SSO_LEGACY]) + creds = double('creds', set?: true, credentials: Credentials.new('SSO_AKID', 'sak'), + metrics: %w[CREDENTIALS_SSO_LEGACY]) expect(SSOCredentials).to receive(:new).with( sso_start_url: 'START_URL', sso_region: 'us-east-1', @@ -644,8 +696,6 @@ module Aws sso_role_name: 'SSO_ROLE_NAME', sso_session: nil, ).and_return(creds) - expect(creds).to receive(:metrics_source=).with(:legacy) - expect(creds).to receive(:metrics_source).and_return(:legacy) allow(SSOTokenProvider).to receive(:new) .and_return(double('SSOToken', set?: true)) @@ -664,12 +714,13 @@ module Aws expect( client.config.credentials.credentials.access_key_id ).to eq('AR_AKID') - expect(client.config.credentials.metrics_source).to eq(:legacy) + expected_metrics = metrics_list_from_code(%w[o t u i]) + expect(client.config.credentials.metrics).to contain_exactly(*expected_metrics) end it 'emits correct UserAgent metrics during STS calls for :source_profile from legacy sso credentials' do - creds = double('creds', set?: true, credentials: Credentials.new('SSO_AKID', 'sak')) - allow(creds).to receive(:metrics).and_return(%w[CREDENTIALS_PROFILE_SSO_LEGACY CREDENTIALS_SSO_LEGACY]) + creds = double('creds', set?: true, credentials: Credentials.new('SSO_AKID', 'sak'), + metrics: %w[CREDENTIALS_SSO_LEGACY]) expect(SSOCredentials).to receive(:new).with( sso_start_url: 'START_URL', sso_region: 'us-east-1', @@ -677,8 +728,6 @@ module Aws sso_role_name: 'SSO_ROLE_NAME', sso_session: nil, ).and_return(creds) - expect(creds).to receive(:metrics_source=).with(:legacy) - expect(creds).to receive(:metrics_source).and_return(:legacy) allow(SSOTokenProvider).to receive(:new) .and_return(double('SSOToken', set?: true)) @@ -692,8 +741,9 @@ module Aws ) expect_any_instance_of(STS::Client).to receive(:assume_role).and_wrap_original do |m, *args| resp = m.call(*args) - metrics = metrics_from_user_agent_header(resp.context.http_request.headers['User-Agent']) - expect(metrics).to include('o,t,u') + metrics = metrics_from_user_agent_header(resp) + expected_metrics = %w[o t u] + expect(metrics).to include(*expected_metrics) resp end client = ApiHelper.sample_rest_xml::Client.new( @@ -724,7 +774,8 @@ module Aws expect( client.config.credentials.credentials.access_key_id ).to eq('AK_2') - expect(client.config.credentials.metrics_source).to eq(:static) + expected_metrics = metrics_list_from_code(%w[o n i]) + expect(client.config.credentials.metrics).to contain_exactly(*expected_metrics) end it 'emits correct UserAgent metrics during STS calls for assume role chaining' do @@ -745,8 +796,9 @@ module Aws ) allow_any_instance_of(STS::Client).to receive(:assume_role).and_wrap_original do |m, *args| resp = m.call(*args) - metrics = metrics_from_user_agent_header(resp.context.http_request.headers['User-Agent']) - expect(metrics).to include('o,n') + metrics = metrics_from_user_agent_header(resp) + expected_metrics = %w[o n] + expect(metrics).to include(*expected_metrics) resp end client = ApiHelper.sample_rest_xml::Client.new( @@ -769,7 +821,8 @@ module Aws expect( client.config.credentials.credentials.access_key_id ).to eq('AK_2') - expect(client.config.credentials.metrics_source).to eq(:static) + expected_metrics = metrics_list_from_code(%w[o n i]) + expect(client.config.credentials.metrics).to contain_exactly(*expected_metrics) end it 'uses static credentials when the profile self references' do @@ -787,7 +840,8 @@ module Aws expect( client.config.credentials.credentials.access_key_id ).to eq('AK_2') - expect(client.config.credentials.metrics_source).to eq(:static) + expected_metrics = metrics_list_from_code(%w[o n i]) + expect(client.config.credentials.metrics).to contain_exactly(*expected_metrics) end it 'raises if there is a loop in chained profiles' do @@ -829,7 +883,8 @@ module Aws expect( client.config.credentials.credentials.access_key_id ).to eq('AR_AKID') - expect(client.config.credentials.metrics_source).to eq(:static) + expected_metrics = metrics_list_from_code(%w[o n i]) + expect(client.config.credentials.metrics).to contain_exactly(*expected_metrics) end it 'will then try to assume a role from shared config' do @@ -846,7 +901,8 @@ module Aws expect( client.config.credentials.credentials.access_key_id ).to eq('AR_AKID') - expect(client.config.credentials.metrics_source).to eq(:static) + expected_metrics = metrics_list_from_code(%w[o n i]) + expect(client.config.credentials.metrics).to contain_exactly(*expected_metrics) end it 'assumes a role from config using source in shared credentials' do @@ -863,7 +919,8 @@ module Aws expect( client.config.credentials.credentials.access_key_id ).to eq('AR_AKID') - expect(client.config.credentials.metrics_source).to eq(:static) + expected_metrics = metrics_list_from_code(%w[o n i]) + expect(client.config.credentials.metrics).to contain_exactly(*expected_metrics) end it 'allows region to be resolved when unspecified' do @@ -884,7 +941,8 @@ module Aws expect( credentials.credentials.access_key_id ).to eq('AR_AKID') - expect(credentials.metrics_source).to eq(:static) + expected_metrics = metrics_list_from_code(%w[o n i]) + expect(credentials.metrics).to contain_exactly(*expected_metrics) end end @@ -929,7 +987,8 @@ module Aws expect( client.config.credentials.credentials.access_key_id ).to eq('AR_AKID') - expect(client.config.credentials.metrics_source).to eq(:instance) + expected_metrics = metrics_list_from_code(%w[p 0 i]) + expect(client.config.credentials.metrics).to contain_exactly(*expected_metrics) end it 'emits correct UserAgent metrics during STS calls for EC2 Instance Metadata as a source' do @@ -968,8 +1027,9 @@ module Aws .to_return(status: 200, body: resp) expect_any_instance_of(STS::Client).to receive(:assume_role).and_wrap_original do |m, *args| resp = m.call(*args) - metrics = metrics_from_user_agent_header(resp.context.http_request.headers['User-Agent']) - expect(metrics).to include('p,0') + metrics = metrics_from_user_agent_header(resp) + expected_metrics = %w[p 0] + expect(metrics).to include(*expected_metrics) resp end client = ApiHelper.sample_rest_xml::Client.new( @@ -1008,7 +1068,8 @@ module Aws expect( client.config.credentials.credentials.access_key_id ).to eq('AR_AKID') - expect(client.config.credentials.metrics_source).to eq(:ecs) + expected_metrics = metrics_list_from_code(%w[p z i]) + expect(client.config.credentials.metrics).to contain_exactly(*expected_metrics) end it 'emits correct UserAgent metrics during STS calls for ECS Credentials as a source' do @@ -1036,8 +1097,9 @@ module Aws ) expect_any_instance_of(STS::Client).to receive(:assume_role).and_wrap_original do |m, *args| resp = m.call(*args) - metrics = metrics_from_user_agent_header(resp.context.http_request.headers['User-Agent']) - expect(metrics).to include('p,z') + metrics = metrics_from_user_agent_header(resp) + expected_metrics = %w[p z] + expect(metrics).to include(*expected_metrics) resp end client = ApiHelper.sample_rest_xml::Client.new( @@ -1073,7 +1135,8 @@ module Aws expect( client.config.credentials.credentials.access_key_id ).to eq('ACCESS_DIRECT') - expect(client.config.credentials.metrics_source).to eq(:profile) + expected_metrics = metrics_list_from_code(%w[n]) + expect(client.config.credentials.metrics).to contain_exactly(*expected_metrics) end it 'prefers ENV credentials over shared config when profile not set' do @@ -1088,7 +1151,8 @@ module Aws expect( client.config.credentials.credentials.access_key_id ).to eq('AKID_ENV_STUB') - expect(client.config.credentials.metrics_source).to eq(:env) + expected_metrics = metrics_list_from_code(%w[g]) + expect(client.config.credentials.metrics).to contain_exactly(*expected_metrics) end it 'prefers config from profile over ENV credentials when profile is set on client' do @@ -1103,6 +1167,8 @@ module Aws expect( client.config.credentials.credentials.access_key_id ).to eq('ACCESS_KEY_1') + expected_metrics = metrics_list_from_code(%w[n]) + expect(client.config.credentials.metrics).to contain_exactly(*expected_metrics) end it 'will not load credentials from shared config' do @@ -1154,6 +1220,8 @@ module Aws expect( client.config.credentials.credentials.access_key_id ).to eq('akid-md') + expected_metrics = metrics_list_from_code(%w[0]) + expect(client.config.credentials.metrics).to contain_exactly(*expected_metrics) end end @@ -1255,8 +1323,22 @@ def stub_token_file(token) allow(File).to receive(:read).with('my-token.jwt').and_return(token) end - def metrics_from_user_agent_header(header) - header[(header.index('m/') + 2)..-1] + def metrics_from_user_agent_header(resp) + header = resp.context.http_request.headers['User-Agent'] + header.match(/ m\/([A-Za-z0-9+-,]+)/)[1].split(',') + end + + def metrics_list_from_code(codes) + codes.map { |code| metrics_hash[code.to_sym] } + end + + def validate_metrics(actual, expected) + expected = metrics_list_from_code(expected) + (actual - expected).empty? && (expected - actual).empty? + end + + def validate_header_metrics(actual, expected) + (expected - actual).empty? end end end diff --git a/gems/aws-sdk-core/spec/aws/credentials_spec.rb b/gems/aws-sdk-core/spec/aws/credentials_spec.rb index 82867bbd90d..3c65274667c 100644 --- a/gems/aws-sdk-core/spec/aws/credentials_spec.rb +++ b/gems/aws-sdk-core/spec/aws/credentials_spec.rb @@ -37,10 +37,6 @@ module Aws expect(Credentials.new('akid', 'secret').account_id).to be(nil) end - it 'defaults the source to code' do - expect(Credentials.new('akid', 'secret').metrics_source).to eq(:code) - end - describe '#set?' do it 'returns true when the key and secret are both non nil values' do @@ -64,30 +60,5 @@ module Aws end end - - describe '#metrics' do - - it 'returns the correct metrics when the source is none' do - expect(Credentials.new('akid', 'secret').metrics).to eq(['CREDENTIALS_CODE']) - end - - it 'returns the correct metrics when the source is profile' do - creds = Credentials.new('akid', 'secret') - creds.metrics_source = :profile - expect(creds.metrics).to eq(['CREDENTIALS_PROFILE']) - end - - it 'returns the correct metrics when the source is env' do - creds = Credentials.new('akid', 'secret') - creds.metrics_source = :env - expect(creds.metrics).to eq(['CREDENTIALS_ENV_VARS']) - end - - it 'returns no metrics when resolving' do - creds = Credentials.new('akid', 'secret') - creds.resolving = true - expect(creds.metrics).to eq([]) - end - end end end diff --git a/gems/aws-sdk-core/spec/aws/ecs_credentials_spec.rb b/gems/aws-sdk-core/spec/aws/ecs_credentials_spec.rb index 9953b99bf38..8c963c0d1d0 100644 --- a/gems/aws-sdk-core/spec/aws/ecs_credentials_spec.rb +++ b/gems/aws-sdk-core/spec/aws/ecs_credentials_spec.rb @@ -87,17 +87,6 @@ module Aws expect(c.expiration.to_s).to eq(expiration.to_s) end - it 'will return the correct metrics' do - c = ECSCredentials.new(backoff: 0, retries: 0) - expect(c.metrics).to eq(['CREDENTIALS_HTTP']) - end - - it 'will return no metrics when resolving' do - c = ECSCredentials.new(backoff: 0, retries: 0) - c.resolving = true - expect(c.metrics).to eq([]) - end - context 'auto refreshing' do # expire in 4 minutes let(:expiration) { Time.now.utc + 299 } diff --git a/gems/aws-sdk-core/spec/aws/instance_profile_credentials_spec.rb b/gems/aws-sdk-core/spec/aws/instance_profile_credentials_spec.rb index 8b3e797421f..925b5808e9a 100644 --- a/gems/aws-sdk-core/spec/aws/instance_profile_credentials_spec.rb +++ b/gems/aws-sdk-core/spec/aws/instance_profile_credentials_spec.rb @@ -687,16 +687,5 @@ module Aws assert_requested(expected_request, times: 2) end end - - it 'will return the correct metrics' do - c = InstanceProfileCredentials.new - expect(c.metrics).to eq(['CREDENTIALS_IMDS']) - end - - it 'will return no metrics when resolving' do - c = InstanceProfileCredentials.new - c.resolving = true - expect(c.metrics).to eq([]) - end end end diff --git a/gems/aws-sdk-core/spec/aws/plugins/client_metrics_spec.rb b/gems/aws-sdk-core/spec/aws/plugins/client_metrics_spec.rb index 4427cf2949a..a6b46d43f7f 100644 --- a/gems/aws-sdk-core/spec/aws/plugins/client_metrics_spec.rb +++ b/gems/aws-sdk-core/spec/aws/plugins/client_metrics_spec.rb @@ -174,7 +174,6 @@ module Plugins expect(api_call.latency).to be_a_kind_of(Integer) expect(api_call.client_id).to eq('') expect(api_call.region).to eq('us-stubbed-1') - # expect(api_call.user_agent).to match(/^aws-sdk-ruby3/) expect(api_call.final_http_status_code).to eq(200) end end @@ -194,7 +193,6 @@ module Plugins expect(attempt.version).to be_a_kind_of(Integer) expect(attempt.fqdn).to eq('s3.us-stubbed-1.amazonaws.com') expect(attempt.region).to eq('us-stubbed-1') - # expect(attempt.user_agent).to match(/^aws-sdk-ruby3/) expect(attempt.access_key).to eq('stubbed-akid') expect(attempt.http_status_code).to eq(200) expect(attempt.request_latency).to be_a_kind_of(Integer) diff --git a/gems/aws-sdk-core/spec/aws/plugins/sign_spec.rb b/gems/aws-sdk-core/spec/aws/plugins/sign_spec.rb index 87bcd7e63b5..2c456b67e5d 100644 --- a/gems/aws-sdk-core/spec/aws/plugins/sign_spec.rb +++ b/gems/aws-sdk-core/spec/aws/plugins/sign_spec.rb @@ -203,14 +203,11 @@ def call(context) end end - it 'Adds metrics from the credential providers' do + it 'retrieves the credential provider metrics' do creds = Aws::Credentials.new('akid', 'secret') client = TestClient.new(client_options.merge(credentials: creds)) - resp = client.operation - req = resp.context.http_request - header = req.headers['User-Agent'] - metrics = header[(header.index('m/') + 2)..-1] - expect(metrics).to include('e') + expect(creds).to receive(:metrics) + client.operation end end diff --git a/gems/aws-sdk-core/spec/aws/process_credentials_spec.rb b/gems/aws-sdk-core/spec/aws/process_credentials_spec.rb index bd80973c55f..d038b0322bb 100644 --- a/gems/aws-sdk-core/spec/aws/process_credentials_spec.rb +++ b/gems/aws-sdk-core/spec/aws/process_credentials_spec.rb @@ -46,19 +46,6 @@ module Aws }.to raise_error(Errors::InvalidProcessCredentialsPayload) end - it 'will return the correct metrics when source is code' do - process = %w[echo {"Version":1,"AccessKeyId":"AK_PROC1","SecretAccessKey":"SECRET_AK_PROC1","SessionToken":"TOKEN_PROC1","AccountId":"ACCOUNT_ID_PROC1"}] - c = ProcessCredentials.new(process) - expect(c.metrics).to eq(['CREDENTIALS_PROCESS']) - end - - it 'will return the correct metrics when source is profile' do - process = %w[echo {"Version":1,"AccessKeyId":"AK_PROC1","SecretAccessKey":"SECRET_AK_PROC1","SessionToken":"TOKEN_PROC1","AccountId":"ACCOUNT_ID_PROC1"}] - c = ProcessCredentials.new(process) - c.metrics_source = :profile - expect(c.metrics).to eq(%w[CREDENTIALS_PROFILE_PROCESS CREDENTIALS_PROCESS]) - end - context 'legacy process string' do before do expect_any_instance_of(ProcessCredentials) diff --git a/gems/aws-sdk-core/spec/aws/shared_credentials_spec.rb b/gems/aws-sdk-core/spec/aws/shared_credentials_spec.rb index 02b4931ca77..38a5401396d 100644 --- a/gems/aws-sdk-core/spec/aws/shared_credentials_spec.rb +++ b/gems/aws-sdk-core/spec/aws/shared_credentials_spec.rb @@ -136,11 +136,5 @@ module Aws creds = SharedCredentials.new.credentials expect(creds).to eq(nil) end - - it 'will return the correct metrics' do - creds = SharedCredentials.new(path:mock_credential_file) - expect(creds.metrics).to eq(['CREDENTIALS_PROFILE']) - end - end end diff --git a/gems/aws-sdk-core/spec/aws/sso_credentials_spec.rb b/gems/aws-sdk-core/spec/aws/sso_credentials_spec.rb index 939ed8e3fd0..5cc05286a6d 100644 --- a/gems/aws-sdk-core/spec/aws/sso_credentials_spec.rb +++ b/gems/aws-sdk-core/spec/aws/sso_credentials_spec.rb @@ -148,22 +148,6 @@ def mock_token_file(start_url, cached_token) expect(sso_creds.expiration).to eq(expiration) end end - - describe '#metrics' do - - it 'returns the correct metrics when the source is code' do - c = SSOCredentials.new(sso_opts) - expect(c.metrics).to eq(['CREDENTIALS_SSO']) - end - - it 'returns the correct metrics when the source is new' do - c = SSOCredentials.new(sso_opts) - c.metrics_source = :new - expect(c.metrics).to eq(%w[CREDENTIALS_PROFILE_SSO CREDENTIALS_SSO]) - end - - end - end context 'legacy profile' do @@ -306,30 +290,6 @@ def mock_token_file(start_url, cached_token) sso_creds.credentials end end - - describe '#metrics' do - - it 'returns the correct metrics when the source is code' do - expect(SSO::Client).to receive(:new) - .with({region: sso_region, credentials: nil}) - .and_return(client) - - mock_token_file(sso_start_url, cached_token) - c = SSOCredentials.new(sso_opts) - expect(c.metrics).to eq(['CREDENTIALS_SSO_LEGACY']) - end - - it 'returns the correct metrics when the source is legacy' do - expect(SSO::Client).to receive(:new) - .with({region: sso_region, credentials: nil}) - .and_return(client) - - mock_token_file(sso_start_url, cached_token) - c = SSOCredentials.new(sso_opts) - c.metrics_source = :legacy - expect(c.metrics).to eq(%w[CREDENTIALS_PROFILE_SSO_LEGACY CREDENTIALS_SSO_LEGACY]) - end - end end end end From d2d05e4ca7190dd1305d857f1eaaba2d037c6a2d Mon Sep 17 00:00:00 2001 From: Richard Wang Date: Wed, 9 Apr 2025 13:27:27 -0700 Subject: [PATCH 52/59] Minor edits --- gems/aws-sdk-core/lib/aws-sdk-core/plugins/user_agent.rb | 1 - gems/aws-sdk-core/spec/aws/assume_role_credentials_spec.rb | 1 + gems/aws-sdk-core/spec/aws/shared_credentials_spec.rb | 1 + 3 files changed, 2 insertions(+), 1 deletion(-) diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/plugins/user_agent.rb b/gems/aws-sdk-core/lib/aws-sdk-core/plugins/user_agent.rb index b8c472eddb3..e2298a5898d 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/plugins/user_agent.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/plugins/user_agent.rb @@ -213,7 +213,6 @@ def metric_metadata end metrics = Thread.current[:aws_sdk_core_user_agent_metric].join(',') - # Metric metadata is limited to 1024 bytes return "m/#{metrics}" if metrics.bytesize <= 1024 diff --git a/gems/aws-sdk-core/spec/aws/assume_role_credentials_spec.rb b/gems/aws-sdk-core/spec/aws/assume_role_credentials_spec.rb index 745d098330c..caadd47f486 100644 --- a/gems/aws-sdk-core/spec/aws/assume_role_credentials_spec.rb +++ b/gems/aws-sdk-core/spec/aws/assume_role_credentials_spec.rb @@ -173,5 +173,6 @@ module Aws expect(before_refresh_called).to be(true) end + end end diff --git a/gems/aws-sdk-core/spec/aws/shared_credentials_spec.rb b/gems/aws-sdk-core/spec/aws/shared_credentials_spec.rb index 38a5401396d..1b0ca3f48fc 100644 --- a/gems/aws-sdk-core/spec/aws/shared_credentials_spec.rb +++ b/gems/aws-sdk-core/spec/aws/shared_credentials_spec.rb @@ -136,5 +136,6 @@ module Aws creds = SharedCredentials.new.credentials expect(creds).to eq(nil) end + end end From 18ae6241244e90cda76d1a4c4aa74d59234910a7 Mon Sep 17 00:00:00 2001 From: Richard Wang Date: Wed, 9 Apr 2025 13:31:23 -0700 Subject: [PATCH 53/59] More minor edits --- gems/aws-sdk-core/lib/aws-sdk-core/assume_role_credentials.rb | 4 ---- gems/aws-sdk-core/lib/aws-sdk-core/shared_config.rb | 3 ++- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_credentials.rb b/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_credentials.rb index bc53b3d329e..e7f6c6c8889 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_credentials.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/assume_role_credentials.rb @@ -79,10 +79,6 @@ def parse_account_id(resp) ARNParser.parse(arn).account_id if ARNParser.arn?(arn) end - def insert_metric(base, metrics) - base.insert(1, *metrics) - end - class << self # @api private diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/shared_config.rb b/gems/aws-sdk-core/lib/aws-sdk-core/shared_config.rb index 98c957d0411..d592267b1eb 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/shared_config.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/shared_config.rb @@ -277,6 +277,7 @@ def assume_role_from_profile(cfg, profile, opts, chain_config) else metrics << 'CREDENTIALS_PROFILE_SOURCE_PROFILE' end + # Set the original credentials metrics to [] to prevent duplicate metrics during sign plugin opts[:credentials].metrics = [] with_metrics(metrics) do creds = AssumeRoleCredentials.new(opts) @@ -299,7 +300,7 @@ def assume_role_from_profile(cfg, profile, opts, chain_config) opts[:serial_number] ||= prof_cfg['mfa_serial'] opts.delete(:source_profile) # Cleanup - metrics = Marshal.load(Marshal.dump(opts[:credentials].metrics)) + metrics = opts[:credentials].metrics.dup metrics << ('CREDENTIALS_PROFILE_NAMED_PROVIDER') opts[:credentials].metrics = [] with_metrics(metrics) do From ac4305f6513340eeacf7e0afdcc90d28be82efff Mon Sep 17 00:00:00 2001 From: Richard Wang Date: Wed, 9 Apr 2025 13:36:31 -0700 Subject: [PATCH 54/59] Add double arguments --- .../spec/aws/credential_provider_chain_spec.rb | 8 ++------ .../spec/aws/credential_resolution_chain_spec.rb | 6 ++---- 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/gems/aws-sdk-core/spec/aws/credential_provider_chain_spec.rb b/gems/aws-sdk-core/spec/aws/credential_provider_chain_spec.rb index 80d77139a61..c9bcdd115b6 100644 --- a/gems/aws-sdk-core/spec/aws/credential_provider_chain_spec.rb +++ b/gems/aws-sdk-core/spec/aws/credential_provider_chain_spec.rb @@ -135,20 +135,16 @@ def validate_metrics(expected_metrics) it 'hydrates credentials from ECS when AWS_CONTAINER_CREDENTIALS_RELATIVE_URI is set' do ENV['AWS_CONTAINER_CREDENTIALS_RELATIVE_URI'] = 'test_uri' - mock_ecs_creds = double('ECSCredentials') - allow(mock_ecs_creds).to receive(:metrics).and_return(['CREDENTIALS_HTTP']) + mock_ecs_creds = double('ECSCredentials', metrics: ['CREDENTIALS_HTTP'], set?: true) expect(ECSCredentials).to receive(:new).and_return(mock_ecs_creds) - expect(mock_ecs_creds).to receive(:set?).and_return(true) expect(credentials).to be(mock_ecs_creds) validate_metrics(['CREDENTIALS_HTTP']) end it 'hydrates credentials from ECS when AWS_CONTAINER_CREDENTIALS_FULL_URI is set' do ENV['AWS_CONTAINER_CREDENTIALS_FULL_URI'] = 'test_uri' - mock_ecs_creds = double('ECSCredentials') - allow(mock_ecs_creds).to receive(:metrics).and_return(['CREDENTIALS_HTTP']) + mock_ecs_creds = double('ECSCredentials', metrics: ['CREDENTIALS_HTTP'], set?: true) expect(ECSCredentials).to receive(:new).and_return(mock_ecs_creds) - expect(mock_ecs_creds).to receive(:set?).and_return(true) expect(credentials).to be(mock_ecs_creds) validate_metrics(['CREDENTIALS_HTTP']) end diff --git a/gems/aws-sdk-core/spec/aws/credential_resolution_chain_spec.rb b/gems/aws-sdk-core/spec/aws/credential_resolution_chain_spec.rb index 0011d7458ec..09649b4e342 100644 --- a/gems/aws-sdk-core/spec/aws/credential_resolution_chain_spec.rb +++ b/gems/aws-sdk-core/spec/aws/credential_resolution_chain_spec.rb @@ -1279,11 +1279,9 @@ def assume_role_web_identity_stub(role_arn, access_key, secret_key, token) end def sso_stub - token = double('token') - allow(token).to receive(:token).and_return('token') - token_provider = double('token_provider', token: token) + token = double('token', token: 'token') + token_provider = double('token_provider', token: token, set?: true) allow(Aws::SSOTokenProvider).to receive(:new).and_return(token_provider) - allow(token_provider).to receive(:set?).and_return(true) stub_request(:get, 'https://portal.sso.us-east-1.amazonaws.com/federation/credentials?account_id=SSO_ACCOUNT_ID&role_name=SSO_ROLE_NAME') .to_return(body: <<-RESP) { From 9f1f25c5f0d36ef17dd4c796a6833356515b94b6 Mon Sep 17 00:00:00 2001 From: Richard Wang Date: Wed, 9 Apr 2025 13:54:40 -0700 Subject: [PATCH 55/59] Remove dup --- gems/aws-sdk-core/lib/aws-sdk-core/shared_config.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/shared_config.rb b/gems/aws-sdk-core/lib/aws-sdk-core/shared_config.rb index d592267b1eb..f21f62d5368 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/shared_config.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/shared_config.rb @@ -270,7 +270,7 @@ def assume_role_from_profile(cfg, profile, opts, chain_config) opts[:profile] = opts.delete(:source_profile) opts.delete(:visited_profiles) - metrics = provider.metrics.dup + metrics = provider.metrics if provider.is_a? AssumeRoleCredentials opts[:credentials] = provider metrics.delete('CREDENTIALS_STS_ASSUME_ROLE') @@ -300,8 +300,8 @@ def assume_role_from_profile(cfg, profile, opts, chain_config) opts[:serial_number] ||= prof_cfg['mfa_serial'] opts.delete(:source_profile) # Cleanup - metrics = opts[:credentials].metrics.dup - metrics << ('CREDENTIALS_PROFILE_NAMED_PROVIDER') + metrics = opts[:credentials].metrics + metrics << 'CREDENTIALS_PROFILE_NAMED_PROVIDER' opts[:credentials].metrics = [] with_metrics(metrics) do creds = AssumeRoleCredentials.new(opts) From 281fc0d965402c30352777db4c20bbbbe4c2f1ce Mon Sep 17 00:00:00 2001 From: Richard Wang Date: Thu, 10 Apr 2025 11:24:35 -0700 Subject: [PATCH 56/59] Add changes from PR comments --- .../lib/aws-sdk-core/plugins/user_agent.rb | 2 +- .../lib/aws-sdk-core/shared_config.rb | 14 +- .../aws/credential_provider_chain_spec.rb | 28 +- .../aws/credential_resolution_chain_spec.rb | 319 +++++------------- 4 files changed, 103 insertions(+), 260 deletions(-) diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/plugins/user_agent.rb b/gems/aws-sdk-core/lib/aws-sdk-core/plugins/user_agent.rb index e2298a5898d..70717adb26c 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/plugins/user_agent.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/plugins/user_agent.rb @@ -222,7 +222,7 @@ def metric_metadata end end - # Priority set to 5 in order to add credentials related metrics from Sign plugin + # Priority set to 5 in order to add user agent as late as possible after signing handler(Handler, step: :sign, priority: 5) end end diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/shared_config.rb b/gems/aws-sdk-core/lib/aws-sdk-core/shared_config.rb index f21f62d5368..b9303f53013 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/shared_config.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/shared_config.rb @@ -259,7 +259,9 @@ def assume_role_from_profile(cfg, profile, opts, chain_config) 'provide only source_profile or credential_source, not both.' elsif opts[:source_profile] opts[:visited_profiles] ||= Set.new - provider = resolve_source_profile(opts[:source_profile], opts) + provider = with_metrics('CREDENTIALS_PROFILE_SOURCE_PROFILE') do + resolve_source_profile(opts[:source_profile], opts) + end if provider && (opts[:credentials] = provider.credentials) opts[:role_session_name] ||= prof_cfg['role_session_name'] opts[:role_session_name] ||= 'default_session' @@ -271,7 +273,7 @@ def assume_role_from_profile(cfg, profile, opts, chain_config) opts.delete(:visited_profiles) metrics = provider.metrics - if provider.is_a? AssumeRoleCredentials + if provider.is_a?(AssumeRoleCredentials) opts[:credentials] = provider metrics.delete('CREDENTIALS_STS_ASSUME_ROLE') else @@ -335,15 +337,11 @@ def resolve_source_profile(profile, opts = {}) elsif profile_config && profile_config['source_profile'] opts.delete(:source_profile) assume_role_credentials_from_config(opts.merge(profile: profile)) - elsif (provider = with_metrics('CREDENTIALS_PROFILE_SOURCE_PROFILE') do - assume_role_web_identity_credentials_from_config(opts.merge(profile: profile)) - end) + elsif (provider = assume_role_web_identity_credentials_from_config(opts.merge(profile: profile))) provider if provider.credentials.set? elsif (provider = assume_role_process_credentials_from_config(profile)) provider if provider.credentials.set? - elsif (provider = with_metrics('CREDENTIALS_PROFILE_SOURCE_PROFILE') do - sso_credentials_from_config(profile: profile) - end) + elsif (provider = sso_credentials_from_config(profile: profile)) provider if provider.credentials.set? end end diff --git a/gems/aws-sdk-core/spec/aws/credential_provider_chain_spec.rb b/gems/aws-sdk-core/spec/aws/credential_provider_chain_spec.rb index c9bcdd115b6..737494beb71 100644 --- a/gems/aws-sdk-core/spec/aws/credential_provider_chain_spec.rb +++ b/gems/aws-sdk-core/spec/aws/credential_provider_chain_spec.rb @@ -59,7 +59,7 @@ def validate_credentials(expected_creds) expect(creds.account_id).to eq(expected_creds[:account_id]) end - def validate_metrics(expected_metrics) + def validate_metrics(*expected_metrics) expect(credentials.metrics).to eq(expected_metrics) end @@ -89,7 +89,7 @@ def validate_metrics(expected_metrics) it 'hydrates credentials from config options' do expected_creds = with_config_credentials validate_credentials(expected_creds) - validate_metrics(['CREDENTIALS_PROFILE']) + validate_metrics('CREDENTIALS_PROFILE') end it 'hydrates credentials from ENV with prefix AWS_' do @@ -99,7 +99,7 @@ def validate_metrics(expected_metrics) ENV['AWS_SESSION_TOKEN'] = expected_creds[:session_token] ENV['AWS_ACCOUNT_ID'] = expected_creds[:account_id] validate_credentials(expected_creds) - validate_metrics(['CREDENTIALS_ENV_VARS']) + validate_metrics('CREDENTIALS_ENV_VARS') end it 'hydrates credentials from ENV with prefix AMAZON_' do @@ -108,7 +108,7 @@ def validate_metrics(expected_metrics) ENV['AMAZON_SECRET_ACCESS_KEY'] = expected_creds[:secret_access_key] ENV['AMAZON_SESSION_TOKEN'] = expected_creds[:session_token] validate_credentials(expected_creds) - validate_metrics(['CREDENTIALS_ENV_VARS']) + validate_metrics('CREDENTIALS_ENV_VARS') end it 'hydrates credentials from ENV at AWS_ACCESS_KEY & AWS_SECRET_KEY' do @@ -116,7 +116,7 @@ def validate_metrics(expected_metrics) ENV['AWS_ACCESS_KEY'] = expected_creds[:access_key_id] ENV['AWS_SECRET_KEY'] = expected_creds[:secret_access_key] validate_credentials(expected_creds) - validate_metrics(['CREDENTIALS_ENV_VARS']) + validate_metrics('CREDENTIALS_ENV_VARS') end it 'hydrates credentials from ENV at AWS_ACCESS_KEY_ID & AWS_SECRET_KEY' do @@ -124,13 +124,13 @@ def validate_metrics(expected_metrics) ENV['AWS_ACCESS_KEY_ID'] = expected_creds[:access_key_id] ENV['AWS_SECRET_KEY'] = expected_creds[:secret_access_key] validate_credentials(expected_creds) - validate_metrics(['CREDENTIALS_ENV_VARS']) + validate_metrics('CREDENTIALS_ENV_VARS') end it 'hydrates credentials from the instance profile service' do expect(mock_instance_creds).to receive(:set?).and_return(true) expect(credentials).to be(mock_instance_creds) - validate_metrics(['CREDENTIALS_IMDS']) + validate_metrics('CREDENTIALS_IMDS') end it 'hydrates credentials from ECS when AWS_CONTAINER_CREDENTIALS_RELATIVE_URI is set' do @@ -138,7 +138,7 @@ def validate_metrics(expected_metrics) mock_ecs_creds = double('ECSCredentials', metrics: ['CREDENTIALS_HTTP'], set?: true) expect(ECSCredentials).to receive(:new).and_return(mock_ecs_creds) expect(credentials).to be(mock_ecs_creds) - validate_metrics(['CREDENTIALS_HTTP']) + validate_metrics('CREDENTIALS_HTTP') end it 'hydrates credentials from ECS when AWS_CONTAINER_CREDENTIALS_FULL_URI is set' do @@ -146,7 +146,7 @@ def validate_metrics(expected_metrics) mock_ecs_creds = double('ECSCredentials', metrics: ['CREDENTIALS_HTTP'], set?: true) expect(ECSCredentials).to receive(:new).and_return(mock_ecs_creds) expect(credentials).to be(mock_ecs_creds) - validate_metrics(['CREDENTIALS_HTTP']) + validate_metrics('CREDENTIALS_HTTP') end describe 'with config set to nil' do @@ -172,7 +172,7 @@ def validate_metrics(expected_metrics) expected_creds = with_shared_credentials('test') ENV['AWS_DEFAULT_PROFILE'] = expected_creds[:profile_name] validate_credentials(expected_creds) - validate_metrics(['CREDENTIALS_PROFILE']) + validate_metrics('CREDENTIALS_PROFILE') end it 'returns credentials from proper profile when config is set' do @@ -180,7 +180,7 @@ def validate_metrics(expected_metrics) allow(config).to receive(:profile).and_return(expected_creds[:profile_name]) ENV['AWS_DEFAULT_PROFILE'] = 'BAD_PROFILE' validate_credentials(expected_creds) - validate_metrics(['CREDENTIALS_PROFILE']) + validate_metrics('CREDENTIALS_PROFILE') end end @@ -190,14 +190,14 @@ def validate_metrics(expected_metrics) ENV['AWS_DEFAULT_PROFILE'] = shared_creds[:profile_name] expected_creds = with_env_credentials validate_credentials(expected_creds) - validate_metrics(['CREDENTIALS_ENV_VARS']) + validate_metrics('CREDENTIALS_ENV_VARS') end it 'hydrates credentials from config over ENV' do env_creds = with_env_credentials expected_creds = with_config_credentials validate_credentials(expected_creds) - validate_metrics(['CREDENTIALS_PROFILE']) + validate_metrics('CREDENTIALS_PROFILE') end it 'hydrates credentials from profile when config set over ENV' do @@ -205,7 +205,7 @@ def validate_metrics(expected_metrics) allow(config).to receive(:profile).and_return(expected_creds[:profile_name]) env_creds = with_env_credentials validate_credentials(expected_creds) - validate_metrics(['CREDENTIALS_PROFILE']) + validate_metrics('CREDENTIALS_PROFILE') end end end diff --git a/gems/aws-sdk-core/spec/aws/credential_resolution_chain_spec.rb b/gems/aws-sdk-core/spec/aws/credential_resolution_chain_spec.rb index 09649b4e342..51137ded5eb 100644 --- a/gems/aws-sdk-core/spec/aws/credential_resolution_chain_spec.rb +++ b/gems/aws-sdk-core/spec/aws/credential_resolution_chain_spec.rb @@ -24,28 +24,6 @@ module Aws let(:mock_instance_creds) { double('InstanceProfileCredentials', set?: false) } - let(:metrics_hash) { - { - 'e': 'CREDENTIALS_CODE', - 'g': 'CREDENTIALS_ENV_VARS', - 'h': 'CREDENTIALS_ENV_VARS_STS_WEB_ID_TOKEN', - 'i': 'CREDENTIALS_STS_ASSUME_ROLE', - 'k': 'CREDENTIALS_STS_ASSUME_ROLE_WEB_ID', - "n": 'CREDENTIALS_PROFILE', - 'o': 'CREDENTIALS_PROFILE_SOURCE_PROFILE', - 'p': 'CREDENTIALS_PROFILE_NAMED_PROVIDER', - 'q': 'CREDENTIALS_PROFILE_STS_WEB_ID_TOKEN', - 'r': 'CREDENTIALS_PROFILE_SSO', - 's': 'CREDENTIALS_SSO', - 't': 'CREDENTIALS_PROFILE_SSO_LEGACY', - 'u': 'CREDENTIALS_SSO_LEGACY', - 'v': 'CREDENTIALS_PROFILE_PROCESS', - 'w': 'CREDENTIALS_PROCESS', - 'z': 'CREDENTIALS_HTTP', - '0': 'CREDENTIALS_IMDS' - } - } - before(:all) do # Ensure the sample_rest_xml is built before any mocks occur ApiHelper.sample_rest_xml @@ -80,8 +58,7 @@ module Aws region: 'us-east-1' ) expect(client.config.credentials.access_key_id).to eq('ACCESS_DIRECT') - expected_metrics = metrics_list_from_code(%w[n]) - expect(client.config.credentials.metrics).to contain_exactly(*expected_metrics) + expect(metric_values(client.config.credentials.metrics)).to include('n') end it 'prefers assume role credentials when profile explicitly set over ENV credentials' do @@ -101,8 +78,7 @@ module Aws profile: 'assumerole_sc', region: 'us-east-1' ) expect(client.config.credentials.credentials.access_key_id).to eq('AR_AKID') - expected_metrics = metrics_list_from_code(%w[o n i]) - expect(client.config.credentials.metrics).to contain_exactly(*expected_metrics) + expect(metric_values(client.config.credentials.metrics)).to include('o', 'n', 'i') end it 'emits correct UserAgent metrics during STS call for assume role credentials' do @@ -120,12 +96,10 @@ module Aws ) expect_any_instance_of(STS::Client).to receive(:assume_role).and_wrap_original do |m, *args| resp = m.call(*args) - metrics = metrics_from_user_agent_header(resp) - expected_metrics = %w[o n] - expect(metrics).to include(*expected_metrics) + expect(metrics_from_user_agent_header(resp)).to include('o', 'n') resp end - client = ApiHelper.sample_rest_xml::Client.new( + ApiHelper.sample_rest_xml::Client.new( profile: 'assumerole_sc', region: 'us-east-1' ) end @@ -143,8 +117,7 @@ module Aws expect( client.config.credentials.credentials.access_key_id ).to eq('AR_AKID') - expected_metrics = metrics_list_from_code(%w[q k]) - expect(client.config.credentials.metrics).to contain_exactly(*expected_metrics) + expect(metric_values(client.config.credentials.metrics)).to include('q', 'k') end it 'emits correct UserAgent metrics during STS call for assume role web identity from profile' do @@ -156,12 +129,10 @@ module Aws ) expect_any_instance_of(STS::Client).to receive(:assume_role_with_web_identity).and_wrap_original do |m, *args| resp = m.call(*args) - metrics = metrics_from_user_agent_header(resp) - expected_metrics = %w[q] - expect(metrics).to include(*expected_metrics) + expect(metrics_from_user_agent_header(resp)).to include('q') resp end - client = ApiHelper.sample_rest_xml::Client.new( + ApiHelper.sample_rest_xml::Client.new( profile: 'ar_web_identity', region: 'us-east-1' ) end @@ -183,8 +154,7 @@ module Aws ) expect(client.config.credentials.credentials.access_key_id) .to eq('AR_AKID') - expected_metrics = metrics_list_from_code(%w[h k]) - expect(client.config.credentials.metrics).to contain_exactly(*expected_metrics) + expect(metric_values(client.config.credentials.metrics)).to include('h', 'k') end it 'emits correct UserAgent metrics during STS call for assume role web identity from env' do @@ -201,26 +171,16 @@ module Aws ) expect_any_instance_of(STS::Client).to receive(:assume_role_with_web_identity).and_wrap_original do |m, *args| resp = m.call(*args) - metrics = metrics_from_user_agent_header(resp) - expected_metrics = %w[h] - expect(metrics).to include(*expected_metrics) + expect(metrics_from_user_agent_header(resp)).to include('h') resp end - client = ApiHelper.sample_rest_xml::Client.new( + ApiHelper.sample_rest_xml::Client.new( region: 'us-east-1' ) end it 'prefers sso credentials over assume role' do - creds = double('creds', set?: true, credentials: double(access_key_id: 'SSO_AKID'), - metrics: %w[CREDENTIALS_SSO]) - expect(SSOCredentials).to receive(:new).with( - sso_start_url: 'START_URL', - sso_region: 'us-east-1', - sso_account_id: 'SSO_ACCOUNT_ID', - sso_role_name: 'SSO_ROLE_NAME', - sso_session: 'sso-test-session', - ).and_return(creds) + sso_stub client = ApiHelper.sample_rest_xml::Client.new( profile: 'sso_creds', token_provider: nil @@ -228,69 +188,47 @@ module Aws expect( client.config.credentials.credentials.access_key_id ).to eq('SSO_AKID') - expected_metrics = metrics_list_from_code(%w[r s]) - expect(client.config.credentials.metrics).to contain_exactly(*expected_metrics) + expect(metric_values(client.config.credentials.metrics)).to include('r', 's') end it 'emits correct UserAgent metrics during SSO call for SSO' do sso_stub expect_any_instance_of(SSO::Client).to receive(:get_role_credentials).and_wrap_original do |m, *args| resp = m.call(*args) - metrics = metrics_from_user_agent_header(resp) - expected_metrics = %w[r] - expect(metrics).to include(*expected_metrics) + expect(metrics_from_user_agent_header(resp)).to include('r') resp end - client = ApiHelper.sample_rest_xml::Client.new( + ApiHelper.sample_rest_xml::Client.new( profile: 'sso_creds', token_provider: nil ) end it 'loads SSO credentials from a legacy profile' do - creds = double('creds', set?: true, credentials: double(access_key_id: 'SSO_AKID'), - metrics: %w[CREDENTIALS_SSO_LEGACY]) - expect(SSOCredentials).to receive(:new).with( - sso_start_url: 'START_URL', - sso_region: 'us-east-1', - sso_account_id: 'SSO_ACCOUNT_ID', - sso_role_name: 'SSO_ROLE_NAME', - sso_session: nil, - ).and_return(creds) + legacy_sso_stub client = ApiHelper.sample_rest_xml::Client.new( profile: 'sso_creds_legacy' ) expect( client.config.credentials.credentials.access_key_id ).to eq('SSO_AKID') - expected_metrics = metrics_list_from_code(%w[t u]) - expect(client.config.credentials.metrics).to contain_exactly(*expected_metrics) + expect(metric_values(client.config.credentials.metrics)).to include('t', 'u') end it 'emits correct UserAgent metrics during SSO call for legacy SSO' do legacy_sso_stub expect_any_instance_of(SSO::Client).to receive(:get_role_credentials).and_wrap_original do |m, *args| resp = m.call(*args) - metrics = metrics_from_user_agent_header(resp) - expected_metrics = %w[t] - expect(metrics).to include(*expected_metrics) + expect(metrics_from_user_agent_header(resp)).to include('t') resp end - client = ApiHelper.sample_rest_xml::Client.new( + ApiHelper.sample_rest_xml::Client.new( profile: 'sso_creds_legacy' ) end it 'loads SSO credentials from a mixed legacy profile when values match' do - creds = double('creds', set?: true, credentials: double(access_key_id: 'SSO_AKID'), - metrics: %w[CREDENTIALS_SSO]) - expect(SSOCredentials).to receive(:new).with( - sso_start_url: 'START_URL', - sso_region: 'us-east-1', - sso_account_id: 'SSO_ACCOUNT_ID', - sso_role_name: 'SSO_ROLE_NAME', - sso_session: 'sso-test-session', - ).and_return(creds) + sso_stub client = ApiHelper.sample_rest_xml::Client.new( profile: 'sso_creds_mixed_legacy', token_provider: nil, @@ -298,20 +236,11 @@ module Aws expect( client.config.credentials.credentials.access_key_id ).to eq('SSO_AKID') - expected_metrics = metrics_list_from_code(%w[r s]) - expect(client.config.credentials.metrics).to contain_exactly(*expected_metrics) + expect(metric_values(client.config.credentials.metrics)).to include('r', 's') end it 'loads SSO credentials from when the session name has quotes' do - creds = double('creds', set?: true, credentials: double(access_key_id: 'SSO_AKID'), - metrics: %w[CREDENTIALS_SSO]) - expect(SSOCredentials).to receive(:new).with( - sso_start_url: 'START_URL', - sso_region: 'us-east-1', - sso_account_id: 'SSO_ACCOUNT_ID', - sso_role_name: 'SSO_ROLE_NAME', - sso_session: 'sso test session', - ).and_return(creds) + sso_stub client = ApiHelper.sample_rest_xml::Client.new( profile: 'sso_creds_session_with_quotes', token_provider: nil @@ -319,8 +248,7 @@ module Aws expect( client.config.credentials.credentials.access_key_id ).to eq('SSO_AKID') - expected_metrics = metrics_list_from_code(%w[r s]) - expect(client.config.credentials.metrics).to contain_exactly(*expected_metrics) + expect(metric_values(client.config.credentials.metrics)).to include('r', 's') end it 'raises when attempting to load an incomplete SSO Profile' do @@ -366,8 +294,7 @@ module Aws expect( client.config.credentials.credentials.access_key_id ).to eq('AR_AKID') - expected_metrics = metrics_list_from_code(%w[o n i]) - expect(client.config.credentials.metrics).to contain_exactly(*expected_metrics) + expect(metric_values(client.config.credentials.metrics)).to include('o', 'n', 'i') sts_client = client.config.credentials.client expect( @@ -382,8 +309,7 @@ module Aws expect( client.config.credentials.credentials.access_key_id ).to eq('ACCESS_KEY_CRD') - expected_metrics = metrics_list_from_code(%w[n]) - expect(client.config.credentials.metrics).to contain_exactly(*expected_metrics) + expect(metric_values(client.config.credentials.metrics)).to include('n') end it 'will source static credentials from shared config after shared credentials' do @@ -393,8 +319,7 @@ module Aws expect( client.config.credentials.credentials.access_key_id ).to eq('ACCESS_KEY_SC1') - expected_metrics = metrics_list_from_code(%w[n]) - expect(client.config.credentials.metrics).to contain_exactly(*expected_metrics) + expect(metric_values(client.config.credentials.metrics)).to include('n') end it 'prefers process credentials over metadata credentials' do @@ -404,8 +329,7 @@ module Aws expect( client.config.credentials.credentials.access_key_id ).to eq('AK_PROC1') - expected_metrics = metrics_list_from_code(%w[v w]) - expect(client.config.credentials.metrics).to contain_exactly(*expected_metrics) + expect(metric_values(client.config.credentials.metrics)).to include('v', 'w') end it 'prefers direct credentials over process credentials when profile not set' do @@ -420,8 +344,7 @@ module Aws expect( client.config.credentials.credentials.access_key_id ).to eq('AKID_ENV_STUB') - expected_metrics = metrics_list_from_code(%w[g]) - expect(client.config.credentials.metrics).to contain_exactly(*expected_metrics) + expect(metric_values(client.config.credentials.metrics)).to include('g') end it 'prefers process credentials from direct profile over env' do @@ -436,8 +359,7 @@ module Aws expect( client.config.credentials.credentials.access_key_id ).to eq('AK_PROC1') - expected_metrics = metrics_list_from_code(%w[v w]) - expect(client.config.credentials.metrics).to contain_exactly(*expected_metrics) + expect(metric_values(client.config.credentials.metrics)).to include('v', 'w') end it 'attempts to fetch metadata credentials last using IMDS' do @@ -475,8 +397,7 @@ module Aws expect( client.config.credentials.credentials.access_key_id ).to eq('akid-md') - expected_metrics = metrics_list_from_code(%w[0]) - expect(client.config.credentials.metrics).to contain_exactly(*expected_metrics) + expect(metric_values(client.config.credentials.metrics)).to include('0') end it 'attempts to fetch metadata credentials last using ECS' do @@ -499,8 +420,7 @@ module Aws region: 'us-east-1' ) expect(client.config.credentials.credentials.access_key_id).to eq('ACCESS_KEY_ECS') - expected_metrics = metrics_list_from_code(%w[z]) - expect(client.config.credentials.metrics).to contain_exactly(*expected_metrics) + expect(metric_values(client.config.credentials.metrics)).to include('z') end describe 'Assume Role Resolution' do @@ -540,8 +460,7 @@ module Aws expect( client.config.credentials.credentials.access_key_id ).to eq('AR_AKID') - expected_metrics = metrics_list_from_code(%w[o q k i]) - expect(client.config.credentials.metrics).to contain_exactly(*expected_metrics) + expect(metric_values(client.config.credentials.metrics)).to include('o', 'q', 'k', 'i') sts_client = client.config.credentials.client expect( @@ -565,19 +484,15 @@ module Aws ) expect_any_instance_of(STS::Client).to receive(:assume_role_with_web_identity).and_wrap_original do |m, *args| resp = m.call(*args) - metrics = metrics_from_user_agent_header(resp) - expected_metrics = %w[o q] - expect(metrics).to include(*expected_metrics) + expect(metrics_from_user_agent_header(resp)).to include('o', 'q') resp end expect_any_instance_of(STS::Client).to receive(:assume_role).and_wrap_original do |m, *args| resp = m.call(*args) - metrics = metrics_from_user_agent_header(resp) - expected_metrics = %w[o q k] - expect(metrics).to include(*expected_metrics) + expect(metrics_from_user_agent_header(resp)).to include('o', 'q', 'k') resp end - client = ApiHelper.sample_rest_xml::Client.new( + ApiHelper.sample_rest_xml::Client.new( profile: 'ar_web_src', region: 'us-east-1' ) end @@ -597,8 +512,7 @@ module Aws expect( client.config.credentials.credentials.access_key_id ).to eq('AK_PROC1') - expected_metrics = metrics_list_from_code(%w[o v w i]) - expect(client.config.credentials.metrics).to contain_exactly(*expected_metrics) + expect(metric_values(client.config.credentials.metrics)).to include('o', 'v', 'w', 'i') end it 'emits correct UserAgent metrics during STS calls for :source_profile from process credentials' do @@ -611,29 +525,16 @@ module Aws ) expect_any_instance_of(STS::Client).to receive(:assume_role).and_wrap_original do |m, *args| resp = m.call(*args) - metrics = metrics_from_user_agent_header(resp) - expected_metrics = %w[o v w] - expect(metrics).to include(*expected_metrics) + expect(metrics_from_user_agent_header(resp)).to include('o', 'v', 'w') resp end - client = ApiHelper.sample_rest_xml::Client.new( + ApiHelper.sample_rest_xml::Client.new( profile: 'creds_from_sc_process', region: 'us-east-1' ) end it 'supports :source_profile from sso credentials' do - creds = double('creds', set?: true, credentials: Credentials.new('SSO_AKID', 'sak'), - metrics: %w[CREDENTIALS_SSO]) - expect(SSOCredentials).to receive(:new).with( - sso_start_url: 'START_URL', - sso_region: 'us-east-1', - sso_account_id: 'SSO_ACCOUNT_ID', - sso_role_name: 'SSO_ROLE_NAME', - sso_session: 'sso-test-session' - ).and_return(creds) - - allow(SSOTokenProvider).to receive(:new) - .and_return(double('SSOToken', set?: true)) + sso_stub assume_role_stub( 'arn:aws:iam::123456789012:role/foo', @@ -649,23 +550,11 @@ module Aws expect( client.config.credentials.credentials.access_key_id ).to eq('AR_AKID') - expected_metrics = metrics_list_from_code(%w[o r s i]) - expect(client.config.credentials.metrics).to contain_exactly(*expected_metrics) + expect(metric_values(client.config.credentials.metrics)).to include('o', 'r', 's', 'i') end - it 'emits correct UserAgent metrics during STS calls for :source_profile from sso credentials' do - creds = double('creds', set?: true, credentials: Credentials.new('SSO_AKID', 'sak'), - metrics: %w[CREDENTIALS_SSO]) - expect(SSOCredentials).to receive(:new).with( - sso_start_url: 'START_URL', - sso_region: 'us-east-1', - sso_account_id: 'SSO_ACCOUNT_ID', - sso_role_name: 'SSO_ROLE_NAME', - sso_session: 'sso-test-session', - ).and_return(creds) - - allow(SSOTokenProvider).to receive(:new) - .and_return(double('SSOToken', set?: true)) + it 'emits correct UserAgent metrics during service calls for :source_profile from sso credentials' do + sso_stub assume_role_stub( 'arn:aws:iam::123456789012:role/foo', @@ -674,31 +563,23 @@ module Aws 'SECRET_AK', 'TOKEN' ) + expect_any_instance_of(SSO::Client).to receive(:get_role_credentials).and_wrap_original do |m, *args| + resp = m.call(*args) + expect(metrics_from_user_agent_header(resp)).to include('o', 'r') + resp + end expect_any_instance_of(STS::Client).to receive(:assume_role).and_wrap_original do |m, *args| resp = m.call(*args) - metrics = metrics_from_user_agent_header(resp) - expected_metrics = %w[o r s] - expect(metrics).to include(*expected_metrics) + expect(metrics_from_user_agent_header(resp)).to include('o', 'r', 's') resp end - client = ApiHelper.sample_rest_xml::Client.new( + ApiHelper.sample_rest_xml::Client.new( profile: 'ar_sso_src', region: 'us-east-1' ) end it 'supports :source_profile from legacy sso credentials' do - creds = double('creds', set?: true, credentials: Credentials.new('SSO_AKID', 'sak'), - metrics: %w[CREDENTIALS_SSO_LEGACY]) - expect(SSOCredentials).to receive(:new).with( - sso_start_url: 'START_URL', - sso_region: 'us-east-1', - sso_account_id: 'SSO_ACCOUNT_ID', - sso_role_name: 'SSO_ROLE_NAME', - sso_session: nil, - ).and_return(creds) - - allow(SSOTokenProvider).to receive(:new) - .and_return(double('SSOToken', set?: true)) + legacy_sso_stub assume_role_stub( 'arn:aws:iam::123456789012:role/foo', @@ -714,23 +595,11 @@ module Aws expect( client.config.credentials.credentials.access_key_id ).to eq('AR_AKID') - expected_metrics = metrics_list_from_code(%w[o t u i]) - expect(client.config.credentials.metrics).to contain_exactly(*expected_metrics) + expect(metric_values(client.config.credentials.metrics)).to include('o', 't', 'u', 'i') end it 'emits correct UserAgent metrics during STS calls for :source_profile from legacy sso credentials' do - creds = double('creds', set?: true, credentials: Credentials.new('SSO_AKID', 'sak'), - metrics: %w[CREDENTIALS_SSO_LEGACY]) - expect(SSOCredentials).to receive(:new).with( - sso_start_url: 'START_URL', - sso_region: 'us-east-1', - sso_account_id: 'SSO_ACCOUNT_ID', - sso_role_name: 'SSO_ROLE_NAME', - sso_session: nil, - ).and_return(creds) - - allow(SSOTokenProvider).to receive(:new) - .and_return(double('SSOToken', set?: true)) + legacy_sso_stub assume_role_stub( 'arn:aws:iam::123456789012:role/foo', @@ -739,14 +608,17 @@ module Aws 'SECRET_AK', 'TOKEN' ) + expect_any_instance_of(SSO::Client).to receive(:get_role_credentials).and_wrap_original do |m, *args| + resp = m.call(*args) + expect(metrics_from_user_agent_header(resp)).to include('o', 't') + resp + end expect_any_instance_of(STS::Client).to receive(:assume_role).and_wrap_original do |m, *args| resp = m.call(*args) - metrics = metrics_from_user_agent_header(resp) - expected_metrics = %w[o t u] - expect(metrics).to include(*expected_metrics) + expect(metrics_from_user_agent_header(resp)).to include('o', 't', 'u') resp end - client = ApiHelper.sample_rest_xml::Client.new( + ApiHelper.sample_rest_xml::Client.new( profile: 'ar_sso_legacy_src', region: 'us-east-1' ) end @@ -774,8 +646,7 @@ module Aws expect( client.config.credentials.credentials.access_key_id ).to eq('AK_2') - expected_metrics = metrics_list_from_code(%w[o n i]) - expect(client.config.credentials.metrics).to contain_exactly(*expected_metrics) + expect(metric_values(client.config.credentials.metrics)).to include('o', 'n', 'i') end it 'emits correct UserAgent metrics during STS calls for assume role chaining' do @@ -796,12 +667,10 @@ module Aws ) allow_any_instance_of(STS::Client).to receive(:assume_role).and_wrap_original do |m, *args| resp = m.call(*args) - metrics = metrics_from_user_agent_header(resp) - expected_metrics = %w[o n] - expect(metrics).to include(*expected_metrics) + expect(metrics_from_user_agent_header(resp)).to include('o', 'n') resp end - client = ApiHelper.sample_rest_xml::Client.new( + ApiHelper.sample_rest_xml::Client.new( profile: 'assume_role_chain_b', region: 'us-east-1' ) end @@ -821,8 +690,7 @@ module Aws expect( client.config.credentials.credentials.access_key_id ).to eq('AK_2') - expected_metrics = metrics_list_from_code(%w[o n i]) - expect(client.config.credentials.metrics).to contain_exactly(*expected_metrics) + expect(metric_values(client.config.credentials.metrics)).to include('o', 'n', 'i') end it 'uses static credentials when the profile self references' do @@ -840,8 +708,7 @@ module Aws expect( client.config.credentials.credentials.access_key_id ).to eq('AK_2') - expected_metrics = metrics_list_from_code(%w[o n i]) - expect(client.config.credentials.metrics).to contain_exactly(*expected_metrics) + expect(metric_values(client.config.credentials.metrics)).to include('o', 'n', 'i') end it 'raises if there is a loop in chained profiles' do @@ -883,8 +750,7 @@ module Aws expect( client.config.credentials.credentials.access_key_id ).to eq('AR_AKID') - expected_metrics = metrics_list_from_code(%w[o n i]) - expect(client.config.credentials.metrics).to contain_exactly(*expected_metrics) + expect(metric_values(client.config.credentials.metrics)).to include('o', 'n', 'i') end it 'will then try to assume a role from shared config' do @@ -901,8 +767,7 @@ module Aws expect( client.config.credentials.credentials.access_key_id ).to eq('AR_AKID') - expected_metrics = metrics_list_from_code(%w[o n i]) - expect(client.config.credentials.metrics).to contain_exactly(*expected_metrics) + expect(metric_values(client.config.credentials.metrics)).to include('o', 'n', 'i') end it 'assumes a role from config using source in shared credentials' do @@ -919,8 +784,7 @@ module Aws expect( client.config.credentials.credentials.access_key_id ).to eq('AR_AKID') - expected_metrics = metrics_list_from_code(%w[o n i]) - expect(client.config.credentials.metrics).to contain_exactly(*expected_metrics) + expect(metric_values(client.config.credentials.metrics)).to include('o', 'n', 'i') end it 'allows region to be resolved when unspecified' do @@ -941,8 +805,7 @@ module Aws expect( credentials.credentials.access_key_id ).to eq('AR_AKID') - expected_metrics = metrics_list_from_code(%w[o n i]) - expect(credentials.metrics).to contain_exactly(*expected_metrics) + expect(metric_values(credentials.metrics)).to include('o', 'n', 'i') end end @@ -987,8 +850,7 @@ module Aws expect( client.config.credentials.credentials.access_key_id ).to eq('AR_AKID') - expected_metrics = metrics_list_from_code(%w[p 0 i]) - expect(client.config.credentials.metrics).to contain_exactly(*expected_metrics) + expect(metric_values(client.config.credentials.metrics)).to include('p', '0', 'i') end it 'emits correct UserAgent metrics during STS calls for EC2 Instance Metadata as a source' do @@ -1027,12 +889,10 @@ module Aws .to_return(status: 200, body: resp) expect_any_instance_of(STS::Client).to receive(:assume_role).and_wrap_original do |m, *args| resp = m.call(*args) - metrics = metrics_from_user_agent_header(resp) - expected_metrics = %w[p 0] - expect(metrics).to include(*expected_metrics) + expect(metrics_from_user_agent_header(resp)).to include('p', '0') resp end - client = ApiHelper.sample_rest_xml::Client.new( + ApiHelper.sample_rest_xml::Client.new( profile: profile, region: 'us-east-1' ) @@ -1068,8 +928,7 @@ module Aws expect( client.config.credentials.credentials.access_key_id ).to eq('AR_AKID') - expected_metrics = metrics_list_from_code(%w[p z i]) - expect(client.config.credentials.metrics).to contain_exactly(*expected_metrics) + expect(metric_values(client.config.credentials.metrics)).to include('p', 'z', 'i') end it 'emits correct UserAgent metrics during STS calls for ECS Credentials as a source' do @@ -1097,12 +956,10 @@ module Aws ) expect_any_instance_of(STS::Client).to receive(:assume_role).and_wrap_original do |m, *args| resp = m.call(*args) - metrics = metrics_from_user_agent_header(resp) - expected_metrics = %w[p z] - expect(metrics).to include(*expected_metrics) + expect(metrics_from_user_agent_header(resp)).to include('p', 'z') resp end - client = ApiHelper.sample_rest_xml::Client.new( + ApiHelper.sample_rest_xml::Client.new( profile: profile, region: 'us-east-1' ) @@ -1135,8 +992,7 @@ module Aws expect( client.config.credentials.credentials.access_key_id ).to eq('ACCESS_DIRECT') - expected_metrics = metrics_list_from_code(%w[n]) - expect(client.config.credentials.metrics).to contain_exactly(*expected_metrics) + expect(metric_values(client.config.credentials.metrics)).to include('n') end it 'prefers ENV credentials over shared config when profile not set' do @@ -1151,8 +1007,7 @@ module Aws expect( client.config.credentials.credentials.access_key_id ).to eq('AKID_ENV_STUB') - expected_metrics = metrics_list_from_code(%w[g]) - expect(client.config.credentials.metrics).to contain_exactly(*expected_metrics) + expect(metric_values(client.config.credentials.metrics)).to include('g') end it 'prefers config from profile over ENV credentials when profile is set on client' do @@ -1167,8 +1022,7 @@ module Aws expect( client.config.credentials.credentials.access_key_id ).to eq('ACCESS_KEY_1') - expected_metrics = metrics_list_from_code(%w[n]) - expect(client.config.credentials.metrics).to contain_exactly(*expected_metrics) + expect(metric_values(client.config.credentials.metrics)).to include('n') end it 'will not load credentials from shared config' do @@ -1220,8 +1074,7 @@ module Aws expect( client.config.credentials.credentials.access_key_id ).to eq('akid-md') - expected_metrics = metrics_list_from_code(%w[0]) - expect(client.config.credentials.metrics).to contain_exactly(*expected_metrics) + expect(metric_values(client.config.credentials.metrics)).to include('0') end end @@ -1289,7 +1142,7 @@ def sso_stub "accessKeyId": "SSO_AKID", "secretAccessKey": "secret_key", "sessionToken": "token", - "expiration": #{(Time.now + 3600).to_i} + "expiration": #{(Time.now + 3600).to_i * 1000} } } RESP @@ -1323,20 +1176,12 @@ def stub_token_file(token) def metrics_from_user_agent_header(resp) header = resp.context.http_request.headers['User-Agent'] - header.match(/ m\/([A-Za-z0-9+-,]+)/)[1].split(',') - end - - def metrics_list_from_code(codes) - codes.map { |code| metrics_hash[code.to_sym] } - end - - def validate_metrics(actual, expected) - expected = metrics_list_from_code(expected) - (actual - expected).empty? && (expected - actual).empty? + # Parse list of metrics from User-Agent header + header.match(%r{ m/([A-Za-z0-9+-,]+)})[1].split(',') end - def validate_header_metrics(actual, expected) - (expected - actual).empty? + def metric_values(metrics) + metrics.map { |metric| Aws::Plugins::UserAgent::METRICS[metric] } end end end From 147f5e713c0731544e41074219817a62037baacc Mon Sep 17 00:00:00 2001 From: Richard Wang Date: Thu, 10 Apr 2025 13:12:07 -0700 Subject: [PATCH 57/59] Add some rubocop fixes --- .../lib/aws-sdk-core/credential_provider_chain.rb | 1 - gems/aws-sdk-core/lib/aws-sdk-core/plugins/sign.rb | 4 +--- .../spec/aws/credential_resolution_chain_spec.rb | 12 ++++-------- 3 files changed, 5 insertions(+), 12 deletions(-) diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/credential_provider_chain.rb b/gems/aws-sdk-core/lib/aws-sdk-core/credential_provider_chain.rb index f90b04ae016..2efebeaaef1 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/credential_provider_chain.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/credential_provider_chain.rb @@ -99,7 +99,6 @@ def static_profile_process_credentials(options) nil end - def env_credentials(_options) key = %w[AWS_ACCESS_KEY_ID AMAZON_ACCESS_KEY_ID AWS_ACCESS_KEY] secret = %w[AWS_SECRET_ACCESS_KEY AMAZON_SECRET_ACCESS_KEY AWS_SECRET_KEY] diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/plugins/sign.rb b/gems/aws-sdk-core/lib/aws-sdk-core/plugins/sign.rb index cfd1b35aa14..eba2235498f 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/plugins/sign.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/plugins/sign.rb @@ -58,9 +58,7 @@ def call(context) private def with_metrics(credentials, &block) - unless credentials && credentials.respond_to?(:metrics) - return block.call - end + return block.call unless credentials&.respond_to?(:metrics) Aws::Plugins::UserAgent.metric(*credentials.metrics, &block) end diff --git a/gems/aws-sdk-core/spec/aws/credential_resolution_chain_spec.rb b/gems/aws-sdk-core/spec/aws/credential_resolution_chain_spec.rb index 51137ded5eb..e141482d286 100644 --- a/gems/aws-sdk-core/spec/aws/credential_resolution_chain_spec.rb +++ b/gems/aws-sdk-core/spec/aws/credential_resolution_chain_spec.rb @@ -231,7 +231,7 @@ module Aws sso_stub client = ApiHelper.sample_rest_xml::Client.new( profile: 'sso_creds_mixed_legacy', - token_provider: nil, + token_provider: nil ) expect( client.config.credentials.credentials.access_key_id @@ -411,8 +411,7 @@ module Aws "Expiration" : "#{(Time.now.utc + 3600).strftime('%Y-%m-%dT%H:%M:%SZ')}" } JSON - stub_const('ENV', - 'AWS_CONTAINER_CREDENTIALS_RELATIVE_URI' => path) + stub_const('ENV', 'AWS_CONTAINER_CREDENTIALS_RELATIVE_URI' => path) stub_request(:get, "http://169.254.170.2#{path}") .to_return(status: 200, body: resp) client = ApiHelper.sample_rest_xml::Client.new( @@ -719,7 +718,6 @@ module Aws end.to raise_error(Errors::SourceProfileCircularReferenceError) end - it 'raises if credential_source is present but invalid' do expect do ApiHelper.sample_rest_xml::Client.new( @@ -910,8 +908,7 @@ module Aws "Expiration" : "#{(Time.now.utc + 3600).strftime('%Y-%m-%dT%H:%M:%SZ')}" } JSON - stub_const('ENV', - 'AWS_CONTAINER_CREDENTIALS_RELATIVE_URI' => path) + stub_const('ENV', 'AWS_CONTAINER_CREDENTIALS_RELATIVE_URI' => path) stub_request(:get, "http://169.254.170.2#{path}") .to_return(status: 200, body: resp) assume_role_stub( @@ -943,8 +940,7 @@ module Aws "Expiration" : "#{(Time.now.utc + 3600).strftime('%Y-%m-%dT%H:%M:%SZ')}" } JSON - stub_const('ENV', - 'AWS_CONTAINER_CREDENTIALS_RELATIVE_URI' => path) + stub_const('ENV', 'AWS_CONTAINER_CREDENTIALS_RELATIVE_URI' => path) stub_request(:get, "http://169.254.170.2#{path}") .to_return(status: 200, body: resp) assume_role_stub( From 5a5fa02ac3917ff7f9e1241f9968d9708144967e Mon Sep 17 00:00:00 2001 From: Richard Wang Date: Fri, 11 Apr 2025 09:07:21 -0700 Subject: [PATCH 58/59] Fix resolve source --- .../lib/aws-sdk-core/shared_config.rb | 20 ++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/shared_config.rb b/gems/aws-sdk-core/lib/aws-sdk-core/shared_config.rb index b9303f53013..fecba9a928e 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/shared_config.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/shared_config.rb @@ -259,9 +259,7 @@ def assume_role_from_profile(cfg, profile, opts, chain_config) 'provide only source_profile or credential_source, not both.' elsif opts[:source_profile] opts[:visited_profiles] ||= Set.new - provider = with_metrics('CREDENTIALS_PROFILE_SOURCE_PROFILE') do - resolve_source_profile(opts[:source_profile], opts) - end + provider = resolve_source_profile(opts[:source_profile], opts) if provider && (opts[:credentials] = provider.credentials) opts[:role_session_name] ||= prof_cfg['role_session_name'] opts[:role_session_name] ||= 'default_session' @@ -337,15 +335,27 @@ def resolve_source_profile(profile, opts = {}) elsif profile_config && profile_config['source_profile'] opts.delete(:source_profile) assume_role_credentials_from_config(opts.merge(profile: profile)) - elsif (provider = assume_role_web_identity_credentials_from_config(opts.merge(profile: profile))) + elsif (provider = assume_role_web_identity_credentials_from_config_with_metrics(opts.merge(profile: profile))) provider if provider.credentials.set? elsif (provider = assume_role_process_credentials_from_config(profile)) provider if provider.credentials.set? - elsif (provider = sso_credentials_from_config(profile: profile)) + elsif (provider = sso_credentials_from_config_with_metrics(profile)) provider if provider.credentials.set? end end + def assume_role_web_identity_credentials_from_config_with_metrics(opts) + with_metrics('CREDENTIALS_PROFILE_SOURCE_PROFILE') do + assume_role_web_identity_credentials_from_config(opts) + end + end + + def sso_credentials_from_config_with_metrics(profile) + with_metrics('CREDENTIALS_PROFILE_SOURCE_PROFILE') do + sso_credentials_from_config(profile: profile) + end + end + def credentials_from_source(credential_source, config) case credential_source when 'Ec2InstanceMetadata' From ab2034fecf1eaf2424d1ae418fbedc8ef3af29f7 Mon Sep 17 00:00:00 2001 From: Richard Wang Date: Mon, 14 Apr 2025 08:33:50 -0700 Subject: [PATCH 59/59] Omit unused metrics --- gems/aws-sdk-core/lib/aws-sdk-core/plugins/user_agent.rb | 6 ------ gems/aws-sdk-core/lib/aws-sdk-core/shared_config.rb | 1 + 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/plugins/user_agent.rb b/gems/aws-sdk-core/lib/aws-sdk-core/plugins/user_agent.rb index 70717adb26c..5c1c3faada4 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/plugins/user_agent.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/plugins/user_agent.rb @@ -37,14 +37,10 @@ class UserAgent < Seahorse::Client::Plugin "FLEXIBLE_CHECKSUMS_RES_WHEN_REQUIRED" : "c", "DDB_MAPPER": "d", "CREDENTIALS_CODE" : "e", - "CREDENTIALS_JVM_SYSTEM_PROPERTIES" : "f", "CREDENTIALS_ENV_VARS" : "g", "CREDENTIALS_ENV_VARS_STS_WEB_ID_TOKEN" : "h", "CREDENTIALS_STS_ASSUME_ROLE" : "i", - "CREDENTIALS_STS_ASSUME_ROLE_SAML" : "j", "CREDENTIALS_STS_ASSUME_ROLE_WEB_ID" : "k", - "CREDENTIALS_STS_FEDERATION_TOKEN" : "l", - "CREDENTIALS_STS_SESSION_TOKEN" : "m", "CREDENTIALS_PROFILE" : "n", "CREDENTIALS_PROFILE_SOURCE_PROFILE" : "o", "CREDENTIALS_PROFILE_NAMED_PROVIDER" : "p", @@ -55,8 +51,6 @@ class UserAgent < Seahorse::Client::Plugin "CREDENTIALS_SSO_LEGACY" : "u", "CREDENTIALS_PROFILE_PROCESS" : "v", "CREDENTIALS_PROCESS" : "w", - "CREDENTIALS_BOTO2_CONFIG_FILE" : "x", - "CREDENTIALS_AWS_SDK_STORE" : "y", "CREDENTIALS_HTTP" : "z", "CREDENTIALS_IMDS" : "0", "SSO_LOGIN_DEVICE" : "1", diff --git a/gems/aws-sdk-core/lib/aws-sdk-core/shared_config.rb b/gems/aws-sdk-core/lib/aws-sdk-core/shared_config.rb index fecba9a928e..140650e985a 100644 --- a/gems/aws-sdk-core/lib/aws-sdk-core/shared_config.rb +++ b/gems/aws-sdk-core/lib/aws-sdk-core/shared_config.rb @@ -302,6 +302,7 @@ def assume_role_from_profile(cfg, profile, opts, chain_config) metrics = opts[:credentials].metrics metrics << 'CREDENTIALS_PROFILE_NAMED_PROVIDER' + # Set the original credentials metrics to [] to prevent duplicate metrics during sign plugin opts[:credentials].metrics = [] with_metrics(metrics) do creds = AssumeRoleCredentials.new(opts)