aws-sdk-core 3.46.0 → 3.94.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 (86) hide show
  1. checksums.yaml +5 -5
  2. data/VERSION +1 -1
  3. data/lib/aws-sdk-core.rb +7 -0
  4. data/lib/aws-sdk-core/arn.rb +77 -0
  5. data/lib/aws-sdk-core/arn_parser.rb +38 -0
  6. data/lib/aws-sdk-core/assume_role_web_identity_credentials.rb +102 -0
  7. data/lib/aws-sdk-core/async_client_stubs.rb +80 -0
  8. data/lib/aws-sdk-core/binary.rb +3 -0
  9. data/lib/aws-sdk-core/binary/decode_handler.rb +9 -1
  10. data/lib/aws-sdk-core/binary/encode_handler.rb +32 -0
  11. data/lib/aws-sdk-core/binary/event_builder.rb +122 -0
  12. data/lib/aws-sdk-core/binary/event_parser.rb +48 -18
  13. data/lib/aws-sdk-core/binary/event_stream_decoder.rb +5 -2
  14. data/lib/aws-sdk-core/binary/event_stream_encoder.rb +53 -0
  15. data/lib/aws-sdk-core/client_side_monitoring/publisher.rb +9 -1
  16. data/lib/aws-sdk-core/client_stubs.rb +10 -9
  17. data/lib/aws-sdk-core/credential_provider.rb +0 -31
  18. data/lib/aws-sdk-core/credential_provider_chain.rb +79 -39
  19. data/lib/aws-sdk-core/deprecations.rb +16 -10
  20. data/lib/aws-sdk-core/ecs_credentials.rb +12 -8
  21. data/lib/aws-sdk-core/endpoint_cache.rb +14 -11
  22. data/lib/aws-sdk-core/errors.rb +94 -6
  23. data/lib/aws-sdk-core/event_emitter.rb +42 -0
  24. data/lib/aws-sdk-core/instance_profile_credentials.rb +120 -38
  25. data/lib/aws-sdk-core/json.rb +13 -14
  26. data/lib/aws-sdk-core/json/error_handler.rb +19 -2
  27. data/lib/aws-sdk-core/json/handler.rb +19 -1
  28. data/lib/aws-sdk-core/log/formatter.rb +7 -1
  29. data/lib/aws-sdk-core/log/param_filter.rb +3 -3
  30. data/lib/aws-sdk-core/pageable_response.rb +34 -20
  31. data/lib/aws-sdk-core/param_validator.rb +11 -5
  32. data/lib/aws-sdk-core/plugins/client_metrics_plugin.rb +26 -1
  33. data/lib/aws-sdk-core/plugins/endpoint_discovery.rb +1 -1
  34. data/lib/aws-sdk-core/plugins/event_stream_configuration.rb +14 -0
  35. data/lib/aws-sdk-core/plugins/invocation_id.rb +33 -0
  36. data/lib/aws-sdk-core/plugins/regional_endpoint.rb +8 -1
  37. data/lib/aws-sdk-core/plugins/retries/client_rate_limiter.rb +137 -0
  38. data/lib/aws-sdk-core/plugins/retries/clock_skew.rb +98 -0
  39. data/lib/aws-sdk-core/plugins/retries/error_inspector.rb +142 -0
  40. data/lib/aws-sdk-core/plugins/retries/retry_quota.rb +57 -0
  41. data/lib/aws-sdk-core/plugins/retry_errors.rb +290 -106
  42. data/lib/aws-sdk-core/plugins/signature_v4.rb +13 -2
  43. data/lib/aws-sdk-core/plugins/stub_responses.rb +20 -7
  44. data/lib/aws-sdk-core/plugins/transfer_encoding.rb +51 -0
  45. data/lib/aws-sdk-core/plugins/user_agent.rb +4 -8
  46. data/lib/aws-sdk-core/process_credentials.rb +9 -3
  47. data/lib/aws-sdk-core/shared_config.rb +95 -125
  48. data/lib/aws-sdk-core/structure.rb +1 -2
  49. data/lib/aws-sdk-core/stubbing/protocols/rest.rb +19 -0
  50. data/lib/aws-sdk-core/stubbing/stub_data.rb +13 -4
  51. data/lib/aws-sdk-core/util.rb +4 -0
  52. data/lib/aws-sdk-core/waiters/waiter.rb +2 -2
  53. data/lib/aws-sdk-core/xml/error_handler.rb +26 -3
  54. data/lib/aws-sdk-sts.rb +7 -4
  55. data/lib/aws-sdk-sts/client.rb +1109 -459
  56. data/lib/aws-sdk-sts/client_api.rb +67 -0
  57. data/lib/aws-sdk-sts/customizations.rb +2 -0
  58. data/lib/aws-sdk-sts/errors.rb +150 -0
  59. data/lib/aws-sdk-sts/plugins/sts_regional_endpoints.rb +32 -0
  60. data/lib/aws-sdk-sts/presigner.rb +67 -0
  61. data/lib/aws-sdk-sts/resource.rb +1 -0
  62. data/lib/aws-sdk-sts/types.rb +736 -176
  63. data/lib/seahorse.rb +9 -0
  64. data/lib/seahorse/client/async_base.rb +50 -0
  65. data/lib/seahorse/client/async_response.rb +62 -0
  66. data/lib/seahorse/client/base.rb +4 -2
  67. data/lib/seahorse/client/configuration.rb +4 -2
  68. data/lib/seahorse/client/events.rb +1 -1
  69. data/lib/seahorse/client/h2/connection.rb +246 -0
  70. data/lib/seahorse/client/h2/handler.rb +151 -0
  71. data/lib/seahorse/client/handler_list_entry.rb +2 -2
  72. data/lib/seahorse/client/http/async_response.rb +42 -0
  73. data/lib/seahorse/client/http/response.rb +13 -8
  74. data/lib/seahorse/client/logging/formatter.rb +4 -2
  75. data/lib/seahorse/client/net_http/connection_pool.rb +19 -20
  76. data/lib/seahorse/client/net_http/handler.rb +7 -1
  77. data/lib/seahorse/client/net_http/patches.rb +7 -1
  78. data/lib/seahorse/client/networking_error.rb +28 -0
  79. data/lib/seahorse/client/plugin.rb +5 -4
  80. data/lib/seahorse/client/plugins/content_length.rb +5 -2
  81. data/lib/seahorse/client/plugins/h2.rb +64 -0
  82. data/lib/seahorse/client/response.rb +3 -5
  83. data/lib/seahorse/model/api.rb +4 -0
  84. data/lib/seahorse/model/operation.rb +4 -0
  85. data/lib/seahorse/model/shapes.rb +2 -2
  86. metadata +43 -10
@@ -42,7 +42,7 @@ module Aws
42
42
  option(:unsigned_operations) do |cfg|
43
43
  cfg.api.operation_names.inject([]) do |unsigned, operation_name|
44
44
  if cfg.api.operation(operation_name)['authtype'] == 'none' ||
45
- cfg.api.operation(operation_name)['authtype'] == 'custom'
45
+ cfg.api.operation(operation_name)['authtype'] == 'custom'
46
46
  # Unsign requests that has custom apigateway authorizer as well
47
47
  unsigned << operation_name
48
48
  else
@@ -107,6 +107,17 @@ module Aws
107
107
  req.headers.delete('X-Amz-Security-Token')
108
108
  req.headers.delete('X-Amz-Date')
109
109
 
110
+ if context.config.respond_to?(:clock_skew) &&
111
+ context.config.clock_skew &&
112
+ context.config.correct_clock_skew
113
+
114
+ endpoint = context.http_request.endpoint
115
+ skew = context.config.clock_skew.clock_correction(endpoint)
116
+ if skew.abs > 0
117
+ req.headers['X-Amz-Date'] = (Time.now.utc + skew).strftime("%Y%m%dT%H%M%SZ")
118
+ end
119
+ end
120
+
110
121
  # compute the signature
111
122
  begin
112
123
  signature = signer.sign_request(
@@ -130,7 +141,7 @@ module Aws
130
141
  # @api private
131
142
  def apply_authtype(context)
132
143
  if context.operation['authtype'].eql?('v4-unsigned-body') &&
133
- context.http_request.endpoint.scheme.eql?('https')
144
+ context.http_request.endpoint.scheme.eql?('https')
134
145
  context.http_request.headers['X-Amz-Content-Sha256'] = 'UNSIGNED-PAYLOAD'
135
146
  end
136
147
  context
@@ -34,6 +34,7 @@ requests are made, and retries are disabled.
34
34
  if client.config.stub_responses
35
35
  client.setup_stubbing
36
36
  client.handlers.remove(RetryErrors::Handler)
37
+ client.handlers.remove(RetryErrors::LegacyHandler)
37
38
  client.handlers.remove(ClientMetricsPlugin::Handler)
38
39
  client.handlers.remove(ClientMetricsSendPlugin::LatencyHandler)
39
40
  client.handlers.remove(ClientMetricsSendPlugin::AttemptHandler)
@@ -45,15 +46,18 @@ requests are made, and retries are disabled.
45
46
  def call(context)
46
47
  stub = context.client.next_stub(context)
47
48
  resp = Seahorse::Client::Response.new(context: context)
48
- apply_stub(stub, resp)
49
- resp
49
+ async_mode = context.client.is_a? Seahorse::Client::AsyncBase
50
+ apply_stub(stub, resp, async_mode)
51
+
52
+ async_mode ? Seahorse::Client::AsyncResponse.new(
53
+ context: context, stream: context[:input_event_stream_handler].event_emitter.stream, sync_queue: Queue.new) : resp
50
54
  end
51
55
 
52
- def apply_stub(stub, response)
56
+ def apply_stub(stub, response, async_mode = false)
53
57
  http_resp = response.context.http_response
54
58
  case
55
59
  when stub[:error] then signal_error(stub[:error], http_resp)
56
- when stub[:http] then signal_http(stub[:http], http_resp)
60
+ when stub[:http] then signal_http(stub[:http], http_resp, async_mode)
57
61
  when stub[:data] then response.data = stub[:data]
58
62
  end
59
63
  end
@@ -67,9 +71,18 @@ requests are made, and retries are disabled.
67
71
  end
68
72
 
69
73
  # @param [Seahorse::Client::Http::Response] stub
70
- # @param [Seahorse::Client::Http::Response] http_resp
71
- def signal_http(stub, http_resp)
72
- http_resp.signal_headers(stub.status_code, stub.headers.to_h)
74
+ # @param [Seahorse::Client::Http::Response | Seahorse::Client::Http::AsyncResponse] http_resp
75
+ # @param [Boolean] async_mode
76
+ def signal_http(stub, http_resp, async_mode = false)
77
+ if async_mode
78
+ h2_headers = stub.headers.to_h.inject([]) do |arr, (k, v)|
79
+ arr << [k, v]
80
+ end
81
+ h2_headers << [":status", stub.status_code]
82
+ http_resp.signal_headers(h2_headers)
83
+ else
84
+ http_resp.signal_headers(stub.status_code, stub.headers.to_h)
85
+ end
73
86
  while chunk = stub.body.read(1024 * 1024)
74
87
  http_resp.signal_data(chunk)
75
88
  end
@@ -0,0 +1,51 @@
1
+ module Aws
2
+ module Plugins
3
+
4
+ # For Streaming Input Operations, when `requiresLength` is enabled
5
+ # checking whether `Content-Length` header can be set,
6
+ # for `v4-unsigned-body` operations, set `Transfer-Encoding` header
7
+ class TransferEncoding < Seahorse::Client::Plugin
8
+
9
+ # @api private
10
+ class Handler < Seahorse::Client::Handler
11
+ def call(context)
12
+ if streaming?(context.operation.input)
13
+ # If it's an IO object and not a File / String / String IO
14
+ unless context.http_request.body.respond_to?(:size)
15
+ if requires_length?(context.operation.input)
16
+ # if size of the IO is not available but required
17
+ raise Aws::Errors::MissingContentLength.new
18
+ elsif context.operation['authtype'] == "v4-unsigned-body"
19
+ context.http_request.headers['Transfer-Encoding'] = 'chunked'
20
+ end
21
+ end
22
+ end
23
+
24
+ @handler.call(context)
25
+ end
26
+
27
+ private
28
+
29
+ def streaming?(ref)
30
+ if payload = ref[:payload_member]
31
+ payload["streaming"] || # checking ref and shape
32
+ payload.shape["streaming"]
33
+ else
34
+ false
35
+ end
36
+ end
37
+
38
+ def requires_length?(ref)
39
+ payload = ref[:payload_member]
40
+ payload["requiresLength"] || # checking ref and shape
41
+ payload.shape["requiresLength"]
42
+ end
43
+
44
+ end
45
+
46
+ handler(Handler, step: :sign)
47
+
48
+ end
49
+
50
+ end
51
+ end
@@ -2,20 +2,16 @@ module Aws
2
2
  module Plugins
3
3
  # @api private
4
4
  class UserAgent < Seahorse::Client::Plugin
5
-
6
5
  option(:user_agent_suffix)
7
6
 
8
7
  # @api private
9
8
  class Handler < Seahorse::Client::Handler
10
-
11
9
  def call(context)
12
10
  set_user_agent(context)
13
11
  @handler.call(context)
14
12
  end
15
13
 
16
14
  def set_user_agent(context)
17
- execution_env = ENV["AWS_EXECUTION_ENV"]
18
-
19
15
  ua = "aws-sdk-ruby3/#{CORE_GEM_VERSION}"
20
16
 
21
17
  begin
@@ -30,19 +26,19 @@ module Aws
30
26
  ua += " #{context[:gem_name]}/#{context[:gem_version]}"
31
27
  end
32
28
 
33
- if execution_env
29
+ if (execution_env = ENV['AWS_EXECUTION_ENV'])
34
30
  ua += " exec-env/#{execution_env}"
35
31
  end
36
32
 
37
- ua += " #{context.config.user_agent_suffix}" if context.config.user_agent_suffix
33
+ if context.config.user_agent_suffix
34
+ ua += " #{context.config.user_agent_suffix}"
35
+ end
38
36
 
39
37
  context.http_request.headers['User-Agent'] = ua.strip
40
38
  end
41
-
42
39
  end
43
40
 
44
41
  handler(Handler)
45
-
46
42
  end
47
43
  end
48
44
  end
@@ -5,7 +5,7 @@ module Aws
5
5
  # A credential provider that executes a given process and attempts
6
6
  # to read its stdout to recieve a JSON payload containing the credentials
7
7
  #
8
- # Automatically handles refreshing credentials if an Expiration time is
8
+ # Automatically handles refreshing credentials if an Expiration time is
9
9
  # provided in the credentials payload
10
10
  #
11
11
  # credentials = Aws::ProcessCredentials.new('/usr/bin/credential_proc').credentials
@@ -23,10 +23,12 @@ module Aws
23
23
  # external process to be used as a credential provider.
24
24
  #
25
25
  # @param [String] process Invocation string for process
26
- # credentials provider.
26
+ # credentials provider.
27
27
  def initialize(process)
28
28
  @process = process
29
29
  @credentials = credentials_from_process(@process)
30
+
31
+ super
30
32
  end
31
33
 
32
34
  private
@@ -38,7 +40,11 @@ module Aws
38
40
  end
39
41
 
40
42
  if process_status.success?
41
- creds_json = JSON.parse(raw_out)
43
+ begin
44
+ creds_json = JSON.parse(raw_out)
45
+ rescue JSON::ParserError
46
+ raise Errors::InvalidProcessCredentialsPayload.new("Invalid JSON response")
47
+ end
42
48
  payload_version = creds_json['Version']
43
49
  if payload_version == 1
44
50
  _parse_payload_format_v1(creds_json)
@@ -1,8 +1,6 @@
1
1
  module Aws
2
-
3
2
  # @api private
4
3
  class SharedConfig
5
-
6
4
  # @return [String]
7
5
  attr_reader :credentials_path
8
6
 
@@ -48,7 +46,7 @@ module Aws
48
46
  @profile_name = determine_profile(options)
49
47
  @config_enabled = options[:config_enabled]
50
48
  @credentials_path = options[:credentials_path] ||
51
- determine_credentials_path
49
+ determine_credentials_path
52
50
  @parsed_credentials = {}
53
51
  load_credentials_file if loadable?(@credentials_path)
54
52
  if @config_enabled
@@ -67,7 +65,7 @@ module Aws
67
65
  @config_enabled = options[:config_enabled] ? true : false
68
66
  @profile_name = determine_profile(options)
69
67
  @credentials_path = options[:credentials_path] ||
70
- determine_credentials_path
68
+ determine_credentials_path
71
69
  load_credentials_file if loadable?(@credentials_path)
72
70
  if @config_enabled
73
71
  @config_path = options[:config_path] || determine_config_path
@@ -99,12 +97,10 @@ module Aws
99
97
  def credentials(opts = {})
100
98
  p = opts[:profile] || @profile_name
101
99
  validate_profile_exists(p) if credentials_present?
102
- if credentials = credentials_from_shared(p, opts)
100
+ if (credentials = credentials_from_shared(p, opts))
103
101
  credentials
104
- elsif credentials = credentials_from_config(p, opts)
102
+ elsif (credentials = credentials_from_config(p, opts))
105
103
  credentials
106
- else
107
- nil
108
104
  end
109
105
  end
110
106
 
@@ -121,79 +117,61 @@ module Aws
121
117
  credentials
122
118
  end
123
119
 
124
- def region(opts = {})
120
+ def assume_role_web_identity_credentials_from_config(opts = {})
125
121
  p = opts[:profile] || @profile_name
126
- if @config_enabled
127
- if @parsed_credentials
128
- region = @parsed_credentials.fetch(p, {})["region"]
129
- end
130
- if @parsed_config
131
- region ||= @parsed_config.fetch(p, {})["region"]
122
+ if @config_enabled && @parsed_config
123
+ entry = @parsed_config.fetch(p, {})
124
+ if entry['web_identity_token_file'] && entry['role_arn']
125
+ cfg = {
126
+ role_arn: entry['role_arn'],
127
+ web_identity_token_file: entry['web_identity_token_file'],
128
+ role_session_name: entry['role_session_name']
129
+ }
130
+ cfg[:region] = opts[:region] if opts[:region]
131
+ AssumeRoleWebIdentityCredentials.new(cfg)
132
132
  end
133
- region
134
- else
135
- nil
136
133
  end
137
134
  end
138
135
 
139
- def endpoint_discovery(opts = {})
140
- p = opts[:profile] || @profile_name
141
- if @config_enabled && @parsed_config
142
- @parsed_config.fetch(p, {})["endpoint_discovery_enabled"]
136
+ # Add an accessor method (similar to attr_reader) to return a configuration value
137
+ # Uses the get_config_value below to control where
138
+ # values are loaded from
139
+ def self.config_reader(*attrs)
140
+ attrs.each do |attr|
141
+ define_method(attr) { |opts = {}| get_config_value(attr.to_s, opts) }
143
142
  end
144
143
  end
145
144
 
146
- def credentials_process(profile)
147
- validate_profile_exists(profile)
148
- @parsed_config[profile]['credential_process']
149
- end
145
+ config_reader(
146
+ :region,
147
+ :credential_process,
148
+ :endpoint_discovery_enabled,
149
+ :max_attempts,
150
+ :retry_mode,
151
+ :adaptive_retry_wait_to_fill,
152
+ :correct_clock_skew,
153
+ :csm_client_id,
154
+ :csm_enabled,
155
+ :csm_host,
156
+ :csm_port,
157
+ :sts_regional_endpoints,
158
+ :s3_use_arn_region,
159
+ :s3_us_east_1_regional_endpoint
160
+ )
150
161
 
151
- def csm_enabled(opts = {})
152
- p = opts[:profile] || @profile_name
153
- if @config_enabled
154
- if @parsed_credentials
155
- value = @parsed_credentials.fetch(p, {})["csm_enabled"]
156
- end
157
- if @parsed_config
158
- value ||= @parsed_config.fetch(p, {})["csm_enabled"]
159
- end
160
- value
161
- else
162
- nil
163
- end
164
- end
162
+ private
165
163
 
166
- def csm_client_id(opts = {})
164
+ # Get a config value from from shared credential/config files.
165
+ # Only loads a value when config_enabled is true
166
+ # Return a value from credentials preferentially over config
167
+ def get_config_value(key, opts)
167
168
  p = opts[:profile] || @profile_name
168
- if @config_enabled
169
- if @parsed_credentials
170
- value = @parsed_credentials.fetch(p, {})["csm_client_id"]
171
- end
172
- if @parsed_config
173
- value ||= @parsed_config.fetch(p, {})["csm_client_id"]
174
- end
175
- value
176
- else
177
- nil
178
- end
179
- end
180
169
 
181
- def csm_port(opts = {})
182
- p = opts[:profile] || @profile_name
183
- if @config_enabled
184
- if @parsed_credentials
185
- value = @parsed_credentials.fetch(p, {})["csm_port"]
186
- end
187
- if @parsed_config
188
- value ||= @parsed_config.fetch(p, {})["csm_port"]
189
- end
190
- value
191
- else
192
- nil
193
- end
170
+ value = @parsed_credentials.fetch(p, {})[key] if @parsed_credentials
171
+ value ||= @parsed_config.fetch(p, {})[key] if @config_enabled && @parsed_config
172
+ value
194
173
  end
195
174
 
196
- private
197
175
  def credentials_present?
198
176
  (@parsed_credentials && !@parsed_credentials.empty?) ||
199
177
  (@parsed_config && !@parsed_config.empty?)
@@ -201,30 +179,28 @@ module Aws
201
179
 
202
180
  def assume_role_from_profile(cfg, profile, opts, chain_config)
203
181
  if cfg && prof_cfg = cfg[profile]
204
- opts[:source_profile] ||= prof_cfg["source_profile"]
182
+ opts[:source_profile] ||= prof_cfg['source_profile']
205
183
  credential_source = opts.delete(:credential_source)
206
- credential_source ||= prof_cfg["credential_source"]
184
+ credential_source ||= prof_cfg['credential_source']
207
185
  if opts[:source_profile] && credential_source
208
- raise Errors::CredentialSourceConflictError.new(
209
- "Profile #{profile} has a source_profile, and "\
210
- "a credential_source. For assume role credentials, must "\
211
- "provide only source_profile or credential_source, not both."
212
- )
186
+ raise Errors::CredentialSourceConflictError,
187
+ "Profile #{profile} has a source_profile, and "\
188
+ 'a credential_source. For assume role credentials, must '\
189
+ 'provide only source_profile or credential_source, not both.'
213
190
  elsif opts[:source_profile]
214
- opts[:credentials] = credentials(profile: opts[:source_profile])
191
+ opts[:credentials] = resolve_source_profile(opts[:source_profile], opts)
215
192
  if opts[:credentials]
216
- opts[:role_session_name] ||= prof_cfg["role_session_name"]
217
- opts[:role_session_name] ||= "default_session"
218
- opts[:role_arn] ||= prof_cfg["role_arn"]
219
- opts[:external_id] ||= prof_cfg["external_id"]
220
- opts[:serial_number] ||= prof_cfg["mfa_serial"]
193
+ opts[:role_session_name] ||= prof_cfg['role_session_name']
194
+ opts[:role_session_name] ||= 'default_session'
195
+ opts[:role_arn] ||= prof_cfg['role_arn']
196
+ opts[:duration_seconds] ||= prof_cfg['duration_seconds']
197
+ opts[:external_id] ||= prof_cfg['external_id']
198
+ opts[:serial_number] ||= prof_cfg['mfa_serial']
221
199
  opts[:profile] = opts.delete(:source_profile)
222
200
  AssumeRoleCredentials.new(opts)
223
201
  else
224
- raise Errors::NoSourceProfileError.new(
225
- "Profile #{profile} has a role_arn, and source_profile, but the"\
226
- " source_profile does not have credentials."
227
- )
202
+ raise Errors::NoSourceProfileError, "Profile #{profile} has a role_arn, and source_profile, but the"\
203
+ ' source_profile does not have credentials.'
228
204
  end
229
205
  elsif credential_source
230
206
  opts[:credentials] = credentials_from_source(
@@ -232,61 +208,64 @@ module Aws
232
208
  chain_config
233
209
  )
234
210
  if opts[:credentials]
235
- opts[:role_session_name] ||= prof_cfg["role_session_name"]
236
- opts[:role_session_name] ||= "default_session"
237
- opts[:role_arn] ||= prof_cfg["role_arn"]
238
- opts[:external_id] ||= prof_cfg["external_id"]
239
- opts[:serial_number] ||= prof_cfg["mfa_serial"]
211
+ opts[:role_session_name] ||= prof_cfg['role_session_name']
212
+ opts[:role_session_name] ||= 'default_session'
213
+ opts[:role_arn] ||= prof_cfg['role_arn']
214
+ opts[:duration_seconds] ||= prof_cfg['duration_seconds']
215
+ opts[:external_id] ||= prof_cfg['external_id']
216
+ opts[:serial_number] ||= prof_cfg['mfa_serial']
240
217
  opts.delete(:source_profile) # Cleanup
241
218
  AssumeRoleCredentials.new(opts)
242
219
  else
243
- raise Errors::NoSourceCredentials.new(
244
- "Profile #{profile} could not get source credentials from"\
220
+ raise Errors::NoSourceCredentials, "Profile #{profile} could not get source credentials from"\
245
221
  " provider #{credential_source}"
246
- )
247
222
  end
248
- elsif prof_cfg["role_arn"]
249
- raise Errors::NoSourceProfileError.new(
250
- "Profile #{profile} has a role_arn, but no source_profile."
251
- )
252
- else
253
- nil
223
+ elsif prof_cfg['role_arn']
224
+ raise Errors::NoSourceProfileError, "Profile #{profile} has a role_arn, but no source_profile."
254
225
  end
255
- else
256
- nil
226
+ end
227
+ end
228
+
229
+ def resolve_source_profile(profile, opts = {})
230
+ if (creds = credentials(profile: profile))
231
+ creds # static credentials
232
+ elsif (provider = assume_role_web_identity_credentials_from_config(opts.merge(profile: profile)))
233
+ provider.credentials if provider.credentials.set?
234
+ elsif (provider = assume_role_process_credentials_from_config(profile))
235
+ provider.credentials if provider.credentials.set?
257
236
  end
258
237
  end
259
238
 
260
239
  def credentials_from_source(credential_source, config)
261
240
  case credential_source
262
- when "Ec2InstanceMetadata"
241
+ when 'Ec2InstanceMetadata'
263
242
  InstanceProfileCredentials.new(
264
243
  retries: config ? config.instance_profile_credentials_retries : 0,
265
244
  http_open_timeout: config ? config.instance_profile_credentials_timeout : 1,
266
245
  http_read_timeout: config ? config.instance_profile_credentials_timeout : 1
267
246
  )
268
- when "EcsContainer"
247
+ when 'EcsContainer'
269
248
  ECSCredentials.new
270
249
  else
271
- raise Errors::InvalidCredentialSourceError.new(
272
- "Unsupported credential_source: #{credential_source}"
273
- )
250
+ raise Errors::InvalidCredentialSourceError, "Unsupported credential_source: #{credential_source}"
274
251
  end
275
252
  end
276
253
 
277
- def credentials_from_shared(profile, opts)
254
+ def assume_role_process_credentials_from_config(profile)
255
+ validate_profile_exists(profile)
256
+ credential_process = @parsed_config[profile]['credential_process']
257
+ ProcessCredentials.new(credential_process) if credential_process
258
+ end
259
+
260
+ def credentials_from_shared(profile, _opts)
278
261
  if @parsed_credentials && prof_config = @parsed_credentials[profile]
279
262
  credentials_from_profile(prof_config)
280
- else
281
- nil
282
263
  end
283
264
  end
284
265
 
285
- def credentials_from_config(profile, opts)
266
+ def credentials_from_config(profile, _opts)
286
267
  if @parsed_config && prof_config = @parsed_config[profile]
287
268
  credentials_from_profile(prof_config)
288
- else
289
- nil
290
269
  end
291
270
  end
292
271
 
@@ -296,15 +275,7 @@ module Aws
296
275
  prof_config['aws_secret_access_key'],
297
276
  prof_config['aws_session_token']
298
277
  )
299
- if credentials_complete(creds)
300
- creds
301
- else
302
- nil
303
- end
304
- end
305
-
306
- def credentials_complete(creds)
307
- creds.set?
278
+ creds if creds.set?
308
279
  end
309
280
 
310
281
  def load_credentials_file
@@ -334,19 +305,18 @@ module Aws
334
305
 
335
306
  def validate_profile_exists(profile)
336
307
  unless (@parsed_credentials && @parsed_credentials[profile]) ||
337
- (@parsed_config && @parsed_config[profile])
308
+ (@parsed_config && @parsed_config[profile])
338
309
  msg = "Profile `#{profile}' not found in #{@credentials_path}"
339
310
  msg << " or #{@config_path}" if @config_path
340
- raise Errors::NoSuchProfileError.new(msg)
311
+ raise Errors::NoSuchProfileError, msg
341
312
  end
342
313
  end
343
314
 
344
315
  def determine_profile(options)
345
316
  ret = options[:profile_name]
346
- ret ||= ENV["AWS_PROFILE"]
347
- ret ||= "default"
317
+ ret ||= ENV['AWS_PROFILE']
318
+ ret ||= 'default'
348
319
  ret
349
320
  end
350
-
351
321
  end
352
322
  end