aws-sdk-core 3.220.1 → 3.232.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +140 -0
  3. data/VERSION +1 -1
  4. data/lib/aws-sdk-core/assume_role_credentials.rb +1 -0
  5. data/lib/aws-sdk-core/assume_role_web_identity_credentials.rb +1 -0
  6. data/lib/aws-sdk-core/credential_provider.rb +4 -0
  7. data/lib/aws-sdk-core/credential_provider_chain.rb +28 -8
  8. data/lib/aws-sdk-core/credentials.rb +6 -0
  9. data/lib/aws-sdk-core/ecs_credentials.rb +1 -0
  10. data/lib/aws-sdk-core/endpoints/matchers.rb +2 -1
  11. data/lib/aws-sdk-core/endpoints.rb +37 -13
  12. data/lib/aws-sdk-core/error_handler.rb +5 -0
  13. data/lib/aws-sdk-core/errors.rb +2 -2
  14. data/lib/aws-sdk-core/event_emitter.rb +1 -1
  15. data/lib/aws-sdk-core/instance_profile_credentials.rb +147 -157
  16. data/lib/aws-sdk-core/json/error_handler.rb +14 -4
  17. data/lib/aws-sdk-core/plugins/client_metrics_plugin.rb +0 -1
  18. data/lib/aws-sdk-core/plugins/credentials_configuration.rb +75 -59
  19. data/lib/aws-sdk-core/plugins/endpoint_pattern.rb +40 -32
  20. data/lib/aws-sdk-core/plugins/sign.rb +29 -20
  21. data/lib/aws-sdk-core/plugins/stub_responses.rb +6 -0
  22. data/lib/aws-sdk-core/plugins/user_agent.rb +24 -2
  23. data/lib/aws-sdk-core/process_credentials.rb +1 -1
  24. data/lib/aws-sdk-core/rest/request/headers.rb +1 -1
  25. data/lib/aws-sdk-core/rpc_v2/error_handler.rb +26 -16
  26. data/lib/aws-sdk-core/rpc_v2/parser.rb +8 -0
  27. data/lib/aws-sdk-core/shared_config.rb +82 -21
  28. data/lib/aws-sdk-core/shared_credentials.rb +1 -0
  29. data/lib/aws-sdk-core/sso_credentials.rb +2 -0
  30. data/lib/aws-sdk-core/static_token_provider.rb +1 -2
  31. data/lib/aws-sdk-core/token.rb +3 -3
  32. data/lib/aws-sdk-core/token_provider.rb +4 -0
  33. data/lib/aws-sdk-core/token_provider_chain.rb +2 -6
  34. data/lib/aws-sdk-core/util.rb +2 -1
  35. data/lib/aws-sdk-core/xml/error_handler.rb +3 -1
  36. data/lib/aws-sdk-sso/client.rb +25 -19
  37. data/lib/aws-sdk-sso/endpoint_provider.rb +2 -2
  38. data/lib/aws-sdk-sso.rb +1 -1
  39. data/lib/aws-sdk-ssooidc/client.rb +38 -21
  40. data/lib/aws-sdk-ssooidc/client_api.rb +6 -0
  41. data/lib/aws-sdk-ssooidc/types.rb +28 -1
  42. data/lib/aws-sdk-ssooidc.rb +1 -1
  43. data/lib/aws-sdk-sts/client.rb +25 -19
  44. data/lib/aws-sdk-sts/client_api.rb +10 -8
  45. data/lib/aws-sdk-sts/endpoint_provider.rb +18 -18
  46. data/lib/aws-sdk-sts/errors.rb +0 -1
  47. data/lib/aws-sdk-sts/presigner.rb +2 -6
  48. data/lib/aws-sdk-sts.rb +1 -1
  49. data/lib/seahorse/client/async_base.rb +4 -5
  50. data/lib/seahorse/client/base.rb +0 -14
  51. data/lib/seahorse/client/h2/connection.rb +18 -28
  52. data/lib/seahorse/client/http/response.rb +1 -1
  53. data/lib/seahorse/client/net_http/connection_pool.rb +2 -1
  54. data/lib/seahorse/client/networking_error.rb +1 -1
  55. data/lib/seahorse/client/plugins/h2.rb +4 -4
  56. data/lib/seahorse/client/request_context.rb +2 -2
  57. data/lib/seahorse/util.rb +2 -1
  58. data/sig/aws-sdk-core/async_client_stubs.rbs +21 -0
  59. data/sig/seahorse/client/async_base.rbs +18 -0
  60. metadata +34 -8
@@ -4,62 +4,70 @@ module Aws
4
4
  module Plugins
5
5
  # @api private
6
6
  class EndpointPattern < Seahorse::Client::Plugin
7
-
8
- option(:disable_host_prefix_injection,
7
+ option(
8
+ :disable_host_prefix_injection,
9
9
  default: false,
10
10
  doc_type: 'Boolean',
11
- docstring: <<-DOCS
12
- Set to true to disable SDK automatically adding host prefix
13
- to default service endpoint when available.
14
- DOCS
15
- )
11
+ docstring: 'When `true`, the SDK will not prepend the modeled host prefix to the endpoint.'
12
+ ) do |cfg|
13
+ resolve_disable_host_prefix_injection(cfg)
14
+ end
16
15
 
17
- def add_handlers(handlers, config)
16
+ def add_handlers(handlers, _config)
18
17
  handlers.add(Handler, priority: 10)
19
18
  end
20
19
 
21
- class Handler < Seahorse::Client::Handler
20
+ class << self
21
+ private
22
+
23
+ def resolve_disable_host_prefix_injection(cfg)
24
+ value = ENV['AWS_DISABLE_HOST_PREFIX_INJECTION'] ||
25
+ Aws.shared_config.disable_host_prefix_injection(profile: cfg.profile) ||
26
+ 'false'
27
+ value = Aws::Util.str_2_bool(value)
28
+ unless [true, false].include?(value)
29
+ raise ArgumentError,
30
+ 'Must provide either `true` or `false` for '\
31
+ 'disable_host_prefix_injection profile option or for '\
32
+ 'ENV[\'AWS_DISABLE_HOST_PREFIX_INJECTION\']'
33
+ end
34
+ value
35
+ end
36
+ end
22
37
 
38
+ # @api private
39
+ class Handler < Seahorse::Client::Handler
23
40
  def call(context)
24
- if !context.config.disable_host_prefix_injection
41
+ unless context.config.disable_host_prefix_injection
25
42
  endpoint_trait = context.operation.endpoint_pattern
26
- if endpoint_trait && !endpoint_trait.empty?
27
- _apply_endpoint_trait(context, endpoint_trait)
28
- end
43
+ apply_endpoint_trait(context, endpoint_trait) if endpoint_trait && !endpoint_trait.empty?
29
44
  end
30
45
  @handler.call(context)
31
46
  end
32
47
 
33
48
  private
34
49
 
35
- def _apply_endpoint_trait(context, trait)
36
- # currently only support host pattern
37
- ori_host = context.http_request.endpoint.host
38
- if pattern = trait['hostPrefix']
39
- host_prefix = pattern.gsub(/\{.+?\}/) do |label|
40
- label = label.delete("{}")
41
- _replace_label_value(
42
- ori_host, label, context.operation.input, context.params)
43
- end
44
- context.http_request.endpoint.host = host_prefix + context.http_request.endpoint.host
50
+ def apply_endpoint_trait(context, trait)
51
+ pattern = trait['hostPrefix']
52
+ return unless pattern
53
+
54
+ host_prefix = pattern.gsub(/\{.+?}/) do |label|
55
+ label = label.delete('{}')
56
+ replace_label_value(label, context.operation.input, context.params)
45
57
  end
58
+ context.http_request.endpoint.host = host_prefix + context.http_request.endpoint.host
46
59
  end
47
60
 
48
- def _replace_label_value(ori, label, input_ref, params)
61
+ def replace_label_value(label, input_ref, params)
49
62
  name = nil
50
63
  input_ref.shape.members.each do |m_name, ref|
51
- if ref['hostLabel'] && ref['hostLabelName'] == label
52
- name = m_name
53
- end
54
- end
55
- if name.nil? || params[name].nil?
56
- raise Errors::MissingEndpointHostLabelValue.new(name)
64
+ name = m_name if ref['hostLabel'] && ref['hostLabelName'] == label
57
65
  end
66
+ raise Errors::MissingEndpointHostLabelValue, name if name.nil? || params[name].nil?
67
+
58
68
  params[name]
59
69
  end
60
-
61
70
  end
62
-
63
71
  end
64
72
  end
65
73
  end
@@ -13,9 +13,6 @@ module Aws
13
13
  option(:sigv4_region)
14
14
  option(:unsigned_operations, default: [])
15
15
 
16
- supported_auth_types = %w[sigv4 bearer sigv4-s3express sigv4a none]
17
- SUPPORTED_AUTH_TYPES = supported_auth_types.freeze
18
-
19
16
  def add_handlers(handlers, cfg)
20
17
  operations = cfg.api.operation_names - cfg.unsigned_operations
21
18
  handlers.add(Handler, step: :sign, operations: operations)
@@ -32,7 +29,7 @@ module Aws
32
29
  }
33
30
  SignatureV4.new(auth_scheme, config, sigv4_overrides)
34
31
  when 'bearer'
35
- Bearer.new
32
+ Bearer.new(config)
36
33
  else
37
34
  NullSigner.new
38
35
  end
@@ -50,11 +47,22 @@ module Aws
50
47
  )
51
48
  signer.sign(context)
52
49
  end
53
- @handler.call(context)
50
+ with_metrics(signer) { @handler.call(context) }
54
51
  end
55
52
 
56
53
  private
57
54
 
55
+ def with_metrics(signer, &block)
56
+ case signer
57
+ when SignatureV4
58
+ Aws::Plugins::UserAgent.metric(*signer.credentials.metrics, &block)
59
+ when Bearer
60
+ Aws::Plugins::UserAgent.metric(*signer.token_provider.metrics, &block)
61
+ else
62
+ block.call
63
+ end
64
+ end
65
+
58
66
  def v2_signing?(config)
59
67
  # 's3' is legacy signing, 'v4' is default
60
68
  config.respond_to?(:signature_version) &&
@@ -64,21 +72,19 @@ module Aws
64
72
 
65
73
  # @api private
66
74
  class Bearer
67
- def initialize
75
+ def initialize(config)
76
+ @token_provider = config.token_provider
68
77
  end
69
78
 
79
+ attr_reader :token_provider
80
+
70
81
  def sign(context)
71
82
  if context.http_request.endpoint.scheme != 'https'
72
- raise ArgumentError,
73
- 'Unable to use bearer authorization on non https endpoint.'
83
+ raise ArgumentError, 'Unable to use bearer authorization on non https endpoint.'
74
84
  end
85
+ raise Errors::MissingBearerTokenError unless @token_provider && @token_provider.set?
75
86
 
76
- token_provider = context.config.token_provider
77
-
78
- raise Errors::MissingBearerTokenError unless token_provider&.set?
79
-
80
- context.http_request.headers['Authorization'] =
81
- "Bearer #{token_provider.token.token}"
87
+ context.http_request.headers['Authorization'] = "Bearer #{@token_provider.token.token}"
82
88
  end
83
89
 
84
90
  def presign_url(*args)
@@ -94,12 +100,9 @@ module Aws
94
100
  class SignatureV4
95
101
  def initialize(auth_scheme, config, sigv4_overrides = {})
96
102
  scheme_name = auth_scheme['name']
97
-
98
103
  unless %w[sigv4 sigv4a sigv4-s3express].include?(scheme_name)
99
- raise ArgumentError,
100
- "Expected sigv4, sigv4a, or sigv4-s3express auth scheme, got #{scheme_name}"
104
+ raise ArgumentError, "Expected sigv4, sigv4a, or sigv4-s3express auth scheme, got #{scheme_name}"
101
105
  end
102
-
103
106
  region = if scheme_name == 'sigv4a'
104
107
  auth_scheme['signingRegionSet'].join(',')
105
108
  else
@@ -111,8 +114,8 @@ module Aws
111
114
  region: sigv4_overrides[:region] || config.sigv4_region || region,
112
115
  credentials_provider: sigv4_overrides[:credentials] || config.credentials,
113
116
  signing_algorithm: scheme_name.to_sym,
114
- uri_escape_path: !!!auth_scheme['disableDoubleEncoding'],
115
- normalize_path: !!!auth_scheme['disableNormalizePath'],
117
+ uri_escape_path: !auth_scheme['disableDoubleEncoding'],
118
+ normalize_path: !auth_scheme['disableNormalizePath'],
116
119
  unsigned_headers: %w[content-length user-agent x-amzn-trace-id expect transfer-encoding connection]
117
120
  )
118
121
  rescue Aws::Sigv4::Errors::MissingCredentialsError
@@ -120,6 +123,8 @@ module Aws
120
123
  end
121
124
  end
122
125
 
126
+ attr_reader :signer
127
+
123
128
  def sign(context)
124
129
  req = context.http_request
125
130
 
@@ -155,6 +160,10 @@ module Aws
155
160
  @signer.sign_event(*args)
156
161
  end
157
162
 
163
+ def credentials
164
+ @signer.credentials_provider
165
+ end
166
+
158
167
  private
159
168
 
160
169
  def apply_authtype(context, req)
@@ -29,6 +29,12 @@ requests are made, and retries are disabled.
29
29
  end
30
30
  end
31
31
 
32
+ option(:token_provider) do |config|
33
+ if config.stub_responses
34
+ StaticTokenProvider.new('stubbed-token')
35
+ end
36
+ end
37
+
32
38
  option(:stubs) { {} }
33
39
  option(:stubs_mutex) { Mutex.new }
34
40
  option(:api_requests) { [] }
@@ -34,7 +34,28 @@ module Aws
34
34
  "FLEXIBLE_CHECKSUMS_REQ_WHEN_SUPPORTED" : "Z",
35
35
  "FLEXIBLE_CHECKSUMS_REQ_WHEN_REQUIRED" : "a",
36
36
  "FLEXIBLE_CHECKSUMS_RES_WHEN_SUPPORTED" : "b",
37
- "FLEXIBLE_CHECKSUMS_RES_WHEN_REQUIRED" : "c"
37
+ "FLEXIBLE_CHECKSUMS_RES_WHEN_REQUIRED" : "c",
38
+ "DDB_MAPPER": "d",
39
+ "CREDENTIALS_CODE" : "e",
40
+ "CREDENTIALS_ENV_VARS" : "g",
41
+ "CREDENTIALS_ENV_VARS_STS_WEB_ID_TOKEN" : "h",
42
+ "CREDENTIALS_STS_ASSUME_ROLE" : "i",
43
+ "CREDENTIALS_STS_ASSUME_ROLE_WEB_ID" : "k",
44
+ "CREDENTIALS_PROFILE" : "n",
45
+ "CREDENTIALS_PROFILE_SOURCE_PROFILE" : "o",
46
+ "CREDENTIALS_PROFILE_NAMED_PROVIDER" : "p",
47
+ "CREDENTIALS_PROFILE_STS_WEB_ID_TOKEN" : "q",
48
+ "CREDENTIALS_PROFILE_SSO" : "r",
49
+ "CREDENTIALS_SSO" : "s",
50
+ "CREDENTIALS_PROFILE_SSO_LEGACY" : "t",
51
+ "CREDENTIALS_SSO_LEGACY" : "u",
52
+ "CREDENTIALS_PROFILE_PROCESS" : "v",
53
+ "CREDENTIALS_PROCESS" : "w",
54
+ "CREDENTIALS_HTTP" : "z",
55
+ "CREDENTIALS_IMDS" : "0",
56
+ "SSO_LOGIN_DEVICE" : "1",
57
+ "SSO_LOGIN_AUTH" : "2",
58
+ "BEARER_SERVICE_ENV_VARS": "3"
38
59
  }
39
60
  METRICS
40
61
 
@@ -196,7 +217,8 @@ variable AWS_SDK_UA_APP_ID or the shared config profile attribute sdk_ua_app_id.
196
217
  end
197
218
  end
198
219
 
199
- handler(Handler, step: :sign, priority: 97)
220
+ # Priority set to 5 in order to add user agent as late as possible after signing
221
+ handler(Handler, step: :sign, priority: 5)
200
222
  end
201
223
  end
202
224
  end
@@ -36,7 +36,7 @@ module Aws
36
36
  @process = process
37
37
  @credentials = credentials_from_process
38
38
  @async_refresh = false
39
-
39
+ @metrics = ['CREDENTIALS_PROCESS']
40
40
  super
41
41
  end
42
42
 
@@ -68,7 +68,7 @@ module Aws
68
68
  def apply_header_map(headers, ref, values)
69
69
  prefix = ref.location_name || ''
70
70
  values.each_pair do |name, value|
71
- headers["#{prefix}#{name}"] = value.to_s
71
+ headers["#{prefix}#{name}"] ||= value.to_s
72
72
  end
73
73
  end
74
74
 
@@ -2,6 +2,7 @@
2
2
 
3
3
  module Aws
4
4
  module RpcV2
5
+ # @api private
5
6
  class ErrorHandler < Aws::ErrorHandler
6
7
 
7
8
  def call(context)
@@ -37,11 +38,14 @@ module Aws
37
38
  end
38
39
 
39
40
  def error_code(data, context)
41
+ # This is not correct per protocol tests. awsQueryError is intended to populate the
42
+ # error code of the error class. The error class should come from __type. Query and
43
+ # query compatible services currently have dynamic errors raised from error codes instead
44
+ # of the modeled error class. However, changing this in this major version would break
45
+ # existing usage.
40
46
  code =
41
47
  if aws_query_error?(context)
42
- query_header = context.http_response.headers['x-amzn-query-error']
43
- error, _type = query_header.split(';') # type not supported
44
- remove_prefix(error, context)
48
+ aws_query_error_code(context)
45
49
  else
46
50
  data['__type']
47
51
  end
@@ -52,6 +56,25 @@ module Aws
52
56
  end
53
57
  end
54
58
 
59
+ def aws_query_error?(context)
60
+ context.config.api.metadata['awsQueryCompatible'] &&
61
+ context.http_response.headers['x-amzn-query-error']
62
+ end
63
+
64
+ def aws_query_error_code(context)
65
+ query_header = context.http_response.headers['x-amzn-query-error']
66
+ error, _type = query_header.split(';') # type not supported
67
+ remove_prefix(error, context)
68
+ end
69
+
70
+ def remove_prefix(error_code, context)
71
+ if (prefix = context.config.api.metadata['errorPrefix'])
72
+ error_code.sub(/^#{prefix}/, '')
73
+ else
74
+ error_code
75
+ end
76
+ end
77
+
55
78
  def parse_error_data(context, body, code)
56
79
  data = EmptyStructure.new
57
80
  if (error_rules = context.operation.errors)
@@ -67,19 +90,6 @@ module Aws
67
90
  end
68
91
  data
69
92
  end
70
-
71
- def aws_query_error?(context)
72
- context.config.api.metadata['awsQueryCompatible'] &&
73
- context.http_response.headers['x-amzn-query-error']
74
- end
75
-
76
- def remove_prefix(error_code, context)
77
- if (prefix = context.config.api.metadata['errorPrefix'])
78
- error_code.sub(/^#{prefix}/, '')
79
- else
80
- error_code
81
- end
82
- end
83
93
  end
84
94
  end
85
95
  end
@@ -85,6 +85,14 @@ module Aws
85
85
  end
86
86
  end
87
87
  end
88
+
89
+ def flattened_list?(shape)
90
+ shape.is_a?(ListShape) && shape.flattened
91
+ end
92
+
93
+ def flattened_map?(shape)
94
+ shape.is_a?(MapShape) && shape.flattened
95
+ end
88
96
  end
89
97
  end
90
98
  end
@@ -138,7 +138,11 @@ module Aws
138
138
  role_session_name: entry['role_session_name']
139
139
  }
140
140
  cfg[:region] = opts[:region] if opts[:region]
141
- AssumeRoleWebIdentityCredentials.new(cfg)
141
+ with_metrics('CREDENTIALS_PROFILE_STS_WEB_ID_TOKEN') do
142
+ creds = AssumeRoleWebIdentityCredentials.new(cfg)
143
+ creds.metrics << 'CREDENTIALS_PROFILE_STS_WEB_ID_TOKEN'
144
+ creds
145
+ end
142
146
  end
143
147
  end
144
148
  end
@@ -199,6 +203,7 @@ module Aws
199
203
  config_reader(
200
204
  :region,
201
205
  :account_id_endpoint_mode,
206
+ :auth_scheme_preference,
202
207
  :sigv4a_signing_region_set,
203
208
  :ca_bundle,
204
209
  :credential_process,
@@ -208,6 +213,7 @@ module Aws
208
213
  :ec2_metadata_service_endpoint,
209
214
  :ec2_metadata_service_endpoint_mode,
210
215
  :ec2_metadata_v1_disabled,
216
+ :disable_host_prefix_injection,
211
217
  :max_attempts,
212
218
  :retry_mode,
213
219
  :adaptive_retry_wait_to_fill,
@@ -255,8 +261,8 @@ module Aws
255
261
  'provide only source_profile or credential_source, not both.'
256
262
  elsif opts[:source_profile]
257
263
  opts[:visited_profiles] ||= Set.new
258
- opts[:credentials] = resolve_source_profile(opts[:source_profile], opts)
259
- if opts[:credentials]
264
+ provider = resolve_source_profile(opts[:source_profile], opts)
265
+ if provider && (opts[:credentials] = provider.credentials)
260
266
  opts[:role_session_name] ||= prof_cfg['role_session_name']
261
267
  opts[:role_session_name] ||= 'default_session'
262
268
  opts[:role_arn] ||= prof_cfg['role_arn']
@@ -265,17 +271,28 @@ module Aws
265
271
  opts[:serial_number] ||= prof_cfg['mfa_serial']
266
272
  opts[:profile] = opts.delete(:source_profile)
267
273
  opts.delete(:visited_profiles)
268
- AssumeRoleCredentials.new(opts)
274
+
275
+ metrics = provider.metrics
276
+ if provider.is_a?(AssumeRoleCredentials)
277
+ opts[:credentials] = provider
278
+ metrics.delete('CREDENTIALS_STS_ASSUME_ROLE')
279
+ else
280
+ metrics << 'CREDENTIALS_PROFILE_SOURCE_PROFILE'
281
+ end
282
+ # Set the original credentials metrics to [] to prevent duplicate metrics during sign plugin
283
+ opts[:credentials].metrics = []
284
+ with_metrics(metrics) do
285
+ creds = AssumeRoleCredentials.new(opts)
286
+ creds.metrics.push(*metrics)
287
+ creds
288
+ end
269
289
  else
270
290
  raise Errors::NoSourceProfileError,
271
291
  "Profile #{profile} has a role_arn, and source_profile, but the"\
272
292
  ' source_profile does not have credentials.'
273
293
  end
274
294
  elsif credential_source
275
- opts[:credentials] = credentials_from_source(
276
- credential_source,
277
- chain_config
278
- )
295
+ opts[:credentials] = credentials_from_source(credential_source, chain_config)
279
296
  if opts[:credentials]
280
297
  opts[:role_session_name] ||= prof_cfg['role_session_name']
281
298
  opts[:role_session_name] ||= 'default_session'
@@ -284,7 +301,16 @@ module Aws
284
301
  opts[:external_id] ||= prof_cfg['external_id']
285
302
  opts[:serial_number] ||= prof_cfg['mfa_serial']
286
303
  opts.delete(:source_profile) # Cleanup
287
- AssumeRoleCredentials.new(opts)
304
+
305
+ metrics = opts[:credentials].metrics
306
+ metrics << 'CREDENTIALS_PROFILE_NAMED_PROVIDER'
307
+ # Set the original credentials metrics to [] to prevent duplicate metrics during sign plugin
308
+ opts[:credentials].metrics = []
309
+ with_metrics(metrics) do
310
+ creds = AssumeRoleCredentials.new(opts)
311
+ creds.metrics.push(*metrics)
312
+ creds
313
+ end
288
314
  else
289
315
  raise Errors::NoSourceCredentials,
290
316
  "Profile #{profile} could not get source credentials from"\
@@ -312,12 +338,24 @@ module Aws
312
338
  elsif profile_config && profile_config['source_profile']
313
339
  opts.delete(:source_profile)
314
340
  assume_role_credentials_from_config(opts.merge(profile: profile))
315
- elsif (provider = assume_role_web_identity_credentials_from_config(opts.merge(profile: profile)))
316
- provider.credentials if provider.credentials.set?
341
+ elsif (provider = assume_role_web_identity_credentials_from_config_with_metrics(opts.merge(profile: profile)))
342
+ provider if provider.credentials.set?
317
343
  elsif (provider = assume_role_process_credentials_from_config(profile))
318
- provider.credentials if provider.credentials.set?
319
- elsif (provider = sso_credentials_from_config(profile: profile))
320
- provider.credentials if provider.credentials.set?
344
+ provider if provider.credentials.set?
345
+ elsif (provider = sso_credentials_from_config_with_metrics(profile))
346
+ provider if provider.credentials.set?
347
+ end
348
+ end
349
+
350
+ def assume_role_web_identity_credentials_from_config_with_metrics(opts)
351
+ with_metrics('CREDENTIALS_PROFILE_SOURCE_PROFILE') do
352
+ assume_role_web_identity_credentials_from_config(opts)
353
+ end
354
+ end
355
+
356
+ def sso_credentials_from_config_with_metrics(profile)
357
+ with_metrics('CREDENTIALS_PROFILE_SOURCE_PROFILE') do
358
+ sso_credentials_from_config(profile: profile)
321
359
  end
322
360
  end
323
361
 
@@ -331,6 +369,15 @@ module Aws
331
369
  )
332
370
  when 'EcsContainer'
333
371
  ECSCredentials.new
372
+ when 'Environment'
373
+ creds = Credentials.new(
374
+ ENV['AWS_ACCESS_KEY_ID'],
375
+ ENV['AWS_SECRET_ACCESS_KEY'],
376
+ ENV['AWS_SESSION_TOKEN'],
377
+ account_id: ENV['AWS_ACCOUNT_ID']
378
+ )
379
+ creds.metrics = ['CREDENTIALS_ENV_VARS']
380
+ creds
334
381
  else
335
382
  raise Errors::InvalidCredentialSourceError, "Unsupported credential_source: #{credential_source}"
336
383
  end
@@ -342,7 +389,11 @@ module Aws
342
389
  if @parsed_config
343
390
  credential_process ||= @parsed_config.fetch(profile, {})['credential_process']
344
391
  end
345
- ProcessCredentials.new([credential_process]) if credential_process
392
+ if credential_process
393
+ creds = ProcessCredentials.new([credential_process])
394
+ creds.metrics << 'CREDENTIALS_PROFILE_PROCESS'
395
+ creds
396
+ end
346
397
  end
347
398
 
348
399
  def credentials_from_shared(profile, _opts)
@@ -386,13 +437,18 @@ module Aws
386
437
  sso_start_url = prof_config['sso_start_url']
387
438
  end
388
439
 
389
- SSOCredentials.new(
390
- sso_account_id: prof_config['sso_account_id'],
391
- sso_role_name: prof_config['sso_role_name'],
392
- sso_session: prof_config['sso_session'],
393
- sso_region: sso_region,
394
- sso_start_url: sso_start_url
440
+ metric = prof_config['sso_session'] ? 'CREDENTIALS_PROFILE_SSO' : 'CREDENTIALS_PROFILE_SSO_LEGACY'
441
+ with_metrics(metric) do
442
+ creds = SSOCredentials.new(
443
+ sso_account_id: prof_config['sso_account_id'],
444
+ sso_role_name: prof_config['sso_role_name'],
445
+ sso_session: prof_config['sso_session'],
446
+ sso_region: sso_region,
447
+ sso_start_url: sso_start_url
395
448
  )
449
+ creds.metrics << metric
450
+ creds
451
+ end
396
452
  end
397
453
  end
398
454
 
@@ -420,6 +476,7 @@ module Aws
420
476
  prof_config['aws_session_token'],
421
477
  account_id: prof_config['aws_account_id']
422
478
  )
479
+ creds.metrics = ['CREDENTIALS_PROFILE']
423
480
  creds if creds.set?
424
481
  end
425
482
 
@@ -480,5 +537,9 @@ module Aws
480
537
 
481
538
  sso_session
482
539
  end
540
+
541
+ def with_metrics(metrics, &block)
542
+ Aws::Plugins::UserAgent.metric(*metrics, &block)
543
+ end
483
544
  end
484
545
  end
@@ -40,6 +40,7 @@ module Aws
40
40
  )
41
41
  @credentials = config.credentials(profile: @profile_name)
42
42
  end
43
+ @metrics = ['CREDENTIALS_CODE']
43
44
  end
44
45
 
45
46
  # @return [String]
@@ -91,6 +91,7 @@ module Aws
91
91
  client_opts[:credentials] = nil
92
92
  @client = Aws::SSO::Client.new(client_opts)
93
93
  end
94
+ @metrics = ['CREDENTIALS_SSO']
94
95
  else # legacy behavior
95
96
  missing_keys = LEGACY_REQUIRED_OPTS.select { |k| options[k].nil? }
96
97
  unless missing_keys.empty?
@@ -111,6 +112,7 @@ module Aws
111
112
  client_opts[:credentials] = nil
112
113
 
113
114
  @client = options[:client] || Aws::SSO::Client.new(client_opts)
115
+ @metrics = ['CREDENTIALS_SSO_LEGACY']
114
116
  end
115
117
 
116
118
  @async_refresh = true
@@ -2,12 +2,11 @@
2
2
 
3
3
  module Aws
4
4
  class StaticTokenProvider
5
-
6
5
  include TokenProvider
7
6
 
8
7
  # @param [String] token
9
8
  # @param [Time] expiration
10
- def initialize(token, expiration=nil)
9
+ def initialize(token, expiration = nil)
11
10
  @token = Token.new(token, expiration)
12
11
  end
13
12
  end
@@ -3,9 +3,9 @@
3
3
  module Aws
4
4
  class Token
5
5
 
6
- # @param [String] token
7
- # @param [Time] expiration
8
- def initialize(token, expiration=nil)
6
+ # @param [String, nil] token
7
+ # @param [Time, nil] expiration
8
+ def initialize(token, expiration = nil)
9
9
  @token = token
10
10
  @expiration = expiration
11
11
  end
@@ -6,6 +6,10 @@ module Aws
6
6
  # @return [Token]
7
7
  attr_reader :token
8
8
 
9
+ # @api private
10
+ # Returns UserAgent metrics for tokens.
11
+ attr_accessor :metrics
12
+
9
13
  # @return [Boolean]
10
14
  def set?
11
15
  !!token && token.set?
@@ -27,17 +27,13 @@ module Aws
27
27
 
28
28
  def static_profile_sso_token(options)
29
29
  if Aws.shared_config.config_enabled? && options[:config] && options[:config].profile
30
- Aws.shared_config.sso_token_from_config(
31
- profile: options[:config].profile
32
- )
30
+ Aws.shared_config.sso_token_from_config(profile: options[:config].profile)
33
31
  end
34
32
  end
35
33
 
36
-
37
34
  def sso_token(options)
38
- profile_name = determine_profile_name(options)
39
35
  if Aws.shared_config.config_enabled?
40
- Aws.shared_config.sso_token_from_config(profile: profile_name)
36
+ Aws.shared_config.sso_token_from_config(profile: determine_profile_name(options))
41
37
  end
42
38
  rescue Errors::NoSuchProfileError
43
39
  nil
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'cgi'
3
+ require "cgi/escape"
4
+ require "cgi/util" if RUBY_VERSION < "3.5"
4
5
 
5
6
  module Aws
6
7
  # @api private
@@ -1,9 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'cgi'
3
+ require "cgi/escape"
4
+ require "cgi/util" if RUBY_VERSION < "3.5"
4
5
 
5
6
  module Aws
6
7
  module Xml
8
+ # @api private
7
9
  class ErrorHandler < Aws::ErrorHandler
8
10
 
9
11
  def call(context)