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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +140 -0
- data/VERSION +1 -1
- data/lib/aws-sdk-core/assume_role_credentials.rb +1 -0
- data/lib/aws-sdk-core/assume_role_web_identity_credentials.rb +1 -0
- data/lib/aws-sdk-core/credential_provider.rb +4 -0
- data/lib/aws-sdk-core/credential_provider_chain.rb +28 -8
- data/lib/aws-sdk-core/credentials.rb +6 -0
- data/lib/aws-sdk-core/ecs_credentials.rb +1 -0
- data/lib/aws-sdk-core/endpoints/matchers.rb +2 -1
- data/lib/aws-sdk-core/endpoints.rb +37 -13
- data/lib/aws-sdk-core/error_handler.rb +5 -0
- data/lib/aws-sdk-core/errors.rb +2 -2
- data/lib/aws-sdk-core/event_emitter.rb +1 -1
- data/lib/aws-sdk-core/instance_profile_credentials.rb +147 -157
- data/lib/aws-sdk-core/json/error_handler.rb +14 -4
- data/lib/aws-sdk-core/plugins/client_metrics_plugin.rb +0 -1
- data/lib/aws-sdk-core/plugins/credentials_configuration.rb +75 -59
- data/lib/aws-sdk-core/plugins/endpoint_pattern.rb +40 -32
- data/lib/aws-sdk-core/plugins/sign.rb +29 -20
- data/lib/aws-sdk-core/plugins/stub_responses.rb +6 -0
- data/lib/aws-sdk-core/plugins/user_agent.rb +24 -2
- data/lib/aws-sdk-core/process_credentials.rb +1 -1
- data/lib/aws-sdk-core/rest/request/headers.rb +1 -1
- data/lib/aws-sdk-core/rpc_v2/error_handler.rb +26 -16
- data/lib/aws-sdk-core/rpc_v2/parser.rb +8 -0
- data/lib/aws-sdk-core/shared_config.rb +82 -21
- data/lib/aws-sdk-core/shared_credentials.rb +1 -0
- data/lib/aws-sdk-core/sso_credentials.rb +2 -0
- data/lib/aws-sdk-core/static_token_provider.rb +1 -2
- data/lib/aws-sdk-core/token.rb +3 -3
- data/lib/aws-sdk-core/token_provider.rb +4 -0
- data/lib/aws-sdk-core/token_provider_chain.rb +2 -6
- data/lib/aws-sdk-core/util.rb +2 -1
- data/lib/aws-sdk-core/xml/error_handler.rb +3 -1
- data/lib/aws-sdk-sso/client.rb +25 -19
- data/lib/aws-sdk-sso/endpoint_provider.rb +2 -2
- data/lib/aws-sdk-sso.rb +1 -1
- data/lib/aws-sdk-ssooidc/client.rb +38 -21
- data/lib/aws-sdk-ssooidc/client_api.rb +6 -0
- data/lib/aws-sdk-ssooidc/types.rb +28 -1
- data/lib/aws-sdk-ssooidc.rb +1 -1
- data/lib/aws-sdk-sts/client.rb +25 -19
- data/lib/aws-sdk-sts/client_api.rb +10 -8
- data/lib/aws-sdk-sts/endpoint_provider.rb +18 -18
- data/lib/aws-sdk-sts/errors.rb +0 -1
- data/lib/aws-sdk-sts/presigner.rb +2 -6
- data/lib/aws-sdk-sts.rb +1 -1
- data/lib/seahorse/client/async_base.rb +4 -5
- data/lib/seahorse/client/base.rb +0 -14
- data/lib/seahorse/client/h2/connection.rb +18 -28
- data/lib/seahorse/client/http/response.rb +1 -1
- data/lib/seahorse/client/net_http/connection_pool.rb +2 -1
- data/lib/seahorse/client/networking_error.rb +1 -1
- data/lib/seahorse/client/plugins/h2.rb +4 -4
- data/lib/seahorse/client/request_context.rb +2 -2
- data/lib/seahorse/util.rb +2 -1
- data/sig/aws-sdk-core/async_client_stubs.rbs +21 -0
- data/sig/seahorse/client/async_base.rbs +18 -0
- metadata +34 -8
@@ -4,11 +4,23 @@ require 'time'
|
|
4
4
|
require 'net/http'
|
5
5
|
|
6
6
|
module Aws
|
7
|
-
# An auto-refreshing credential provider that loads credentials from
|
8
|
-
# EC2 instances.
|
7
|
+
# An auto-refreshing credential provider that loads credentials from EC2 instances.
|
9
8
|
#
|
10
9
|
# instance_credentials = Aws::InstanceProfileCredentials.new
|
11
10
|
# ec2 = Aws::EC2::Client.new(credentials: instance_credentials)
|
11
|
+
#
|
12
|
+
# ## Retries
|
13
|
+
# When initialized from the default credential chain, this provider defaults to `0` retries.
|
14
|
+
# Breakdown of retries is as follows:
|
15
|
+
#
|
16
|
+
# * **Configurable retries** (defaults to `1`): these retries handle errors when communicating
|
17
|
+
# with the IMDS endpoint. There are two separate retry mechanisms within the provider:
|
18
|
+
# * Entire token fetch and credential retrieval process
|
19
|
+
# * Token fetching
|
20
|
+
# * **JSON parsing retries**: Fixed at 3 attempts to handle cases when IMDS returns malformed JSON
|
21
|
+
# responses. These retries are separate from configurable retries.
|
22
|
+
#
|
23
|
+
# @see https://docs.aws.amazon.com/sdkref/latest/guide/feature-imds-credentials.html IMDS Credential Provider
|
12
24
|
class InstanceProfileCredentials
|
13
25
|
include CredentialProvider
|
14
26
|
include RefreshingCredentials
|
@@ -22,10 +34,8 @@ module Aws
|
|
22
34
|
# @api private
|
23
35
|
class TokenExpiredError < RuntimeError; end
|
24
36
|
|
25
|
-
# These are the errors we trap when attempting to talk to the
|
26
|
-
#
|
27
|
-
# is not present, no responding or some other non-recoverable
|
28
|
-
# error.
|
37
|
+
# These are the errors we trap when attempting to talk to the instance metadata service.
|
38
|
+
# Any of these imply the service is not present, no responding or some other non-recoverable error.
|
29
39
|
# @api private
|
30
40
|
NETWORK_ERRORS = [
|
31
41
|
Errno::EHOSTUNREACH,
|
@@ -46,99 +56,113 @@ module Aws
|
|
46
56
|
METADATA_TOKEN_PATH = '/latest/api/token'.freeze
|
47
57
|
|
48
58
|
# @param [Hash] options
|
49
|
-
# @option options [Integer] :retries (1) Number of times to retry
|
50
|
-
#
|
51
|
-
#
|
52
|
-
#
|
53
|
-
#
|
54
|
-
#
|
55
|
-
#
|
56
|
-
#
|
57
|
-
# legacy EC2 Metadata Service v1.
|
58
|
-
# @option options [String] :ip_address ('169.254.169.254') Deprecated. Use
|
59
|
-
# :endpoint instead. The IP address for the endpoint.
|
59
|
+
# @option options [Integer] :retries (1) Number of times to retry when retrieving credentials.
|
60
|
+
# @option options [String] :endpoint ('http://169.254.169.254') The IMDS endpoint. This option has precedence
|
61
|
+
# over the `:endpoint_mode`.
|
62
|
+
# @option options [String] :endpoint_mode ('IPv4') The endpoint mode for the instance metadata service. This is
|
63
|
+
# either 'IPv4' (`169.254.169.254`) or IPv6' (`[fd00:ec2::254]`).
|
64
|
+
# @option options [Boolean] :disable_imds_v1 (false) Disable the use of the legacy EC2 Metadata Service v1.
|
65
|
+
# @option options [String] :ip_address ('169.254.169.254') Deprecated. Use `:endpoint` instead.
|
66
|
+
# The IP address for the endpoint.
|
60
67
|
# @option options [Integer] :port (80)
|
61
68
|
# @option options [Float] :http_open_timeout (1)
|
62
69
|
# @option options [Float] :http_read_timeout (1)
|
63
|
-
# @option options [Numeric, Proc] :delay By default, failures are retried
|
64
|
-
#
|
65
|
-
#
|
66
|
-
#
|
67
|
-
#
|
68
|
-
#
|
69
|
-
#
|
70
|
-
# @option options [
|
71
|
-
#
|
72
|
-
# to 21600 seconds
|
73
|
-
# @option options [Callable] before_refresh Proc called before
|
74
|
-
# credentials are refreshed. `before_refresh` is called
|
75
|
-
# with an instance of this object when
|
76
|
-
# AWS credentials are required and need to be refreshed.
|
70
|
+
# @option options [Numeric, Proc] :delay By default, failures are retried with exponential back-off, i.e.
|
71
|
+
# `sleep(1.2 ** num_failures)`. You can pass a number of seconds to sleep between failed attempts, or a Proc
|
72
|
+
# that accepts the number of failures.
|
73
|
+
# @option options [IO] :http_debug_output (nil) HTTP wire traces are sent to this object.
|
74
|
+
# You can specify something like `$stdout`.
|
75
|
+
# @option options [Integer] :token_ttl Time-to-Live in seconds for EC2 Metadata Token used for fetching
|
76
|
+
# Metadata Profile Credentials, defaults to 21600 seconds.
|
77
|
+
# @option options [Callable] :before_refresh Proc called before credentials are refreshed. `before_refresh`
|
78
|
+
# is called with an instance of this object when AWS credentials are required and need to be refreshed.
|
77
79
|
def initialize(options = {})
|
78
|
-
@
|
79
|
-
endpoint_mode = resolve_endpoint_mode(options)
|
80
|
-
@endpoint = resolve_endpoint(options, endpoint_mode)
|
81
|
-
@port = options[:port] || 80
|
80
|
+
@backoff = resolve_backoff(options[:backoff])
|
82
81
|
@disable_imds_v1 = resolve_disable_v1(options)
|
83
|
-
|
84
|
-
@imds_v1_fallback = false
|
82
|
+
@endpoint = resolve_endpoint(options)
|
85
83
|
@http_open_timeout = options[:http_open_timeout] || 1
|
86
84
|
@http_read_timeout = options[:http_read_timeout] || 1
|
87
85
|
@http_debug_output = options[:http_debug_output]
|
88
|
-
@
|
86
|
+
@port = options[:port] || 80
|
87
|
+
@retries = options[:retries] || 1
|
89
88
|
@token_ttl = options[:token_ttl] || 21_600
|
90
|
-
|
91
|
-
@no_refresh_until = nil
|
89
|
+
|
92
90
|
@async_refresh = false
|
91
|
+
@imds_v1_fallback = false
|
92
|
+
@no_refresh_until = nil
|
93
|
+
@token = nil
|
94
|
+
@metrics = ['CREDENTIALS_IMDS']
|
93
95
|
super
|
94
96
|
end
|
95
97
|
|
96
|
-
# @return [
|
97
|
-
|
98
|
-
|
98
|
+
# @return [Boolean0
|
99
|
+
attr_reader :disable_imds_v1
|
100
|
+
|
101
|
+
# @return [Integer]
|
102
|
+
attr_reader :token_ttl
|
103
|
+
|
104
|
+
# @return [Integer]
|
99
105
|
attr_reader :retries
|
100
106
|
|
107
|
+
# @return [Proc]
|
108
|
+
attr_reader :backoff
|
109
|
+
|
110
|
+
# @return [String]
|
111
|
+
attr_reader :endpoint
|
112
|
+
|
113
|
+
# @return [Integer]
|
114
|
+
attr_reader :port
|
115
|
+
|
116
|
+
# @return [Integer]
|
117
|
+
attr_reader :http_open_timeout
|
118
|
+
|
119
|
+
# @return [Integer]
|
120
|
+
attr_reader :http_read_timeout
|
121
|
+
|
122
|
+
# @return [IO, nil]
|
123
|
+
attr_reader :http_debug_output
|
124
|
+
|
101
125
|
private
|
102
126
|
|
103
127
|
def resolve_endpoint_mode(options)
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
)
|
109
|
-
value || 'IPv4'
|
128
|
+
options[:endpoint_mode] ||
|
129
|
+
ENV['AWS_EC2_METADATA_SERVICE_ENDPOINT_MODE'] ||
|
130
|
+
Aws.shared_config.ec2_metadata_service_endpoint_mode(profile: options[:profile]) ||
|
131
|
+
'IPv4'
|
110
132
|
end
|
111
133
|
|
112
|
-
def resolve_endpoint(options
|
113
|
-
value = options[:
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
)
|
134
|
+
def resolve_endpoint(options)
|
135
|
+
if (value = options[:ip_address])
|
136
|
+
warn('The `:ip_address` option is deprecated. Use `:endpoint` instead.')
|
137
|
+
return value
|
138
|
+
end
|
118
139
|
|
140
|
+
value =
|
141
|
+
options[:endpoint] ||
|
142
|
+
ENV['AWS_EC2_METADATA_SERVICE_ENDPOINT'] ||
|
143
|
+
Aws.shared_config.ec2_metadata_service_endpoint(profile: options[:profile]) ||
|
144
|
+
nil
|
119
145
|
return value if value
|
120
146
|
|
147
|
+
endpoint_mode = resolve_endpoint_mode(options)
|
121
148
|
case endpoint_mode.downcase
|
122
149
|
when 'ipv4' then 'http://169.254.169.254'
|
123
150
|
when 'ipv6' then 'http://[fd00:ec2::254]'
|
124
151
|
else
|
125
|
-
raise ArgumentError,
|
126
|
-
':endpoint_mode is not valid, expected IPv4 or IPv6, '\
|
127
|
-
"got: #{endpoint_mode}"
|
152
|
+
raise ArgumentError, ":endpoint_mode is not valid, expected IPv4 or IPv6, got: #{endpoint_mode}"
|
128
153
|
end
|
129
154
|
end
|
130
155
|
|
131
156
|
def resolve_disable_v1(options)
|
132
|
-
value =
|
133
|
-
|
134
|
-
|
135
|
-
profile: options[:profile]
|
136
|
-
|
137
|
-
value
|
138
|
-
Aws::Util.str_2_bool(value) || false
|
157
|
+
value =
|
158
|
+
options[:disable_imds_v1] ||
|
159
|
+
ENV['AWS_EC2_METADATA_V1_DISABLED'] ||
|
160
|
+
Aws.shared_config.ec2_metadata_v1_disabled(profile: options[:profile]) ||
|
161
|
+
'false'
|
162
|
+
Aws::Util.str_2_bool(value.to_s.downcase)
|
139
163
|
end
|
140
164
|
|
141
|
-
def
|
165
|
+
def resolve_backoff(backoff)
|
142
166
|
case backoff
|
143
167
|
when Proc then backoff
|
144
168
|
when Numeric then ->(_) { sleep(backoff) }
|
@@ -152,98 +176,74 @@ module Aws
|
|
152
176
|
return
|
153
177
|
end
|
154
178
|
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
@credentials = Credentials.new(
|
163
|
-
c['AccessKeyId'],
|
164
|
-
c['SecretAccessKey'],
|
165
|
-
c['Token']
|
166
|
-
)
|
167
|
-
@expiration = c['Expiration'] ? Time.iso8601(c['Expiration']) : nil
|
168
|
-
if @expiration && @expiration < Time.now
|
169
|
-
@no_refresh_until = Time.now + refresh_offset
|
170
|
-
warn_expired_credentials
|
171
|
-
end
|
172
|
-
else
|
173
|
-
# credentials are already set, update them only if the new ones are not empty
|
174
|
-
if !c['AccessKeyId'] || c['AccessKeyId'].empty?
|
175
|
-
# error getting new credentials
|
176
|
-
@no_refresh_until = Time.now + refresh_offset
|
177
|
-
warn_expired_credentials
|
178
|
-
else
|
179
|
-
@credentials = Credentials.new(
|
180
|
-
c['AccessKeyId'],
|
181
|
-
c['SecretAccessKey'],
|
182
|
-
c['Token']
|
183
|
-
)
|
184
|
-
@expiration = c['Expiration'] ? Time.iso8601(c['Expiration']) : nil
|
185
|
-
if @expiration && @expiration < Time.now
|
186
|
-
@no_refresh_until = Time.now + refresh_offset
|
187
|
-
warn_expired_credentials
|
188
|
-
end
|
189
|
-
end
|
179
|
+
new_creds =
|
180
|
+
begin
|
181
|
+
# Retry loading credentials up to 3 times is the instance metadata
|
182
|
+
# service is responding but is returning invalid JSON documents
|
183
|
+
# in response to the GET profile credentials call.
|
184
|
+
retry_errors([Aws::Json::ParseError], max_retries: 3) do
|
185
|
+
Aws::Json.load(retrieve_credentials.to_s)
|
190
186
|
end
|
187
|
+
rescue Aws::Json::ParseError
|
188
|
+
raise Aws::Errors::MetadataParserError
|
191
189
|
end
|
192
|
-
|
193
|
-
|
190
|
+
|
191
|
+
if @credentials&.set? && empty_credentials?(new_creds)
|
192
|
+
# credentials are already set, but there was an error getting new credentials
|
193
|
+
# so don't update the credentials and use stale ones (static stability)
|
194
|
+
@no_refresh_until = Time.now + rand(300..360)
|
195
|
+
warn_expired_credentials
|
196
|
+
else
|
197
|
+
# credentials are empty or successfully retrieved, update them
|
198
|
+
update_credentials(new_creds)
|
194
199
|
end
|
195
200
|
end
|
196
201
|
|
197
|
-
def
|
202
|
+
def retrieve_credentials
|
198
203
|
# Retry loading credentials a configurable number of times if
|
199
204
|
# the instance metadata service is not responding.
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
# disable insecure flow if we couldn't get token
|
212
|
-
# and imds v1 is disabled
|
213
|
-
raise TokenRetrivalError if token.nil? && @disable_imds_v1
|
214
|
-
|
215
|
-
_get_credentials(conn, token)
|
216
|
-
end
|
205
|
+
begin
|
206
|
+
retry_errors(NETWORK_ERRORS, max_retries: @retries) do
|
207
|
+
open_connection do |conn|
|
208
|
+
# attempt to fetch token to start secure flow first
|
209
|
+
# and rescue to failover
|
210
|
+
fetch_token(conn) unless @imds_v1_fallback || (@token && !@token.expired?)
|
211
|
+
|
212
|
+
# disable insecure flow if we couldn't get token and imds v1 is disabled
|
213
|
+
raise TokenRetrivalError if @token.nil? && @disable_imds_v1
|
214
|
+
|
215
|
+
fetch_credentials(conn)
|
217
216
|
end
|
218
|
-
rescue => e
|
219
|
-
warn("Error retrieving instance profile credentials: #{e}")
|
220
|
-
'{}'
|
221
217
|
end
|
218
|
+
rescue StandardError => e
|
219
|
+
warn("Error retrieving instance profile credentials: #{e}")
|
220
|
+
'{}'
|
222
221
|
end
|
223
222
|
end
|
224
223
|
|
224
|
+
def update_credentials(creds)
|
225
|
+
@credentials = Credentials.new(creds['AccessKeyId'], creds['SecretAccessKey'], creds['Token'])
|
226
|
+
@expiration = creds['Expiration'] ? Time.iso8601(creds['Expiration']) : nil
|
227
|
+
return unless @expiration && @expiration < Time.now
|
228
|
+
|
229
|
+
@no_refresh_until = Time.now + rand(300..360)
|
230
|
+
warn_expired_credentials
|
231
|
+
end
|
232
|
+
|
225
233
|
def fetch_token(conn)
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
token_value, ttl = http_put(
|
230
|
-
conn, METADATA_TOKEN_PATH, @token_ttl
|
231
|
-
)
|
232
|
-
@token = Token.new(token_value, ttl, created_time) if token_value && ttl
|
233
|
-
end
|
234
|
-
end
|
234
|
+
created_time = Time.now
|
235
|
+
token_value, ttl = http_put(conn)
|
236
|
+
@token = Token.new(token_value, ttl, created_time) if token_value && ttl
|
235
237
|
rescue *NETWORK_ERRORS
|
236
238
|
# token attempt failed, reset token
|
237
239
|
# fallback to non-token mode
|
238
|
-
@token = nil
|
239
240
|
@imds_v1_fallback = true
|
240
241
|
end
|
241
242
|
|
242
|
-
|
243
|
-
|
244
|
-
metadata = http_get(conn, METADATA_PATH_BASE, token)
|
243
|
+
def fetch_credentials(conn)
|
244
|
+
metadata = http_get(conn, METADATA_PATH_BASE)
|
245
245
|
profile_name = metadata.lines.first.strip
|
246
|
-
http_get(conn, METADATA_PATH_BASE + profile_name
|
246
|
+
http_get(conn, METADATA_PATH_BASE + profile_name)
|
247
247
|
rescue TokenExpiredError
|
248
248
|
# Token has expired, reset it
|
249
249
|
# The next retry should fetch it
|
@@ -256,10 +256,6 @@ module Aws
|
|
256
256
|
@token && !@token.expired?
|
257
257
|
end
|
258
258
|
|
259
|
-
def _metadata_disabled?
|
260
|
-
ENV.fetch('AWS_EC2_METADATA_DISABLED', 'false').downcase == 'true'
|
261
|
-
end
|
262
|
-
|
263
259
|
def open_connection
|
264
260
|
uri = URI.parse(@endpoint)
|
265
261
|
http = Net::HTTP.new(uri.hostname || @endpoint, uri.port || @port)
|
@@ -271,9 +267,9 @@ module Aws
|
|
271
267
|
end
|
272
268
|
|
273
269
|
# GET request fetch profile and credentials
|
274
|
-
def http_get(connection, path
|
270
|
+
def http_get(connection, path)
|
275
271
|
headers = { 'User-Agent' => "aws-sdk-ruby3/#{CORE_GEM_VERSION}" }
|
276
|
-
headers['x-aws-ec2-metadata-token'] = token if token
|
272
|
+
headers['x-aws-ec2-metadata-token'] = @token.value if @token
|
277
273
|
response = connection.request(Net::HTTP::Get.new(path, headers))
|
278
274
|
|
279
275
|
case response.code.to_i
|
@@ -287,12 +283,12 @@ module Aws
|
|
287
283
|
end
|
288
284
|
|
289
285
|
# PUT request fetch token with ttl
|
290
|
-
def http_put(connection
|
286
|
+
def http_put(connection)
|
291
287
|
headers = {
|
292
288
|
'User-Agent' => "aws-sdk-ruby3/#{CORE_GEM_VERSION}",
|
293
|
-
'x-aws-ec2-metadata-token-ttl-seconds' =>
|
289
|
+
'x-aws-ec2-metadata-token-ttl-seconds' => @token_ttl.to_s
|
294
290
|
}
|
295
|
-
response = connection.request(Net::HTTP::Put.new(
|
291
|
+
response = connection.request(Net::HTTP::Put.new(METADATA_TOKEN_PATH, headers))
|
296
292
|
case response.code.to_i
|
297
293
|
when 200
|
298
294
|
[
|
@@ -321,18 +317,12 @@ module Aws
|
|
321
317
|
end
|
322
318
|
|
323
319
|
def warn_expired_credentials
|
324
|
-
warn(
|
325
|
-
|
326
|
-
"will be attempted again in 5 minutes.")
|
327
|
-
end
|
328
|
-
|
329
|
-
def empty_credentials?(creds)
|
330
|
-
!creds || !creds.access_key_id || creds.access_key_id.empty?
|
320
|
+
warn('Attempting credential expiration extension due to a credential service availability issue. '\
|
321
|
+
'A refresh of these credentials will be attempted again in 5 minutes.')
|
331
322
|
end
|
332
323
|
|
333
|
-
|
334
|
-
|
335
|
-
300 + rand(0..60)
|
324
|
+
def empty_credentials?(creds_hash)
|
325
|
+
!creds_hash['AccessKeyId'] || creds_hash['AccessKeyId'].empty?
|
336
326
|
end
|
337
327
|
|
338
328
|
# @api private
|
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
module Aws
|
4
4
|
module Json
|
5
|
+
# @api private
|
5
6
|
class ErrorHandler < Aws::ErrorHandler
|
6
7
|
|
7
8
|
def call(context)
|
@@ -24,18 +25,21 @@ module Aws
|
|
24
25
|
end
|
25
26
|
|
26
27
|
def error_code(json, context)
|
28
|
+
# This is not correct per protocol tests. awsQueryError is intended to populate the
|
29
|
+
# error code of the error class. The error class should come from __type. Query and
|
30
|
+
# query compatible services currently have dynamic errors raised from error codes instead
|
31
|
+
# of the modeled error class. However, changing this in this major version would break
|
32
|
+
# existing usage.
|
27
33
|
code =
|
28
34
|
if aws_query_error?(context)
|
29
|
-
|
30
|
-
error, _type = query_header.split(';') # type not supported
|
31
|
-
remove_prefix(error, context)
|
35
|
+
aws_query_error_code(context)
|
32
36
|
else
|
33
37
|
json['__type']
|
34
38
|
end
|
35
39
|
code ||= json['code']
|
36
40
|
code ||= context.http_response.headers['x-amzn-errortype']
|
37
41
|
if code
|
38
|
-
code.split('#').last
|
42
|
+
code.split('#').last.split(':').first
|
39
43
|
else
|
40
44
|
http_status_error_code(context)
|
41
45
|
end
|
@@ -46,6 +50,12 @@ module Aws
|
|
46
50
|
context.http_response.headers['x-amzn-query-error']
|
47
51
|
end
|
48
52
|
|
53
|
+
def aws_query_error_code(context)
|
54
|
+
query_header = context.http_response.headers['x-amzn-query-error']
|
55
|
+
error, _type = query_header.split(';') # type not supported
|
56
|
+
remove_prefix(error, context)
|
57
|
+
end
|
58
|
+
|
49
59
|
def remove_prefix(error_code, context)
|
50
60
|
if (prefix = context.config.api.metadata['errorPrefix'])
|
51
61
|
error_code.sub(/^#{prefix}/, '')
|
@@ -180,7 +180,6 @@ all generated client side metrics. Defaults to an empty string.
|
|
180
180
|
complete_opts = {
|
181
181
|
latency: end_time - start_time,
|
182
182
|
attempt_count: context.retries + 1,
|
183
|
-
user_agent: context.http_request.headers["user-agent"],
|
184
183
|
final_error_retryable: final_error_retryable,
|
185
184
|
final_http_status_code: context.http_response.status_code,
|
186
185
|
final_aws_exception: final_aws_exception,
|
@@ -14,64 +14,68 @@ module Aws
|
|
14
14
|
|
15
15
|
option(:account_id, doc_type: String, docstring: '')
|
16
16
|
|
17
|
-
option(
|
17
|
+
option(
|
18
|
+
:profile,
|
18
19
|
doc_default: 'default',
|
19
20
|
doc_type: String,
|
20
|
-
docstring:
|
21
|
-
Used when loading credentials from the shared credentials file
|
22
|
-
|
21
|
+
docstring: <<~DOCS)
|
22
|
+
Used when loading credentials from the shared credentials file at `HOME/.aws/credentials`.
|
23
|
+
When not specified, 'default' is used.
|
23
24
|
DOCS
|
24
25
|
|
25
|
-
option(
|
26
|
+
option(
|
27
|
+
:credentials,
|
26
28
|
required: true,
|
27
29
|
doc_type: 'Aws::CredentialProvider',
|
28
30
|
rbs_type: 'untyped',
|
29
|
-
docstring:
|
30
|
-
Your AWS credentials. This can be
|
31
|
-
following classes:
|
31
|
+
docstring: <<~DOCS
|
32
|
+
Your AWS credentials used for authentication. This can be any class that includes and implements
|
33
|
+
`Aws::CredentialProvider`, or instance of any one of the following classes:
|
32
34
|
|
33
|
-
* `Aws::Credentials` - Used for configuring static, non-refreshing
|
34
|
-
|
35
|
+
* `Aws::Credentials` - Used for configuring static, non-refreshing
|
36
|
+
credentials.
|
35
37
|
|
36
|
-
* `Aws::SharedCredentials` - Used for loading static credentials from a
|
37
|
-
|
38
|
+
* `Aws::SharedCredentials` - Used for loading static credentials from a
|
39
|
+
shared file, such as `~/.aws/config`.
|
38
40
|
|
39
|
-
* `Aws::AssumeRoleCredentials` - Used when you need to assume a role.
|
41
|
+
* `Aws::AssumeRoleCredentials` - Used when you need to assume a role.
|
40
42
|
|
41
|
-
* `Aws::AssumeRoleWebIdentityCredentials` - Used when you need to
|
42
|
-
|
43
|
+
* `Aws::AssumeRoleWebIdentityCredentials` - Used when you need to
|
44
|
+
assume a role after providing credentials via the web.
|
43
45
|
|
44
|
-
* `Aws::SSOCredentials` - Used for loading credentials from AWS SSO using an
|
45
|
-
|
46
|
+
* `Aws::SSOCredentials` - Used for loading credentials from AWS SSO using an
|
47
|
+
access token generated from `aws login`.
|
46
48
|
|
47
|
-
* `Aws::ProcessCredentials` - Used for loading credentials from a
|
48
|
-
|
49
|
+
* `Aws::ProcessCredentials` - Used for loading credentials from a
|
50
|
+
process that outputs to stdout.
|
49
51
|
|
50
|
-
* `Aws::InstanceProfileCredentials` - Used for loading credentials
|
51
|
-
|
52
|
+
* `Aws::InstanceProfileCredentials` - Used for loading credentials
|
53
|
+
from an EC2 IMDS on an EC2 instance.
|
52
54
|
|
53
|
-
* `Aws::ECSCredentials` - Used for loading credentials from
|
54
|
-
|
55
|
+
* `Aws::ECSCredentials` - Used for loading credentials from
|
56
|
+
instances running in ECS.
|
55
57
|
|
56
|
-
* `Aws::CognitoIdentityCredentials` - Used for loading credentials
|
57
|
-
|
58
|
+
* `Aws::CognitoIdentityCredentials` - Used for loading credentials
|
59
|
+
from the Cognito Identity service.
|
58
60
|
|
59
|
-
When `:credentials` are not configured directly, the following
|
60
|
-
locations will be searched for credentials:
|
61
|
+
When `:credentials` are not configured directly, the following locations will be searched for credentials:
|
61
62
|
|
62
|
-
* `Aws.config[:credentials]`
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
*
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
63
|
+
* `Aws.config[:credentials]`
|
64
|
+
|
65
|
+
* The `:access_key_id`, `:secret_access_key`, `:session_token`, and
|
66
|
+
`:account_id` options.
|
67
|
+
|
68
|
+
* `ENV['AWS_ACCESS_KEY_ID']`, `ENV['AWS_SECRET_ACCESS_KEY']`,
|
69
|
+
`ENV['AWS_SESSION_TOKEN']`, and `ENV['AWS_ACCOUNT_ID']`.
|
70
|
+
|
71
|
+
* `~/.aws/credentials`
|
72
|
+
|
73
|
+
* `~/.aws/config`
|
74
|
+
|
75
|
+
* EC2/ECS IMDS instance profile - When used by default, the timeouts are very aggressive.
|
76
|
+
Construct and pass an instance of `Aws::InstanceProfileCredentials` or `Aws::ECSCredentials` to
|
77
|
+
enable retries and extended timeouts. Instance profile credential fetching can be disabled by
|
78
|
+
setting `ENV['AWS_EC2_METADATA_DISABLED']` to `true`.
|
75
79
|
DOCS
|
76
80
|
) do |config|
|
77
81
|
CredentialProviderChain.new(config).resolve
|
@@ -81,31 +85,43 @@ locations will be searched for credentials:
|
|
81
85
|
|
82
86
|
option(:instance_profile_credentials_timeout, 1)
|
83
87
|
|
84
|
-
option(
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
following classes:
|
88
|
+
option(
|
89
|
+
:token_provider,
|
90
|
+
doc_type: 'Aws::TokenProvider',
|
91
|
+
rbs_type: 'untyped',
|
92
|
+
docstring: <<~DOCS
|
93
|
+
Your Bearer token used for authentication. This can be any class that includes and implements
|
94
|
+
`Aws::TokenProvider`, or instance of any one of the following classes:
|
91
95
|
|
92
|
-
* `Aws::StaticTokenProvider` - Used for configuring static, non-refreshing
|
93
|
-
|
96
|
+
* `Aws::StaticTokenProvider` - Used for configuring static, non-refreshing
|
97
|
+
tokens.
|
94
98
|
|
95
|
-
* `Aws::SSOTokenProvider` - Used for loading tokens from AWS SSO using an
|
96
|
-
|
99
|
+
* `Aws::SSOTokenProvider` - Used for loading tokens from AWS SSO using an
|
100
|
+
access token generated from `aws login`.
|
97
101
|
|
98
|
-
When `:token_provider` is not configured directly, the `Aws::TokenProviderChain`
|
99
|
-
will be used to search for tokens configured for your profile in shared configuration files.
|
100
|
-
|
102
|
+
When `:token_provider` is not configured directly, the `Aws::TokenProviderChain`
|
103
|
+
will be used to search for tokens configured for your profile in shared configuration files.
|
104
|
+
DOCS
|
101
105
|
) do |config|
|
102
|
-
|
103
|
-
StaticTokenProvider.new('token')
|
104
|
-
else
|
105
|
-
TokenProviderChain.new(config).resolve
|
106
|
-
end
|
106
|
+
TokenProviderChain.new(config).resolve
|
107
107
|
end
|
108
108
|
|
109
|
+
option(
|
110
|
+
:auth_scheme_preference,
|
111
|
+
doc_type: 'Array<String>',
|
112
|
+
rbs_type: 'Array[String]',
|
113
|
+
docstring: <<~DOCS
|
114
|
+
A list of preferred authentication schemes to use when making a request. Supported values are:
|
115
|
+
`sigv4`, `sigv4a`, `httpBearerAuth`, and `noAuth`. When set using `ENV['AWS_AUTH_SCHEME_PREFERENCE']` or in
|
116
|
+
shared config as `auth_scheme_preference`, the value should be a comma-separated list.
|
117
|
+
DOCS
|
118
|
+
) do |config|
|
119
|
+
value =
|
120
|
+
ENV['AWS_AUTH_SCHEME_PREFERENCE'] ||
|
121
|
+
Aws.shared_config.auth_scheme_preference(profile: config.profile) ||
|
122
|
+
''
|
123
|
+
value.gsub(' ', '').gsub("\t", '').split(',')
|
124
|
+
end
|
109
125
|
end
|
110
126
|
end
|
111
127
|
end
|