aws-sdk-core 3.100.0 → 3.130.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 +1294 -0
- data/LICENSE.txt +202 -0
- data/VERSION +1 -1
- data/lib/aws-defaults/default_configuration.rb +153 -0
- data/lib/aws-defaults/defaults_mode_config_resolver.rb +107 -0
- data/lib/aws-defaults.rb +3 -0
- data/lib/aws-sdk-core/arn.rb +15 -0
- data/lib/aws-sdk-core/arn_parser.rb +2 -0
- data/lib/aws-sdk-core/assume_role_credentials.rb +21 -0
- data/lib/aws-sdk-core/assume_role_web_identity_credentials.rb +9 -1
- data/lib/aws-sdk-core/async_client_stubs.rb +2 -0
- data/lib/aws-sdk-core/binary/decode_handler.rb +2 -0
- data/lib/aws-sdk-core/binary/encode_handler.rb +2 -0
- data/lib/aws-sdk-core/binary/event_builder.rb +2 -0
- data/lib/aws-sdk-core/binary/event_parser.rb +2 -0
- data/lib/aws-sdk-core/binary/event_stream_decoder.rb +2 -0
- data/lib/aws-sdk-core/binary/event_stream_encoder.rb +2 -0
- data/lib/aws-sdk-core/binary.rb +2 -0
- data/lib/aws-sdk-core/client_side_monitoring/publisher.rb +2 -0
- data/lib/aws-sdk-core/client_side_monitoring/request_metrics.rb +2 -0
- data/lib/aws-sdk-core/client_stubs.rb +7 -1
- data/lib/aws-sdk-core/credential_provider.rb +2 -0
- data/lib/aws-sdk-core/credential_provider_chain.rb +23 -1
- data/lib/aws-sdk-core/credentials.rb +2 -0
- data/lib/aws-sdk-core/deprecations.rb +2 -0
- data/lib/aws-sdk-core/eager_loader.rb +2 -0
- data/lib/aws-sdk-core/ec2_metadata.rb +238 -0
- data/lib/aws-sdk-core/ecs_credentials.rb +10 -4
- data/lib/aws-sdk-core/endpoint_cache.rb +2 -0
- data/lib/aws-sdk-core/errors.rb +11 -2
- data/lib/aws-sdk-core/event_emitter.rb +2 -0
- data/lib/aws-sdk-core/ini_parser.rb +2 -0
- data/lib/aws-sdk-core/instance_profile_credentials.rb +124 -22
- data/lib/aws-sdk-core/json/builder.rb +2 -0
- data/lib/aws-sdk-core/json/error_handler.rb +2 -0
- data/lib/aws-sdk-core/json/handler.rb +2 -0
- data/lib/aws-sdk-core/json/json_engine.rb +12 -8
- data/lib/aws-sdk-core/json/oj_engine.rb +35 -6
- data/lib/aws-sdk-core/json/parser.rb +10 -0
- data/lib/aws-sdk-core/json.rb +10 -26
- data/lib/aws-sdk-core/log/formatter.rb +9 -3
- data/lib/aws-sdk-core/log/handler.rb +2 -0
- data/lib/aws-sdk-core/log/param_filter.rb +37 -12
- data/lib/aws-sdk-core/log/param_formatter.rb +2 -0
- data/lib/aws-sdk-core/pageable_response.rb +82 -32
- data/lib/aws-sdk-core/pager.rb +5 -0
- data/lib/aws-sdk-core/param_converter.rb +2 -0
- data/lib/aws-sdk-core/param_validator.rb +54 -4
- data/lib/aws-sdk-core/plugins/api_key.rb +5 -1
- data/lib/aws-sdk-core/plugins/apig_authorizer_token.rb +2 -0
- data/lib/aws-sdk-core/plugins/apig_credentials_configuration.rb +2 -0
- data/lib/aws-sdk-core/plugins/apig_user_agent.rb +2 -0
- data/lib/aws-sdk-core/plugins/checksum_algorithm.rb +340 -0
- data/lib/aws-sdk-core/plugins/client_metrics_plugin.rb +2 -0
- data/lib/aws-sdk-core/plugins/client_metrics_send_plugin.rb +2 -0
- data/lib/aws-sdk-core/plugins/credentials_configuration.rb +26 -7
- data/lib/aws-sdk-core/plugins/defaults_mode.rb +40 -0
- data/lib/aws-sdk-core/plugins/endpoint_discovery.rb +2 -0
- data/lib/aws-sdk-core/plugins/endpoint_pattern.rb +8 -6
- data/lib/aws-sdk-core/plugins/event_stream_configuration.rb +2 -0
- data/lib/aws-sdk-core/plugins/global_configuration.rb +2 -0
- data/lib/aws-sdk-core/plugins/helpful_socket_errors.rb +2 -0
- data/lib/aws-sdk-core/plugins/http_checksum.rb +10 -1
- data/lib/aws-sdk-core/plugins/idempotency_token.rb +2 -0
- data/lib/aws-sdk-core/plugins/invocation_id.rb +2 -0
- data/lib/aws-sdk-core/plugins/jsonvalue_converter.rb +2 -0
- data/lib/aws-sdk-core/plugins/logging.rb +2 -0
- data/lib/aws-sdk-core/plugins/param_converter.rb +2 -0
- data/lib/aws-sdk-core/plugins/param_validator.rb +2 -0
- data/lib/aws-sdk-core/plugins/protocols/api_gateway.rb +19 -0
- data/lib/aws-sdk-core/plugins/protocols/ec2.rb +2 -0
- data/lib/aws-sdk-core/plugins/protocols/json_rpc.rb +2 -0
- data/lib/aws-sdk-core/plugins/protocols/query.rb +2 -0
- data/lib/aws-sdk-core/plugins/protocols/rest_json.rb +18 -1
- data/lib/aws-sdk-core/plugins/protocols/rest_xml.rb +2 -0
- data/lib/aws-sdk-core/plugins/recursion_detection.rb +27 -0
- data/lib/aws-sdk-core/plugins/regional_endpoint.rb +50 -2
- data/lib/aws-sdk-core/plugins/response_paging.rb +3 -1
- data/lib/aws-sdk-core/plugins/retries/client_rate_limiter.rb +2 -0
- data/lib/aws-sdk-core/plugins/retries/clock_skew.rb +2 -0
- data/lib/aws-sdk-core/plugins/retries/error_inspector.rb +7 -3
- data/lib/aws-sdk-core/plugins/retries/retry_quota.rb +2 -0
- data/lib/aws-sdk-core/plugins/retry_errors.rb +15 -6
- data/lib/aws-sdk-core/plugins/signature_v2.rb +2 -0
- data/lib/aws-sdk-core/plugins/signature_v4.rb +17 -24
- data/lib/aws-sdk-core/plugins/stub_responses.rb +9 -1
- data/lib/aws-sdk-core/plugins/transfer_encoding.rb +2 -0
- data/lib/aws-sdk-core/plugins/user_agent.rb +2 -0
- data/lib/aws-sdk-core/process_credentials.rb +8 -6
- data/lib/aws-sdk-core/query/ec2_param_builder.rb +2 -0
- data/lib/aws-sdk-core/query/handler.rb +2 -0
- data/lib/aws-sdk-core/query/param.rb +2 -0
- data/lib/aws-sdk-core/query/param_builder.rb +2 -0
- data/lib/aws-sdk-core/query/param_list.rb +2 -0
- data/lib/aws-sdk-core/query.rb +2 -0
- data/lib/aws-sdk-core/refreshing_credentials.rb +42 -11
- data/lib/aws-sdk-core/resources/collection.rb +2 -0
- data/lib/aws-sdk-core/rest/handler.rb +2 -0
- data/lib/aws-sdk-core/rest/request/body.rb +21 -1
- data/lib/aws-sdk-core/rest/request/builder.rb +2 -0
- data/lib/aws-sdk-core/rest/request/endpoint.rb +2 -0
- data/lib/aws-sdk-core/rest/request/headers.rb +20 -6
- data/lib/aws-sdk-core/rest/request/querystring_builder.rb +2 -0
- data/lib/aws-sdk-core/rest/response/body.rb +2 -0
- data/lib/aws-sdk-core/rest/response/headers.rb +6 -3
- data/lib/aws-sdk-core/rest/response/parser.rb +2 -0
- data/lib/aws-sdk-core/rest/response/status_code.rb +2 -0
- data/lib/aws-sdk-core/rest.rb +2 -0
- data/lib/aws-sdk-core/shared_config.rb +62 -8
- data/lib/aws-sdk-core/shared_credentials.rb +9 -1
- data/lib/aws-sdk-core/sso_credentials.rb +137 -0
- data/lib/aws-sdk-core/structure.rb +13 -2
- data/lib/aws-sdk-core/stubbing/data_applicator.rb +2 -0
- data/lib/aws-sdk-core/stubbing/empty_stub.rb +2 -0
- data/lib/aws-sdk-core/stubbing/protocols/api_gateway.rb +2 -0
- data/lib/aws-sdk-core/stubbing/protocols/ec2.rb +2 -0
- data/lib/aws-sdk-core/stubbing/protocols/json.rb +3 -1
- data/lib/aws-sdk-core/stubbing/protocols/query.rb +2 -0
- data/lib/aws-sdk-core/stubbing/protocols/rest.rb +3 -1
- data/lib/aws-sdk-core/stubbing/protocols/rest_json.rb +3 -1
- data/lib/aws-sdk-core/stubbing/protocols/rest_xml.rb +2 -2
- data/lib/aws-sdk-core/stubbing/stub_data.rb +2 -0
- data/lib/aws-sdk-core/stubbing/xml_error.rb +2 -0
- data/lib/aws-sdk-core/type_builder.rb +2 -0
- data/lib/aws-sdk-core/util.rb +2 -0
- data/lib/aws-sdk-core/waiters/errors.rb +2 -0
- data/lib/aws-sdk-core/waiters/poller.rb +2 -0
- data/lib/aws-sdk-core/waiters/waiter.rb +2 -0
- data/lib/aws-sdk-core/waiters.rb +2 -0
- data/lib/aws-sdk-core/xml/builder.rb +4 -2
- data/lib/aws-sdk-core/xml/default_list.rb +2 -0
- data/lib/aws-sdk-core/xml/default_map.rb +2 -0
- data/lib/aws-sdk-core/xml/doc_builder.rb +8 -1
- data/lib/aws-sdk-core/xml/error_handler.rb +2 -0
- data/lib/aws-sdk-core/xml/parser/engines/libxml.rb +2 -0
- data/lib/aws-sdk-core/xml/parser/engines/nokogiri.rb +2 -0
- data/lib/aws-sdk-core/xml/parser/engines/oga.rb +2 -0
- data/lib/aws-sdk-core/xml/parser/engines/ox.rb +3 -1
- data/lib/aws-sdk-core/xml/parser/engines/rexml.rb +2 -0
- data/lib/aws-sdk-core/xml/parser/frame.rb +25 -0
- data/lib/aws-sdk-core/xml/parser/parsing_error.rb +2 -0
- data/lib/aws-sdk-core/xml/parser/stack.rb +2 -0
- data/lib/aws-sdk-core/xml/parser.rb +7 -0
- data/lib/aws-sdk-core/xml.rb +2 -0
- data/lib/aws-sdk-core.rb +15 -3
- data/lib/aws-sdk-sso/client.rb +570 -0
- data/lib/aws-sdk-sso/client_api.rb +190 -0
- data/lib/aws-sdk-sso/customizations.rb +1 -0
- data/lib/aws-sdk-sso/errors.rb +102 -0
- data/lib/aws-sdk-sso/resource.rb +26 -0
- data/lib/aws-sdk-sso/types.rb +352 -0
- data/lib/aws-sdk-sso.rb +55 -0
- data/lib/aws-sdk-sts/client.rb +538 -435
- data/lib/aws-sdk-sts/client_api.rb +9 -1
- data/lib/aws-sdk-sts/customizations.rb +2 -0
- data/lib/aws-sdk-sts/errors.rb +3 -1
- data/lib/aws-sdk-sts/plugins/sts_regional_endpoints.rb +7 -1
- data/lib/aws-sdk-sts/presigner.rb +9 -1
- data/lib/aws-sdk-sts/resource.rb +3 -1
- data/lib/aws-sdk-sts/types.rb +360 -191
- data/lib/aws-sdk-sts.rb +10 -3
- data/lib/seahorse/client/async_base.rb +2 -0
- data/lib/seahorse/client/async_response.rb +2 -0
- data/lib/seahorse/client/base.rb +3 -0
- data/lib/seahorse/client/block_io.rb +5 -2
- data/lib/seahorse/client/configuration.rb +6 -0
- data/lib/seahorse/client/events.rb +2 -0
- data/lib/seahorse/client/h2/connection.rb +17 -13
- data/lib/seahorse/client/h2/handler.rb +6 -5
- data/lib/seahorse/client/handler.rb +2 -0
- data/lib/seahorse/client/handler_builder.rb +2 -0
- data/lib/seahorse/client/handler_list.rb +2 -0
- data/lib/seahorse/client/handler_list_entry.rb +2 -0
- data/lib/seahorse/client/http/async_response.rb +2 -0
- data/lib/seahorse/client/http/headers.rb +2 -0
- data/lib/seahorse/client/http/request.rb +2 -0
- data/lib/seahorse/client/http/response.rb +3 -1
- data/lib/seahorse/client/logging/formatter.rb +2 -0
- data/lib/seahorse/client/logging/handler.rb +2 -0
- data/lib/seahorse/client/managed_file.rb +2 -0
- data/lib/seahorse/client/net_http/connection_pool.rb +12 -4
- data/lib/seahorse/client/net_http/handler.rb +19 -8
- data/lib/seahorse/client/net_http/patches.rb +15 -84
- data/lib/seahorse/client/networking_error.rb +2 -0
- data/lib/seahorse/client/plugin.rb +2 -0
- data/lib/seahorse/client/plugin_list.rb +2 -0
- data/lib/seahorse/client/plugins/content_length.rb +13 -5
- data/lib/seahorse/client/plugins/endpoint.rb +2 -0
- data/lib/seahorse/client/plugins/h2.rb +6 -1
- data/lib/seahorse/client/plugins/logging.rb +2 -0
- data/lib/seahorse/client/plugins/net_http.rb +39 -3
- data/lib/seahorse/client/plugins/operation_methods.rb +2 -0
- data/lib/seahorse/client/plugins/raise_response_errors.rb +2 -0
- data/lib/seahorse/client/plugins/request_callback.rb +110 -0
- data/lib/seahorse/client/plugins/response_target.rb +8 -8
- data/lib/seahorse/client/request.rb +2 -0
- data/lib/seahorse/client/request_context.rb +2 -0
- data/lib/seahorse/client/response.rb +2 -0
- data/lib/seahorse/model/api.rb +2 -0
- data/lib/seahorse/model/authorizer.rb +2 -0
- data/lib/seahorse/model/operation.rb +5 -0
- data/lib/seahorse/model/shapes.rb +27 -0
- data/lib/seahorse/util.rb +8 -1
- data/lib/seahorse/version.rb +2 -0
- data/lib/seahorse.rb +3 -0
- metadata +26 -9
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require 'thread'
|
|
2
4
|
|
|
3
5
|
module Aws
|
|
@@ -260,13 +262,17 @@ module Aws
|
|
|
260
262
|
end
|
|
261
263
|
|
|
262
264
|
def convert_stub(operation_name, stub)
|
|
263
|
-
case stub
|
|
265
|
+
stub = case stub
|
|
264
266
|
when Proc then stub
|
|
265
267
|
when Exception, Class then { error: stub }
|
|
266
268
|
when String then service_error_stub(stub)
|
|
267
269
|
when Hash then http_response_stub(operation_name, stub)
|
|
268
270
|
else { data: stub }
|
|
269
271
|
end
|
|
272
|
+
if Hash === stub
|
|
273
|
+
stub[:mutex] = Mutex.new
|
|
274
|
+
end
|
|
275
|
+
stub
|
|
270
276
|
end
|
|
271
277
|
|
|
272
278
|
def service_error_stub(error_code)
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module Aws
|
|
2
4
|
# @api private
|
|
3
5
|
class CredentialProviderChain
|
|
@@ -20,11 +22,13 @@ module Aws
|
|
|
20
22
|
[
|
|
21
23
|
[:static_credentials, {}],
|
|
22
24
|
[:static_profile_assume_role_web_identity_credentials, {}],
|
|
25
|
+
[:static_profile_sso_credentials, {}],
|
|
23
26
|
[:static_profile_assume_role_credentials, {}],
|
|
24
27
|
[:static_profile_credentials, {}],
|
|
25
28
|
[:static_profile_process_credentials, {}],
|
|
26
29
|
[:env_credentials, {}],
|
|
27
30
|
[:assume_role_web_identity_credentials, {}],
|
|
31
|
+
[:sso_credentials, {}],
|
|
28
32
|
[:assume_role_credentials, {}],
|
|
29
33
|
[:shared_credentials, {}],
|
|
30
34
|
[:process_credentials, {}],
|
|
@@ -55,6 +59,14 @@ module Aws
|
|
|
55
59
|
end
|
|
56
60
|
end
|
|
57
61
|
|
|
62
|
+
def static_profile_sso_credentials(options)
|
|
63
|
+
if Aws.shared_config.config_enabled? && options[:config] && options[:config].profile
|
|
64
|
+
Aws.shared_config.sso_credentials_from_config(
|
|
65
|
+
profile: options[:config].profile
|
|
66
|
+
)
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
58
70
|
def static_profile_assume_role_credentials(options)
|
|
59
71
|
if Aws.shared_config.config_enabled? && options[:config] && options[:config].profile
|
|
60
72
|
assume_role_with_profile(options, options[:config].profile)
|
|
@@ -113,6 +125,15 @@ module Aws
|
|
|
113
125
|
nil
|
|
114
126
|
end
|
|
115
127
|
|
|
128
|
+
def sso_credentials(options)
|
|
129
|
+
profile_name = determine_profile_name(options)
|
|
130
|
+
if Aws.shared_config.config_enabled?
|
|
131
|
+
Aws.shared_config.sso_credentials_from_config(profile: profile_name)
|
|
132
|
+
end
|
|
133
|
+
rescue Errors::NoSuchProfileError
|
|
134
|
+
nil
|
|
135
|
+
end
|
|
136
|
+
|
|
116
137
|
def assume_role_credentials(options)
|
|
117
138
|
if Aws.shared_config.config_enabled?
|
|
118
139
|
assume_role_with_profile(options, determine_profile_name(options))
|
|
@@ -139,10 +160,11 @@ module Aws
|
|
|
139
160
|
end
|
|
140
161
|
|
|
141
162
|
def instance_profile_credentials(options)
|
|
163
|
+
profile_name = determine_profile_name(options)
|
|
142
164
|
if ENV['AWS_CONTAINER_CREDENTIALS_RELATIVE_URI']
|
|
143
165
|
ECSCredentials.new(options)
|
|
144
166
|
else
|
|
145
|
-
InstanceProfileCredentials.new(options)
|
|
167
|
+
InstanceProfileCredentials.new(options.merge(profile: profile_name))
|
|
146
168
|
end
|
|
147
169
|
end
|
|
148
170
|
|
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'time'
|
|
4
|
+
require 'net/http'
|
|
5
|
+
|
|
6
|
+
module Aws
|
|
7
|
+
# A client that can query version 2 of the EC2 Instance Metadata
|
|
8
|
+
class EC2Metadata
|
|
9
|
+
# Path for PUT request for token
|
|
10
|
+
# @api private
|
|
11
|
+
METADATA_TOKEN_PATH = '/latest/api/token'.freeze
|
|
12
|
+
|
|
13
|
+
# Raised when the PUT request is not valid. This would be thrown if
|
|
14
|
+
# `token_ttl` is not an Integer.
|
|
15
|
+
# @api private
|
|
16
|
+
class TokenRetrievalError < RuntimeError; end
|
|
17
|
+
|
|
18
|
+
# Token has expired, and the request can be retried with a new token.
|
|
19
|
+
# @api private
|
|
20
|
+
class TokenExpiredError < RuntimeError; end
|
|
21
|
+
|
|
22
|
+
# The requested metadata path does not exist.
|
|
23
|
+
# @api private
|
|
24
|
+
class MetadataNotFoundError < RuntimeError; end
|
|
25
|
+
|
|
26
|
+
# The request is not allowed or IMDS is turned off.
|
|
27
|
+
# @api private
|
|
28
|
+
class RequestForbiddenError < RuntimeError; end
|
|
29
|
+
|
|
30
|
+
# Creates a client that can query version 2 of the EC2 Instance Metadata
|
|
31
|
+
# service (IMDS).
|
|
32
|
+
#
|
|
33
|
+
# @note Customers using containers may need to increase their hop limit
|
|
34
|
+
# to access IMDSv2.
|
|
35
|
+
# @see https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html#instance-metadata-transition-to-version-2
|
|
36
|
+
#
|
|
37
|
+
# @param [Hash] options
|
|
38
|
+
# @option options [Integer] :token_ttl (21600) The session token's TTL,
|
|
39
|
+
# defaulting to 6 hours.
|
|
40
|
+
# @option options [Integer] :retries (3) The number of retries for failed
|
|
41
|
+
# requests.
|
|
42
|
+
# @option options [String] :endpoint ('http://169.254.169.254') The IMDS
|
|
43
|
+
# endpoint. This option has precedence over the :endpoint_mode.
|
|
44
|
+
# @option options [String] :endpoint_mode ('IPv4') The endpoint mode for
|
|
45
|
+
# the instance metadata service. This is either 'IPv4'
|
|
46
|
+
# ('http://169.254.169.254') or 'IPv6' ('http://[fd00:ec2::254]').
|
|
47
|
+
# @option options [Integer] :port (80) The IMDS endpoint port.
|
|
48
|
+
# @option options [Integer] :http_open_timeout (1) The number of seconds to
|
|
49
|
+
# wait for the connection to open.
|
|
50
|
+
# @option options [Integer] :http_read_timeout (1) The number of seconds for
|
|
51
|
+
# one chunk of data to be read.
|
|
52
|
+
# @option options [IO] :http_debug_output An output stream for debugging. Do
|
|
53
|
+
# not use this in production.
|
|
54
|
+
# @option options [Integer,Proc] :backoff A backoff used for retryable
|
|
55
|
+
# requests. When given an Integer, it sleeps that amount. When given a
|
|
56
|
+
# Proc, it is called with the current number of failed retries.
|
|
57
|
+
def initialize(options = {})
|
|
58
|
+
@token_ttl = options[:token_ttl] || 21_600
|
|
59
|
+
@retries = options[:retries] || 3
|
|
60
|
+
@backoff = backoff(options[:backoff])
|
|
61
|
+
|
|
62
|
+
endpoint_mode = options[:endpoint_mode] || 'IPv4'
|
|
63
|
+
@endpoint = resolve_endpoint(options[:endpoint], endpoint_mode)
|
|
64
|
+
@port = options[:port] || 80
|
|
65
|
+
|
|
66
|
+
@http_open_timeout = options[:http_open_timeout] || 1
|
|
67
|
+
@http_read_timeout = options[:http_read_timeout] || 1
|
|
68
|
+
@http_debug_output = options[:http_debug_output]
|
|
69
|
+
|
|
70
|
+
@token = nil
|
|
71
|
+
@mutex = Mutex.new
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
# Fetches a given metadata category using a String path, and returns the
|
|
75
|
+
# result as a String. A path starts with the API version (usually
|
|
76
|
+
# "/latest/"). See the instance data categories for possible paths.
|
|
77
|
+
#
|
|
78
|
+
# @example Fetching the instance ID
|
|
79
|
+
#
|
|
80
|
+
# ec2_metadata = Aws::EC2Metadata.new
|
|
81
|
+
# ec2_metadata.get('/latest/meta-data/instance-id')
|
|
82
|
+
# => "i-023a25f10a73a0f79"
|
|
83
|
+
#
|
|
84
|
+
# @note This implementation always returns a String and will not parse any
|
|
85
|
+
# responses. Parsable responses may include JSON objects or directory
|
|
86
|
+
# listings, which are strings separated by line feeds (ASCII 10).
|
|
87
|
+
#
|
|
88
|
+
# @example Fetching and parsing JSON meta-data
|
|
89
|
+
#
|
|
90
|
+
# require 'json'
|
|
91
|
+
# data = ec2_metadata.get('/latest/dynamic/instance-identity/document')
|
|
92
|
+
# JSON.parse(data)
|
|
93
|
+
# => {"accountId"=>"012345678912", ... }
|
|
94
|
+
#
|
|
95
|
+
# @example Fetching and parsing directory listings
|
|
96
|
+
#
|
|
97
|
+
# listing = ec2_metadata.get('/latest/meta-data')
|
|
98
|
+
# listing.split(10.chr)
|
|
99
|
+
# => ["ami-id", "ami-launch-index", ...]
|
|
100
|
+
#
|
|
101
|
+
# @note Unlike other services, IMDS does not have a service API model. This
|
|
102
|
+
# means that we cannot confidently generate code with methods and
|
|
103
|
+
# response structures. This implementation ensures that new IMDS features
|
|
104
|
+
# are always supported by being deployed to the instance and does not
|
|
105
|
+
# require code changes.
|
|
106
|
+
#
|
|
107
|
+
# @see https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instancedata-data-categories.html
|
|
108
|
+
# @see https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instance-identity-documents.html
|
|
109
|
+
# @param [String] path The full path to the metadata.
|
|
110
|
+
def get(path)
|
|
111
|
+
retry_errors(max_retries: @retries) do
|
|
112
|
+
@mutex.synchronize do
|
|
113
|
+
fetch_token unless @token && !@token.expired?
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
open_connection do |conn|
|
|
117
|
+
http_get(conn, path, @token.value)
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
private
|
|
123
|
+
|
|
124
|
+
def resolve_endpoint(endpoint, endpoint_mode)
|
|
125
|
+
return endpoint if endpoint
|
|
126
|
+
|
|
127
|
+
case endpoint_mode.downcase
|
|
128
|
+
when 'ipv4' then 'http://169.254.169.254'
|
|
129
|
+
when 'ipv6' then 'http://[fd00:ec2::254]'
|
|
130
|
+
else
|
|
131
|
+
raise ArgumentError,
|
|
132
|
+
':endpoint_mode is not valid, expected IPv4 or IPv6, '\
|
|
133
|
+
"got: #{endpoint_mode}"
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
def fetch_token
|
|
138
|
+
open_connection do |conn|
|
|
139
|
+
created_time = Time.now
|
|
140
|
+
token_value, token_ttl = http_put(conn, @token_ttl)
|
|
141
|
+
@token = Token.new(value: token_value, ttl: token_ttl, created_time: created_time)
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
def http_get(connection, path, token)
|
|
146
|
+
headers = {
|
|
147
|
+
'User-Agent' => "aws-sdk-ruby3/#{CORE_GEM_VERSION}",
|
|
148
|
+
'x-aws-ec2-metadata-token' => token
|
|
149
|
+
}
|
|
150
|
+
request = Net::HTTP::Get.new(path, headers)
|
|
151
|
+
response = connection.request(request)
|
|
152
|
+
|
|
153
|
+
case response.code.to_i
|
|
154
|
+
when 200
|
|
155
|
+
response.body
|
|
156
|
+
when 401
|
|
157
|
+
raise TokenExpiredError
|
|
158
|
+
when 404
|
|
159
|
+
raise MetadataNotFoundError
|
|
160
|
+
end
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
def http_put(connection, ttl)
|
|
164
|
+
headers = {
|
|
165
|
+
'User-Agent' => "aws-sdk-ruby3/#{CORE_GEM_VERSION}",
|
|
166
|
+
'x-aws-ec2-metadata-token-ttl-seconds' => ttl.to_s
|
|
167
|
+
}
|
|
168
|
+
request = Net::HTTP::Put.new(METADATA_TOKEN_PATH, headers)
|
|
169
|
+
response = connection.request(request)
|
|
170
|
+
|
|
171
|
+
case response.code.to_i
|
|
172
|
+
when 200
|
|
173
|
+
[
|
|
174
|
+
response.body,
|
|
175
|
+
response.header['x-aws-ec2-metadata-token-ttl-seconds'].to_i
|
|
176
|
+
]
|
|
177
|
+
when 400
|
|
178
|
+
raise TokenRetrievalError
|
|
179
|
+
when 403
|
|
180
|
+
raise RequestForbiddenError
|
|
181
|
+
end
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
def open_connection
|
|
185
|
+
uri = URI.parse(@endpoint)
|
|
186
|
+
http = Net::HTTP.new(uri.hostname || @endpoint, @port || uri.port)
|
|
187
|
+
http.open_timeout = @http_open_timeout
|
|
188
|
+
http.read_timeout = @http_read_timeout
|
|
189
|
+
http.set_debug_output(@http_debug_output) if @http_debug_output
|
|
190
|
+
http.start
|
|
191
|
+
yield(http).tap { http.finish }
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
def retry_errors(options = {}, &_block)
|
|
195
|
+
max_retries = options[:max_retries]
|
|
196
|
+
retries = 0
|
|
197
|
+
begin
|
|
198
|
+
yield
|
|
199
|
+
# These errors should not be retried.
|
|
200
|
+
rescue TokenRetrievalError, MetadataNotFoundError, RequestForbiddenError
|
|
201
|
+
raise
|
|
202
|
+
# StandardError is not ideal but it covers Net::HTTP errors.
|
|
203
|
+
# https://gist.github.com/tenderlove/245188
|
|
204
|
+
rescue StandardError, TokenExpiredError
|
|
205
|
+
raise unless retries < max_retries
|
|
206
|
+
|
|
207
|
+
@backoff.call(retries)
|
|
208
|
+
retries += 1
|
|
209
|
+
retry
|
|
210
|
+
end
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
def backoff(backoff)
|
|
214
|
+
case backoff
|
|
215
|
+
when Proc then backoff
|
|
216
|
+
when Numeric then ->(_) { Kernel.sleep(backoff) }
|
|
217
|
+
else ->(num_failures) { Kernel.sleep(1.2**num_failures) }
|
|
218
|
+
end
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
# @api private
|
|
222
|
+
class Token
|
|
223
|
+
def initialize(options = {})
|
|
224
|
+
@ttl = options[:ttl]
|
|
225
|
+
@value = options[:value]
|
|
226
|
+
@created_time = options[:created_time] || Time.now
|
|
227
|
+
end
|
|
228
|
+
|
|
229
|
+
# [String] Returns the token value.
|
|
230
|
+
attr_reader :value
|
|
231
|
+
|
|
232
|
+
# [Boolean] Returns true if the token expired.
|
|
233
|
+
def expired?
|
|
234
|
+
Time.now - @created_time > @ttl
|
|
235
|
+
end
|
|
236
|
+
end
|
|
237
|
+
end
|
|
238
|
+
end
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
2
3
|
require 'time'
|
|
3
4
|
require 'net/http'
|
|
4
5
|
|
|
@@ -42,6 +43,10 @@ module Aws
|
|
|
42
43
|
# @option options [IO] :http_debug_output (nil) HTTP wire
|
|
43
44
|
# traces are sent to this object. You can specify something
|
|
44
45
|
# like $stdout.
|
|
46
|
+
# @option options [Callable] before_refresh Proc called before
|
|
47
|
+
# credentials are refreshed. `before_refresh` is called
|
|
48
|
+
# with an instance of this object when
|
|
49
|
+
# AWS credentials are required and need to be refreshed.
|
|
45
50
|
def initialize options = {}
|
|
46
51
|
@retries = options[:retries] || 5
|
|
47
52
|
@ip_address = options[:ip_address] || '169.254.170.2'
|
|
@@ -57,6 +62,7 @@ module Aws
|
|
|
57
62
|
@http_read_timeout = options[:http_read_timeout] || 5
|
|
58
63
|
@http_debug_output = options[:http_debug_output]
|
|
59
64
|
@backoff = backoff(options[:backoff])
|
|
65
|
+
@async_refresh = false
|
|
60
66
|
super
|
|
61
67
|
end
|
|
62
68
|
|
|
@@ -79,8 +85,8 @@ module Aws
|
|
|
79
85
|
# service is responding but is returning invalid JSON documents
|
|
80
86
|
# in response to the GET profile credentials call.
|
|
81
87
|
begin
|
|
82
|
-
retry_errors([
|
|
83
|
-
c =
|
|
88
|
+
retry_errors([Aws::Json::ParseError, StandardError], max_retries: 3) do
|
|
89
|
+
c = Aws::Json.load(get_credentials.to_s)
|
|
84
90
|
@credentials = Credentials.new(
|
|
85
91
|
c['AccessKeyId'],
|
|
86
92
|
c['SecretAccessKey'],
|
|
@@ -88,7 +94,7 @@ module Aws
|
|
|
88
94
|
)
|
|
89
95
|
@expiration = c['Expiration'] ? Time.iso8601(c['Expiration']) : nil
|
|
90
96
|
end
|
|
91
|
-
rescue
|
|
97
|
+
rescue Aws::Json::ParseError
|
|
92
98
|
raise Aws::Errors::MetadataParserError.new
|
|
93
99
|
end
|
|
94
100
|
end
|
data/lib/aws-sdk-core/errors.rb
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module Aws
|
|
2
4
|
module Errors
|
|
3
5
|
|
|
@@ -14,10 +16,10 @@ module Aws
|
|
|
14
16
|
# @param [Aws::Structure] data
|
|
15
17
|
def initialize(context, message, data = Aws::EmptyStructure.new)
|
|
16
18
|
@code = self.class.code
|
|
17
|
-
@message = message if message && !message.empty?
|
|
18
19
|
@context = context
|
|
19
20
|
@data = data
|
|
20
|
-
|
|
21
|
+
@message = message && !message.empty? ? message : self.class.to_s
|
|
22
|
+
super(@message)
|
|
21
23
|
end
|
|
22
24
|
|
|
23
25
|
# @return [String]
|
|
@@ -205,6 +207,13 @@ module Aws
|
|
|
205
207
|
# payload with either invalid version number or malformed contents
|
|
206
208
|
class InvalidProcessCredentialsPayload < RuntimeError; end
|
|
207
209
|
|
|
210
|
+
# Raised when SSO Credentials are invalid
|
|
211
|
+
class InvalidSSOCredentials < RuntimeError; end
|
|
212
|
+
|
|
213
|
+
# Raised when there is a circular reference in chained
|
|
214
|
+
# source_profiles
|
|
215
|
+
class SourceProfileCircularReferenceError < RuntimeError; end
|
|
216
|
+
|
|
208
217
|
# Raised when a client is constructed and region is not specified.
|
|
209
218
|
class MissingRegionError < ArgumentError
|
|
210
219
|
def initialize(*args)
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
2
3
|
require 'time'
|
|
3
4
|
require 'net/http'
|
|
4
5
|
|
|
5
6
|
module Aws
|
|
6
7
|
class InstanceProfileCredentials
|
|
7
|
-
|
|
8
8
|
include CredentialProvider
|
|
9
9
|
include RefreshingCredentials
|
|
10
10
|
|
|
@@ -43,7 +43,13 @@ module Aws
|
|
|
43
43
|
# @param [Hash] options
|
|
44
44
|
# @option options [Integer] :retries (1) Number of times to retry
|
|
45
45
|
# when retrieving credentials.
|
|
46
|
-
# @option options [String] :
|
|
46
|
+
# @option options [String] :endpoint ('http://169.254.169.254') The IMDS
|
|
47
|
+
# endpoint. This option has precedence over the :endpoint_mode.
|
|
48
|
+
# @option options [String] :endpoint_mode ('IPv4') The endpoint mode for
|
|
49
|
+
# the instance metadata service. This is either 'IPv4' ('169.254.169.254')
|
|
50
|
+
# or 'IPv6' ('[fd00:ec2::254]').
|
|
51
|
+
# @option options [String] :ip_address ('169.254.169.254') Deprecated. Use
|
|
52
|
+
# :endpoint instead. The IP address for the endpoint.
|
|
47
53
|
# @option options [Integer] :port (80)
|
|
48
54
|
# @option options [Float] :http_open_timeout (1)
|
|
49
55
|
# @option options [Float] :http_read_timeout (1)
|
|
@@ -57,9 +63,14 @@ module Aws
|
|
|
57
63
|
# @option options [Integer] :token_ttl Time-to-Live in seconds for EC2
|
|
58
64
|
# Metadata Token used for fetching Metadata Profile Credentials, defaults
|
|
59
65
|
# to 21600 seconds
|
|
66
|
+
# @option options [Callable] before_refresh Proc called before
|
|
67
|
+
# credentials are refreshed. `before_refresh` is called
|
|
68
|
+
# with an instance of this object when
|
|
69
|
+
# AWS credentials are required and need to be refreshed.
|
|
60
70
|
def initialize(options = {})
|
|
61
71
|
@retries = options[:retries] || 1
|
|
62
|
-
|
|
72
|
+
endpoint_mode = resolve_endpoint_mode(options)
|
|
73
|
+
@endpoint = resolve_endpoint(options, endpoint_mode)
|
|
63
74
|
@port = options[:port] || 80
|
|
64
75
|
@http_open_timeout = options[:http_open_timeout] || 1
|
|
65
76
|
@http_read_timeout = options[:http_read_timeout] || 1
|
|
@@ -67,6 +78,8 @@ module Aws
|
|
|
67
78
|
@backoff = backoff(options[:backoff])
|
|
68
79
|
@token_ttl = options[:token_ttl] || 21_600
|
|
69
80
|
@token = nil
|
|
81
|
+
@no_refresh_until = nil
|
|
82
|
+
@async_refresh = false
|
|
70
83
|
super
|
|
71
84
|
end
|
|
72
85
|
|
|
@@ -77,6 +90,34 @@ module Aws
|
|
|
77
90
|
|
|
78
91
|
private
|
|
79
92
|
|
|
93
|
+
def resolve_endpoint_mode(options)
|
|
94
|
+
value = options[:endpoint_mode]
|
|
95
|
+
value ||= ENV['AWS_EC2_METADATA_SERVICE_ENDPOINT_MODE']
|
|
96
|
+
value ||= Aws.shared_config.ec2_metadata_service_endpoint_mode(
|
|
97
|
+
profile: options[:profile]
|
|
98
|
+
)
|
|
99
|
+
value || 'IPv4'
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def resolve_endpoint(options, endpoint_mode)
|
|
103
|
+
value = options[:endpoint] || options[:ip_address]
|
|
104
|
+
value ||= ENV['AWS_EC2_METADATA_SERVICE_ENDPOINT']
|
|
105
|
+
value ||= Aws.shared_config.ec2_metadata_service_endpoint(
|
|
106
|
+
profile: options[:profile]
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
return value if value
|
|
110
|
+
|
|
111
|
+
case endpoint_mode.downcase
|
|
112
|
+
when 'ipv4' then 'http://169.254.169.254'
|
|
113
|
+
when 'ipv6' then 'http://[fd00:ec2::254]'
|
|
114
|
+
else
|
|
115
|
+
raise ArgumentError,
|
|
116
|
+
':endpoint_mode is not valid, expected IPv4 or IPv6, '\
|
|
117
|
+
"got: #{endpoint_mode}"
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
|
|
80
121
|
def backoff(backoff)
|
|
81
122
|
case backoff
|
|
82
123
|
when Proc then backoff
|
|
@@ -86,20 +127,50 @@ module Aws
|
|
|
86
127
|
end
|
|
87
128
|
|
|
88
129
|
def refresh
|
|
130
|
+
if @no_refresh_until && @no_refresh_until > Time.now
|
|
131
|
+
warn_expired_credentials
|
|
132
|
+
return
|
|
133
|
+
end
|
|
134
|
+
|
|
89
135
|
# Retry loading credentials up to 3 times is the instance metadata
|
|
90
136
|
# service is responding but is returning invalid JSON documents
|
|
91
137
|
# in response to the GET profile credentials call.
|
|
92
138
|
begin
|
|
93
|
-
retry_errors([
|
|
94
|
-
c =
|
|
95
|
-
@credentials
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
139
|
+
retry_errors([Aws::Json::ParseError, StandardError], max_retries: 3) do
|
|
140
|
+
c = Aws::Json.load(get_credentials.to_s)
|
|
141
|
+
if empty_credentials?(@credentials)
|
|
142
|
+
@credentials = Credentials.new(
|
|
143
|
+
c['AccessKeyId'],
|
|
144
|
+
c['SecretAccessKey'],
|
|
145
|
+
c['Token']
|
|
146
|
+
)
|
|
147
|
+
@expiration = c['Expiration'] ? Time.iso8601(c['Expiration']) : nil
|
|
148
|
+
if @expiration && @expiration < Time.now
|
|
149
|
+
@no_refresh_until = Time.now + refresh_offset
|
|
150
|
+
warn_expired_credentials
|
|
151
|
+
end
|
|
152
|
+
else
|
|
153
|
+
# credentials are already set, update them only if the new ones are not empty
|
|
154
|
+
if !c['AccessKeyId'] || c['AccessKeyId'].empty?
|
|
155
|
+
# error getting new credentials
|
|
156
|
+
@no_refresh_until = Time.now + refresh_offset
|
|
157
|
+
warn_expired_credentials
|
|
158
|
+
else
|
|
159
|
+
@credentials = Credentials.new(
|
|
160
|
+
c['AccessKeyId'],
|
|
161
|
+
c['SecretAccessKey'],
|
|
162
|
+
c['Token']
|
|
163
|
+
)
|
|
164
|
+
@expiration = c['Expiration'] ? Time.iso8601(c['Expiration']) : nil
|
|
165
|
+
if @expiration && @expiration < Time.now
|
|
166
|
+
@no_refresh_until = Time.now + refresh_offset
|
|
167
|
+
warn_expired_credentials
|
|
168
|
+
end
|
|
169
|
+
end
|
|
170
|
+
end
|
|
171
|
+
|
|
101
172
|
end
|
|
102
|
-
rescue
|
|
173
|
+
rescue Aws::Json::ParseError
|
|
103
174
|
raise Aws::Errors::MetadataParserError
|
|
104
175
|
end
|
|
105
176
|
end
|
|
@@ -118,10 +189,11 @@ module Aws
|
|
|
118
189
|
begin
|
|
119
190
|
retry_errors(NETWORK_ERRORS, max_retries: @retries) do
|
|
120
191
|
unless token_set?
|
|
192
|
+
created_time = Time.now
|
|
121
193
|
token_value, ttl = http_put(
|
|
122
194
|
conn, METADATA_TOKEN_PATH, @token_ttl
|
|
123
195
|
)
|
|
124
|
-
@token = Token.new(token_value, ttl) if token_value && ttl
|
|
196
|
+
@token = Token.new(token_value, ttl, created_time) if token_value && ttl
|
|
125
197
|
end
|
|
126
198
|
end
|
|
127
199
|
rescue *NETWORK_ERRORS
|
|
@@ -131,9 +203,17 @@ module Aws
|
|
|
131
203
|
end
|
|
132
204
|
|
|
133
205
|
token = @token.value if token_set?
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
206
|
+
|
|
207
|
+
begin
|
|
208
|
+
metadata = http_get(conn, METADATA_PATH_BASE, token)
|
|
209
|
+
profile_name = metadata.lines.first.strip
|
|
210
|
+
http_get(conn, METADATA_PATH_BASE + profile_name, token)
|
|
211
|
+
rescue TokenExpiredError
|
|
212
|
+
# Token has expired, reset it
|
|
213
|
+
# The next retry should fetch it
|
|
214
|
+
@token = nil
|
|
215
|
+
raise Non200Response
|
|
216
|
+
end
|
|
137
217
|
end
|
|
138
218
|
end
|
|
139
219
|
rescue
|
|
@@ -151,7 +231,8 @@ module Aws
|
|
|
151
231
|
end
|
|
152
232
|
|
|
153
233
|
def open_connection
|
|
154
|
-
|
|
234
|
+
uri = URI.parse(@endpoint)
|
|
235
|
+
http = Net::HTTP.new(uri.hostname || @endpoint, @port || uri.port)
|
|
155
236
|
http.open_timeout = @http_open_timeout
|
|
156
237
|
http.read_timeout = @http_read_timeout
|
|
157
238
|
http.set_debug_output(@http_debug_output) if @http_debug_output
|
|
@@ -164,9 +245,15 @@ module Aws
|
|
|
164
245
|
headers = { 'User-Agent' => "aws-sdk-ruby3/#{CORE_GEM_VERSION}" }
|
|
165
246
|
headers['x-aws-ec2-metadata-token'] = token if token
|
|
166
247
|
response = connection.request(Net::HTTP::Get.new(path, headers))
|
|
167
|
-
raise Non200Response unless response.code.to_i == 200
|
|
168
248
|
|
|
169
|
-
response.
|
|
249
|
+
case response.code.to_i
|
|
250
|
+
when 200
|
|
251
|
+
response.body
|
|
252
|
+
when 401
|
|
253
|
+
raise TokenExpiredError
|
|
254
|
+
else
|
|
255
|
+
raise Non200Response
|
|
256
|
+
end
|
|
170
257
|
end
|
|
171
258
|
|
|
172
259
|
# PUT request fetch token with ttl
|
|
@@ -205,13 +292,28 @@ module Aws
|
|
|
205
292
|
end
|
|
206
293
|
end
|
|
207
294
|
|
|
295
|
+
def warn_expired_credentials
|
|
296
|
+
warn("Attempting credential expiration extension due to a credential "\
|
|
297
|
+
"service availability issue. A refresh of these credentials "\
|
|
298
|
+
"will be attempted again in 5 minutes.")
|
|
299
|
+
end
|
|
300
|
+
|
|
301
|
+
def empty_credentials?(creds)
|
|
302
|
+
!creds || !creds.access_key_id || creds.access_key_id.empty?
|
|
303
|
+
end
|
|
304
|
+
|
|
305
|
+
# Compute an offset for refresh with jitter
|
|
306
|
+
def refresh_offset
|
|
307
|
+
300 + rand(0..60)
|
|
308
|
+
end
|
|
309
|
+
|
|
208
310
|
# @api private
|
|
209
311
|
# Token used to fetch IMDS profile and credentials
|
|
210
312
|
class Token
|
|
211
|
-
def initialize(value, ttl)
|
|
313
|
+
def initialize(value, ttl, created_time = Time.now)
|
|
212
314
|
@ttl = ttl
|
|
213
315
|
@value = value
|
|
214
|
-
@created_time =
|
|
316
|
+
@created_time = created_time
|
|
215
317
|
end
|
|
216
318
|
|
|
217
319
|
# [String] token value
|