aws-sdk-core 3.209.1 → 3.240.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 (112) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +331 -0
  3. data/VERSION +1 -1
  4. data/lib/aws-sdk-core/arn.rb +1 -3
  5. data/lib/aws-sdk-core/assume_role_credentials.rb +9 -8
  6. data/lib/aws-sdk-core/assume_role_web_identity_credentials.rb +3 -2
  7. data/lib/aws-sdk-core/cbor/decoder.rb +0 -2
  8. data/lib/aws-sdk-core/cbor/encoder.rb +2 -2
  9. data/lib/aws-sdk-core/cbor.rb +3 -56
  10. data/lib/aws-sdk-core/client_stubs.rb +35 -55
  11. data/lib/aws-sdk-core/credential_provider.rb +4 -0
  12. data/lib/aws-sdk-core/credential_provider_chain.rb +91 -22
  13. data/lib/aws-sdk-core/credentials.rb +6 -0
  14. data/lib/aws-sdk-core/ecs_credentials.rb +14 -13
  15. data/lib/aws-sdk-core/endpoints/matchers.rb +3 -9
  16. data/lib/aws-sdk-core/endpoints.rb +37 -13
  17. data/lib/aws-sdk-core/error_handler.rb +5 -0
  18. data/lib/aws-sdk-core/errors.rb +5 -2
  19. data/lib/aws-sdk-core/event_emitter.rb +1 -1
  20. data/lib/aws-sdk-core/instance_profile_credentials.rb +147 -157
  21. data/lib/aws-sdk-core/json/error_handler.rb +14 -3
  22. data/lib/aws-sdk-core/json/handler.rb +1 -0
  23. data/lib/aws-sdk-core/log/param_formatter.rb +7 -3
  24. data/lib/aws-sdk-core/login_credentials.rb +229 -0
  25. data/lib/aws-sdk-core/plugins/checksum_algorithm.rb +347 -171
  26. data/lib/aws-sdk-core/plugins/client_metrics_plugin.rb +0 -1
  27. data/lib/aws-sdk-core/plugins/credentials_configuration.rb +75 -59
  28. data/lib/aws-sdk-core/plugins/endpoint_pattern.rb +40 -32
  29. data/lib/aws-sdk-core/plugins/http_checksum.rb +2 -8
  30. data/lib/aws-sdk-core/plugins/regional_endpoint.rb +44 -25
  31. data/lib/aws-sdk-core/plugins/sign.rb +30 -21
  32. data/lib/aws-sdk-core/plugins/stub_responses.rb +30 -8
  33. data/lib/aws-sdk-core/plugins/user_agent.rb +35 -2
  34. data/lib/aws-sdk-core/process_credentials.rb +1 -1
  35. data/lib/aws-sdk-core/refreshing_credentials.rb +8 -11
  36. data/lib/aws-sdk-core/rest/request/headers.rb +3 -3
  37. data/lib/aws-sdk-core/rpc_v2/builder.rb +1 -1
  38. data/lib/aws-sdk-core/{cbor → rpc_v2}/cbor_engine.rb +4 -5
  39. data/lib/aws-sdk-core/rpc_v2/content_type_handler.rb +3 -1
  40. data/lib/aws-sdk-core/rpc_v2/error_handler.rb +27 -16
  41. data/lib/aws-sdk-core/rpc_v2/handler.rb +2 -1
  42. data/lib/aws-sdk-core/rpc_v2/parser.rb +9 -1
  43. data/lib/aws-sdk-core/rpc_v2.rb +65 -2
  44. data/lib/aws-sdk-core/shared_config.rb +104 -21
  45. data/lib/aws-sdk-core/shared_credentials.rb +1 -0
  46. data/lib/aws-sdk-core/sso_credentials.rb +3 -1
  47. data/lib/aws-sdk-core/static_token_provider.rb +1 -2
  48. data/lib/aws-sdk-core/stubbing/protocols/ec2.rb +12 -11
  49. data/lib/aws-sdk-core/stubbing/protocols/json.rb +11 -10
  50. data/lib/aws-sdk-core/stubbing/protocols/query.rb +7 -6
  51. data/lib/aws-sdk-core/stubbing/protocols/rest.rb +2 -1
  52. data/lib/aws-sdk-core/stubbing/protocols/rest_json.rb +9 -8
  53. data/lib/aws-sdk-core/stubbing/protocols/rest_xml.rb +6 -5
  54. data/lib/aws-sdk-core/stubbing/protocols/rpc_v2.rb +13 -15
  55. data/lib/aws-sdk-core/stubbing.rb +2 -2
  56. data/lib/aws-sdk-core/token.rb +3 -3
  57. data/lib/aws-sdk-core/token_provider.rb +4 -0
  58. data/lib/aws-sdk-core/token_provider_chain.rb +2 -6
  59. data/lib/aws-sdk-core/util.rb +2 -1
  60. data/lib/aws-sdk-core/xml/error_handler.rb +3 -1
  61. data/lib/aws-sdk-core.rb +4 -0
  62. data/lib/aws-sdk-signin/client.rb +604 -0
  63. data/lib/aws-sdk-signin/client_api.rb +119 -0
  64. data/lib/aws-sdk-signin/customizations.rb +1 -0
  65. data/lib/aws-sdk-signin/endpoint_parameters.rb +69 -0
  66. data/lib/aws-sdk-signin/endpoint_provider.rb +59 -0
  67. data/lib/aws-sdk-signin/endpoints.rb +20 -0
  68. data/lib/aws-sdk-signin/errors.rb +122 -0
  69. data/lib/aws-sdk-signin/plugins/endpoints.rb +77 -0
  70. data/lib/aws-sdk-signin/resource.rb +26 -0
  71. data/lib/aws-sdk-signin/types.rb +299 -0
  72. data/lib/aws-sdk-signin.rb +63 -0
  73. data/lib/aws-sdk-sso/client.rb +76 -47
  74. data/lib/aws-sdk-sso/endpoint_parameters.rb +13 -10
  75. data/lib/aws-sdk-sso/endpoint_provider.rb +16 -20
  76. data/lib/aws-sdk-sso/endpoints.rb +2 -42
  77. data/lib/aws-sdk-sso/plugins/endpoints.rb +1 -14
  78. data/lib/aws-sdk-sso.rb +1 -1
  79. data/lib/aws-sdk-ssooidc/client.rb +132 -73
  80. data/lib/aws-sdk-ssooidc/client_api.rb +11 -0
  81. data/lib/aws-sdk-ssooidc/endpoint_parameters.rb +13 -10
  82. data/lib/aws-sdk-ssooidc/endpoint_provider.rb +14 -18
  83. data/lib/aws-sdk-ssooidc/endpoints.rb +2 -42
  84. data/lib/aws-sdk-ssooidc/errors.rb +10 -0
  85. data/lib/aws-sdk-ssooidc/plugins/endpoints.rb +1 -14
  86. data/lib/aws-sdk-ssooidc/types.rb +65 -21
  87. data/lib/aws-sdk-ssooidc.rb +1 -1
  88. data/lib/aws-sdk-sts/client.rb +416 -107
  89. data/lib/aws-sdk-sts/client_api.rb +105 -8
  90. data/lib/aws-sdk-sts/customizations.rb +0 -1
  91. data/lib/aws-sdk-sts/endpoint_parameters.rb +15 -14
  92. data/lib/aws-sdk-sts/endpoint_provider.rb +50 -55
  93. data/lib/aws-sdk-sts/endpoints.rb +2 -94
  94. data/lib/aws-sdk-sts/errors.rb +79 -0
  95. data/lib/aws-sdk-sts/plugins/endpoints.rb +1 -22
  96. data/lib/aws-sdk-sts/presigner.rb +2 -6
  97. data/lib/aws-sdk-sts/types.rb +343 -32
  98. data/lib/aws-sdk-sts.rb +1 -1
  99. data/lib/seahorse/client/async_base.rb +4 -5
  100. data/lib/seahorse/client/base.rb +0 -14
  101. data/lib/seahorse/client/h2/connection.rb +18 -28
  102. data/lib/seahorse/client/h2/handler.rb +6 -1
  103. data/lib/seahorse/client/http/response.rb +1 -1
  104. data/lib/seahorse/client/net_http/connection_pool.rb +4 -1
  105. data/lib/seahorse/client/networking_error.rb +1 -1
  106. data/lib/seahorse/client/plugins/h2.rb +4 -4
  107. data/lib/seahorse/client/request_context.rb +2 -2
  108. data/lib/seahorse/client/response.rb +2 -0
  109. data/lib/seahorse/util.rb +2 -1
  110. data/sig/aws-sdk-core/async_client_stubs.rbs +21 -0
  111. data/sig/seahorse/client/async_base.rbs +18 -0
  112. metadata +69 -17
@@ -1,28 +1,26 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Aws
4
-
5
4
  # Base class used credential classes that can be refreshed. This
6
5
  # provides basic refresh logic in a thread-safe manner. Classes mixing in
7
- # this module are expected to implement a #refresh method that populates
6
+ # this module are expected to implement a `#refresh` method that populates
8
7
  # the following instance variables:
9
8
  #
10
- # * `@access_key_id`
11
- # * `@secret_access_key`
12
- # * `@session_token`
13
- # * `@expiration`
9
+ # * `@credentials` ({Credentials})
10
+ # * `@expiration` (Time)
14
11
  #
15
- # @api private
16
12
  module RefreshingCredentials
17
-
18
13
  SYNC_EXPIRATION_LENGTH = 300 # 5 minutes
19
14
  ASYNC_EXPIRATION_LENGTH = 600 # 10 minutes
20
15
 
21
16
  CLIENT_EXCLUDE_OPTIONS = Set.new([:before_refresh]).freeze
22
17
 
18
+ # @param [Hash] options
19
+ # @option options [Proc] :before_refresh A Proc called before credentials are refreshed.
20
+ # It accepts `self` as the only argument.
23
21
  def initialize(options = {})
24
22
  @mutex = Mutex.new
25
- @before_refresh = options.delete(:before_refresh) if Hash === options
23
+ @before_refresh = options.delete(:before_refresh) if options.is_a?(Hash)
26
24
 
27
25
  @before_refresh.call(self) if @before_refresh
28
26
  refresh
@@ -59,7 +57,7 @@ module Aws
59
57
  # Otherwise, if we're approaching expiration, use the existing credentials
60
58
  # but attempt a refresh in the background.
61
59
  def refresh_if_near_expiration!
62
- # Note: This check is an optimization. Rather than acquire the mutex on every #refresh_if_near_expiration
60
+ # NOTE: This check is an optimization. Rather than acquire the mutex on every #refresh_if_near_expiration
63
61
  # call, we check before doing so, and then we check within the mutex to avoid a race condition.
64
62
  # See issue: https://github.com/aws/aws-sdk-ruby/issues/2641 for more info.
65
63
  if near_expiration?(sync_expiration_length)
@@ -91,6 +89,5 @@ module Aws
91
89
  true
92
90
  end
93
91
  end
94
-
95
92
  end
96
93
  end
@@ -20,7 +20,7 @@ module Aws
20
20
  def apply(http_req, params)
21
21
  @rules.shape.members.each do |name, ref|
22
22
  value = params[name]
23
- next if value.nil? || ((ref.shape).is_a?(StringShape) && value.empty?)
23
+ next if value.nil?
24
24
 
25
25
  case ref.location
26
26
  when 'header' then apply_header_value(http_req.headers, ref, value)
@@ -51,7 +51,7 @@ module Aws
51
51
  end
52
52
 
53
53
  def list(headers, ref, values)
54
- return if !values || values.empty?
54
+ return if values.nil?
55
55
 
56
56
  member_ref = ref.shape.member
57
57
  values = values.collect do |value|
@@ -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
 
@@ -16,7 +16,7 @@ module Aws
16
16
  # different than if the input shape is a structure with no members.
17
17
  return nil if @rules.shape.struct_class == EmptyStructure
18
18
 
19
- Cbor.encode(format(@rules, params))
19
+ RpcV2.encode(format(@rules, params))
20
20
  end
21
21
 
22
22
  private
@@ -1,18 +1,17 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative 'encoder'
4
- require_relative 'decoder'
3
+ require_relative '../cbor'
5
4
 
6
5
  module Aws
7
- module Cbor
6
+ module RpcV2
8
7
  # Pure Ruby implementation of CBOR encode and decode
9
8
  module CborEngine
10
9
  def self.encode(data)
11
- Encoder.new.add(data).bytes
10
+ Cbor::Encoder.new.add(data).bytes
12
11
  end
13
12
 
14
13
  def self.decode(bytes)
15
- Decoder.new(bytes.force_encoding(Encoding::BINARY)).decode
14
+ Cbor::Decoder.new(bytes.force_encoding(Encoding::BINARY)).decode
16
15
  end
17
16
  end
18
17
  end
@@ -13,11 +13,13 @@ module Aws
13
13
  accept =
14
14
  if eventstream_output?(context)
15
15
  'application/vnd.amazon.eventstream'
16
+ else
17
+ 'application/cbor'
16
18
  end
17
19
 
18
20
  headers = context.http_request.headers
19
21
  headers['Content-Type'] ||= content_type if content_type
20
- headers['Accept'] ||= accept if accept
22
+ headers['Accept'] ||= accept
21
23
  @handler.call(context)
22
24
  end
23
25
 
@@ -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)
@@ -27,7 +28,7 @@ module Aws
27
28
  end
28
29
 
29
30
  def extract_error(body, context)
30
- data = Cbor.decode(body)
31
+ data = RpcV2.decode(body)
31
32
  code = error_code(data, context)
32
33
  message = data['message']
33
34
  data = parse_error_data(context, body, code)
@@ -37,10 +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
- error = context.http_response.headers['x-amzn-query-error'].split(';')[0]
43
- remove_prefix(error, context)
48
+ aws_query_error_code(context)
44
49
  else
45
50
  data['__type']
46
51
  end
@@ -51,6 +56,25 @@ module Aws
51
56
  end
52
57
  end
53
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
+
54
78
  def parse_error_data(context, body, code)
55
79
  data = EmptyStructure.new
56
80
  if (error_rules = context.operation.errors)
@@ -66,19 +90,6 @@ module Aws
66
90
  end
67
91
  data
68
92
  end
69
-
70
- def aws_query_error?(context)
71
- context.config.api.metadata['awsQueryCompatible'] &&
72
- context.http_response.headers['x-amzn-query-error']
73
- end
74
-
75
- def remove_prefix(error_code, context)
76
- if (prefix = context.config.api.metadata['errorPrefix'])
77
- error_code.sub(/^#{prefix}/, '')
78
- else
79
- error_code
80
- end
81
- end
82
93
  end
83
94
  end
84
95
  end
@@ -20,7 +20,8 @@ module Aws
20
20
  end
21
21
 
22
22
  def build_request(context)
23
- context.http_request.headers['smithy-protocol'] = 'rpc-v2-cbor'
23
+ context.http_request.headers['Smithy-Protocol'] = 'rpc-v2-cbor'
24
+ context.http_request.headers['X-Amzn-Query-Mode'] = 'true' if query_compatible?(context)
24
25
  context.http_request.http_method = 'POST'
25
26
  context.http_request.body = build_body(context)
26
27
  build_url(context)
@@ -16,7 +16,7 @@ module Aws
16
16
  def parse(cbor, target = nil)
17
17
  return {} if cbor.empty?
18
18
 
19
- parse_ref(@rules, Cbor.decode(cbor), target)
19
+ parse_ref(@rules, RpcV2.decode(cbor), target)
20
20
  end
21
21
 
22
22
  private
@@ -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
@@ -1,6 +1,69 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative 'cbor'
2
- require_relative 'rpc_v2/handler'
4
+ require_relative 'rpc_v2/builder'
3
5
  require_relative 'rpc_v2/content_type_handler'
4
6
  require_relative 'rpc_v2/error_handler'
5
- require_relative 'rpc_v2/builder'
7
+ require_relative 'rpc_v2/handler'
6
8
  require_relative 'rpc_v2/parser'
9
+
10
+ module Aws
11
+ # @api private
12
+ module RpcV2
13
+ class << self
14
+ # @param [Symbol,Class] engine
15
+ # Must be one of the following values:
16
+ #
17
+ # * :cbor
18
+ #
19
+ def engine=(engine)
20
+ @engine = Class === engine ? engine : load_engine(engine)
21
+ end
22
+
23
+ # @return [Class] Returns the default engine.
24
+ # One of:
25
+ #
26
+ # * {CborEngine}
27
+ #
28
+ def engine
29
+ set_default_engine unless @engine
30
+ @engine
31
+ end
32
+
33
+ def encode(data)
34
+ @engine.encode(data)
35
+ end
36
+
37
+ def decode(bytes)
38
+ bytes.force_encoding(Encoding::BINARY)
39
+ @engine.decode(bytes)
40
+ end
41
+
42
+ def set_default_engine
43
+ [:cbor].each do |name|
44
+ @engine ||= try_load_engine(name)
45
+ end
46
+
47
+ unless @engine
48
+ raise 'Unable to find a compatible cbor library.'
49
+ end
50
+ end
51
+
52
+ private
53
+
54
+ def load_engine(name)
55
+ require "aws-sdk-core/rpc_v2/#{name}_engine"
56
+ const_name = name[0].upcase + name[1..-1] + 'Engine'
57
+ const_get(const_name)
58
+ end
59
+
60
+ def try_load_engine(name)
61
+ load_engine(name)
62
+ rescue LoadError
63
+ false
64
+ end
65
+ end
66
+
67
+ set_default_engine
68
+ end
69
+ 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
@@ -167,6 +171,16 @@ module Aws
167
171
  token
168
172
  end
169
173
 
174
+ # Attempts to load from shared config or shared credentials file.
175
+ # Will always attempt first to load from the shared credentials
176
+ # file, if present.
177
+ def login_credentials_from_config(opts = {})
178
+ p = opts[:profile] || @profile_name
179
+ credentials = login_credentials_from_profile(@parsed_credentials, p, opts[:region])
180
+ credentials ||= login_credentials_from_profile(@parsed_config, p, opts[:region]) if @parsed_config
181
+ credentials
182
+ end
183
+
170
184
  # Source a custom configured endpoint from the shared configuration file
171
185
  #
172
186
  # @param [Hash] opts
@@ -199,6 +213,7 @@ module Aws
199
213
  config_reader(
200
214
  :region,
201
215
  :account_id_endpoint_mode,
216
+ :auth_scheme_preference,
202
217
  :sigv4a_signing_region_set,
203
218
  :ca_bundle,
204
219
  :credential_process,
@@ -208,10 +223,13 @@ module Aws
208
223
  :ec2_metadata_service_endpoint,
209
224
  :ec2_metadata_service_endpoint_mode,
210
225
  :ec2_metadata_v1_disabled,
226
+ :disable_host_prefix_injection,
211
227
  :max_attempts,
212
228
  :retry_mode,
213
229
  :adaptive_retry_wait_to_fill,
214
230
  :correct_clock_skew,
231
+ :request_checksum_calculation,
232
+ :response_checksum_validation,
215
233
  :csm_client_id,
216
234
  :csm_enabled,
217
235
  :csm_host,
@@ -253,8 +271,8 @@ module Aws
253
271
  'provide only source_profile or credential_source, not both.'
254
272
  elsif opts[:source_profile]
255
273
  opts[:visited_profiles] ||= Set.new
256
- opts[:credentials] = resolve_source_profile(opts[:source_profile], opts)
257
- if opts[:credentials]
274
+ provider = resolve_source_profile(opts[:source_profile], opts)
275
+ if provider && (opts[:credentials] = provider.credentials)
258
276
  opts[:role_session_name] ||= prof_cfg['role_session_name']
259
277
  opts[:role_session_name] ||= 'default_session'
260
278
  opts[:role_arn] ||= prof_cfg['role_arn']
@@ -263,17 +281,28 @@ module Aws
263
281
  opts[:serial_number] ||= prof_cfg['mfa_serial']
264
282
  opts[:profile] = opts.delete(:source_profile)
265
283
  opts.delete(:visited_profiles)
266
- AssumeRoleCredentials.new(opts)
284
+
285
+ metrics = provider.metrics
286
+ if provider.is_a?(AssumeRoleCredentials)
287
+ opts[:credentials] = provider
288
+ metrics.delete('CREDENTIALS_STS_ASSUME_ROLE')
289
+ else
290
+ metrics << 'CREDENTIALS_PROFILE_SOURCE_PROFILE'
291
+ end
292
+ # Set the original credentials metrics to [] to prevent duplicate metrics during sign plugin
293
+ opts[:credentials].metrics = []
294
+ with_metrics(metrics) do
295
+ creds = AssumeRoleCredentials.new(opts)
296
+ creds.metrics.push(*metrics)
297
+ creds
298
+ end
267
299
  else
268
300
  raise Errors::NoSourceProfileError,
269
301
  "Profile #{profile} has a role_arn, and source_profile, but the"\
270
302
  ' source_profile does not have credentials.'
271
303
  end
272
304
  elsif credential_source
273
- opts[:credentials] = credentials_from_source(
274
- credential_source,
275
- chain_config
276
- )
305
+ opts[:credentials] = credentials_from_source(credential_source, chain_config)
277
306
  if opts[:credentials]
278
307
  opts[:role_session_name] ||= prof_cfg['role_session_name']
279
308
  opts[:role_session_name] ||= 'default_session'
@@ -282,7 +311,16 @@ module Aws
282
311
  opts[:external_id] ||= prof_cfg['external_id']
283
312
  opts[:serial_number] ||= prof_cfg['mfa_serial']
284
313
  opts.delete(:source_profile) # Cleanup
285
- AssumeRoleCredentials.new(opts)
314
+
315
+ metrics = opts[:credentials].metrics
316
+ metrics << 'CREDENTIALS_PROFILE_NAMED_PROVIDER'
317
+ # Set the original credentials metrics to [] to prevent duplicate metrics during sign plugin
318
+ opts[:credentials].metrics = []
319
+ with_metrics(metrics) do
320
+ creds = AssumeRoleCredentials.new(opts)
321
+ creds.metrics.push(*metrics)
322
+ creds
323
+ end
286
324
  else
287
325
  raise Errors::NoSourceCredentials,
288
326
  "Profile #{profile} could not get source credentials from"\
@@ -310,12 +348,24 @@ module Aws
310
348
  elsif profile_config && profile_config['source_profile']
311
349
  opts.delete(:source_profile)
312
350
  assume_role_credentials_from_config(opts.merge(profile: profile))
313
- elsif (provider = assume_role_web_identity_credentials_from_config(opts.merge(profile: profile)))
314
- provider.credentials if provider.credentials.set?
351
+ elsif (provider = assume_role_web_identity_credentials_from_config_with_metrics(opts.merge(profile: profile)))
352
+ provider if provider.credentials.set?
315
353
  elsif (provider = assume_role_process_credentials_from_config(profile))
316
- provider.credentials if provider.credentials.set?
317
- elsif (provider = sso_credentials_from_config(profile: profile))
318
- provider.credentials if provider.credentials.set?
354
+ provider if provider.credentials.set?
355
+ elsif (provider = sso_credentials_from_config_with_metrics(profile))
356
+ provider if provider.credentials.set?
357
+ end
358
+ end
359
+
360
+ def assume_role_web_identity_credentials_from_config_with_metrics(opts)
361
+ with_metrics('CREDENTIALS_PROFILE_SOURCE_PROFILE') do
362
+ assume_role_web_identity_credentials_from_config(opts)
363
+ end
364
+ end
365
+
366
+ def sso_credentials_from_config_with_metrics(profile)
367
+ with_metrics('CREDENTIALS_PROFILE_SOURCE_PROFILE') do
368
+ sso_credentials_from_config(profile: profile)
319
369
  end
320
370
  end
321
371
 
@@ -329,6 +379,15 @@ module Aws
329
379
  )
330
380
  when 'EcsContainer'
331
381
  ECSCredentials.new
382
+ when 'Environment'
383
+ creds = Credentials.new(
384
+ ENV['AWS_ACCESS_KEY_ID'],
385
+ ENV['AWS_SECRET_ACCESS_KEY'],
386
+ ENV['AWS_SESSION_TOKEN'],
387
+ account_id: ENV['AWS_ACCOUNT_ID']
388
+ )
389
+ creds.metrics = ['CREDENTIALS_ENV_VARS']
390
+ creds
332
391
  else
333
392
  raise Errors::InvalidCredentialSourceError, "Unsupported credential_source: #{credential_source}"
334
393
  end
@@ -340,7 +399,11 @@ module Aws
340
399
  if @parsed_config
341
400
  credential_process ||= @parsed_config.fetch(profile, {})['credential_process']
342
401
  end
343
- ProcessCredentials.new([credential_process]) if credential_process
402
+ if credential_process
403
+ creds = ProcessCredentials.new([credential_process])
404
+ creds.metrics << 'CREDENTIALS_PROFILE_PROCESS'
405
+ creds
406
+ end
344
407
  end
345
408
 
346
409
  def credentials_from_shared(profile, _opts)
@@ -384,13 +447,18 @@ module Aws
384
447
  sso_start_url = prof_config['sso_start_url']
385
448
  end
386
449
 
387
- SSOCredentials.new(
388
- sso_account_id: prof_config['sso_account_id'],
389
- sso_role_name: prof_config['sso_role_name'],
390
- sso_session: prof_config['sso_session'],
391
- sso_region: sso_region,
392
- sso_start_url: sso_start_url
450
+ metric = prof_config['sso_session'] ? 'CREDENTIALS_PROFILE_SSO' : 'CREDENTIALS_PROFILE_SSO_LEGACY'
451
+ with_metrics(metric) do
452
+ creds = SSOCredentials.new(
453
+ sso_account_id: prof_config['sso_account_id'],
454
+ sso_role_name: prof_config['sso_role_name'],
455
+ sso_session: prof_config['sso_session'],
456
+ sso_region: sso_region,
457
+ sso_start_url: sso_start_url
393
458
  )
459
+ creds.metrics << metric
460
+ creds
461
+ end
394
462
  end
395
463
  end
396
464
 
@@ -411,6 +479,16 @@ module Aws
411
479
  end
412
480
  end
413
481
 
482
+ def login_credentials_from_profile(cfg, profile, region)
483
+ return unless @parsed_config && (prof_config = cfg[profile]) && prof_config['login_session']
484
+
485
+ cfg = { login_session: prof_config['login_session'] }
486
+ cfg[:region] = region if region
487
+ creds = LoginCredentials.new(cfg)
488
+ creds.metrics << 'CREDENTIALS_PROFILE_LOGIN'
489
+ creds
490
+ end
491
+
414
492
  def credentials_from_profile(prof_config)
415
493
  creds = Credentials.new(
416
494
  prof_config['aws_access_key_id'],
@@ -418,6 +496,7 @@ module Aws
418
496
  prof_config['aws_session_token'],
419
497
  account_id: prof_config['aws_account_id']
420
498
  )
499
+ creds.metrics = ['CREDENTIALS_PROFILE']
421
500
  creds if creds.set?
422
501
  end
423
502
 
@@ -478,5 +557,9 @@ module Aws
478
557
 
479
558
  sso_session
480
559
  end
560
+
561
+ def with_metrics(metrics, &block)
562
+ Aws::Plugins::UserAgent.metric(*metrics, &block)
563
+ end
481
564
  end
482
565
  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]
@@ -7,7 +7,7 @@ module Aws
7
7
  # {Aws::SSOTokenProvider} will be used to refresh the token if possible.
8
8
  # This class does NOT implement the SSO login token flow - tokens
9
9
  # must generated separately by running `aws login` from the
10
- # AWS CLI with the correct profile. The `SSOCredentials` will
10
+ # AWS CLI with the correct profile. The {SSOCredentials} will
11
11
  # auto-refresh the AWS credentials from SSO.
12
12
  #
13
13
  # # You must first run aws sso login --profile your-sso-profile
@@ -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,6 +3,7 @@
3
3
  module Aws
4
4
  module Stubbing
5
5
  module Protocols
6
+ # @api private
6
7
  class EC2
7
8
 
8
9
  def stub_data(api, operation, data)
@@ -16,17 +17,17 @@ module Aws
16
17
  end
17
18
 
18
19
  def stub_error(error_code)
19
- http_resp = Seahorse::Client::Http::Response.new
20
- http_resp.status_code = 400
21
- http_resp.body = <<-XML.strip
22
- <ErrorResponse>
23
- <Error>
24
- <Code>#{error_code}</Code>
25
- <Message>stubbed-response-error-message</Message>
26
- </Error>
27
- </ErrorResponse>
20
+ resp = Seahorse::Client::Http::Response.new
21
+ resp.status_code = 400
22
+ resp.body = <<~XML.strip
23
+ <ErrorResponse>
24
+ <Error>
25
+ <Code>#{error_code}</Code>
26
+ <Message>stubbed-response-error-message</Message>
27
+ </Error>
28
+ </ErrorResponse>
28
29
  XML
29
- http_resp
30
+ resp
30
31
  end
31
32
 
32
33
  private
@@ -37,7 +38,7 @@ module Aws
37
38
  xml.shift
38
39
  xml.pop
39
40
  xmlns = "http://ec2.amazonaws.com/doc/#{api.version}/".inspect
40
- xml.unshift(" <requestId>stubbed-request-id</requestId>")
41
+ xml.unshift(' <requestId>stubbed-request-id</requestId>')
41
42
  xml.unshift("<#{operation.name}Response xmlns=#{xmlns}>\n")
42
43
  xml.push("</#{operation.name}Response>\n")
43
44
  xml.join
@@ -3,27 +3,28 @@
3
3
  module Aws
4
4
  module Stubbing
5
5
  module Protocols
6
+ # @api private
6
7
  class Json
7
8
 
8
9
  def stub_data(api, operation, data)
9
10
  resp = Seahorse::Client::Http::Response.new
10
11
  resp.status_code = 200
11
- resp.headers["Content-Type"] = content_type(api)
12
- resp.headers["x-amzn-RequestId"] = "stubbed-request-id"
12
+ resp.headers['Content-Type'] = content_type(api)
13
+ resp.headers['x-amzn-RequestId'] = 'stubbed-request-id'
13
14
  resp.body = build_body(operation, data)
14
15
  resp
15
16
  end
16
17
 
17
18
  def stub_error(error_code)
18
- http_resp = Seahorse::Client::Http::Response.new
19
- http_resp.status_code = 400
20
- http_resp.body = <<-JSON.strip
21
- {
22
- "code": #{error_code.inspect},
23
- "message": "stubbed-response-error-message"
24
- }
19
+ resp = Seahorse::Client::Http::Response.new
20
+ resp.status_code = 400
21
+ resp.body = <<~JSON.strip
22
+ {
23
+ "code": #{error_code.inspect},
24
+ "message": "stubbed-response-error-message"
25
+ }
25
26
  JSON
26
- http_resp
27
+ resp
27
28
  end
28
29
 
29
30
  private