aws-sdk-core 3.173.0 → 3.254.1

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 (213) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +947 -0
  3. data/VERSION +1 -1
  4. data/lib/aws-defaults/default_configuration.rb +5 -6
  5. data/lib/aws-defaults.rb +4 -1
  6. data/lib/aws-sdk-core/arn.rb +1 -3
  7. data/lib/aws-sdk-core/assume_role_credentials.rb +21 -13
  8. data/lib/aws-sdk-core/assume_role_web_identity_credentials.rb +16 -9
  9. data/lib/aws-sdk-core/binary/decode_handler.rb +3 -9
  10. data/lib/aws-sdk-core/binary/encode_handler.rb +1 -1
  11. data/lib/aws-sdk-core/binary/event_builder.rb +34 -37
  12. data/lib/aws-sdk-core/binary/event_stream_decoder.rb +1 -0
  13. data/lib/aws-sdk-core/binary/event_stream_encoder.rb +4 -3
  14. data/lib/aws-sdk-core/cbor/decoder.rb +309 -0
  15. data/lib/aws-sdk-core/cbor/encoder.rb +243 -0
  16. data/lib/aws-sdk-core/cbor.rb +53 -0
  17. data/lib/aws-sdk-core/client_side_monitoring.rb +9 -0
  18. data/lib/aws-sdk-core/client_stubs.rb +39 -55
  19. data/lib/aws-sdk-core/credential_provider.rb +8 -1
  20. data/lib/aws-sdk-core/credential_provider_chain.rb +101 -25
  21. data/lib/aws-sdk-core/credentials.rb +19 -6
  22. data/lib/aws-sdk-core/ec2_metadata.rb +1 -1
  23. data/lib/aws-sdk-core/ecs_credentials.rb +104 -26
  24. data/lib/aws-sdk-core/endpoints/endpoint.rb +3 -1
  25. data/lib/aws-sdk-core/endpoints/matchers.rb +21 -19
  26. data/lib/aws-sdk-core/endpoints.rb +106 -22
  27. data/lib/aws-sdk-core/error_handler.rb +46 -0
  28. data/lib/aws-sdk-core/errors.rb +17 -5
  29. data/lib/aws-sdk-core/event_emitter.rb +1 -17
  30. data/lib/aws-sdk-core/ini_parser.rb +7 -0
  31. data/lib/aws-sdk-core/instance_profile_credentials.rb +181 -158
  32. data/lib/aws-sdk-core/json/builder.rb +23 -1
  33. data/lib/aws-sdk-core/json/error_handler.rb +31 -14
  34. data/lib/aws-sdk-core/json/handler.rb +13 -6
  35. data/lib/aws-sdk-core/json/json_engine.rb +3 -1
  36. data/lib/aws-sdk-core/json/oj_engine.rb +7 -1
  37. data/lib/aws-sdk-core/json/parser.rb +33 -3
  38. data/lib/aws-sdk-core/json.rb +43 -14
  39. data/lib/aws-sdk-core/log/param_filter.rb +2 -2
  40. data/lib/aws-sdk-core/log/param_formatter.rb +7 -3
  41. data/lib/aws-sdk-core/log.rb +10 -0
  42. data/lib/aws-sdk-core/login_credentials.rb +230 -0
  43. data/lib/aws-sdk-core/lru_cache.rb +75 -0
  44. data/lib/aws-sdk-core/pageable_response.rb +3 -1
  45. data/lib/aws-sdk-core/param_validator.rb +9 -4
  46. data/lib/aws-sdk-core/plugins/bearer_authorization.rb +2 -0
  47. data/lib/aws-sdk-core/plugins/checksum_algorithm.rb +437 -201
  48. data/lib/aws-sdk-core/plugins/client_metrics_plugin.rb +1 -1
  49. data/lib/aws-sdk-core/plugins/client_metrics_send_plugin.rb +14 -2
  50. data/lib/aws-sdk-core/plugins/credentials_configuration.rb +78 -56
  51. data/lib/aws-sdk-core/plugins/endpoint_pattern.rb +40 -32
  52. data/lib/aws-sdk-core/plugins/global_configuration.rb +8 -9
  53. data/lib/aws-sdk-core/plugins/http_checksum.rb +3 -8
  54. data/lib/aws-sdk-core/plugins/invocation_id.rb +1 -11
  55. data/lib/aws-sdk-core/plugins/logging.rb +2 -0
  56. data/lib/aws-sdk-core/plugins/protocols/api_gateway.rb +3 -1
  57. data/lib/aws-sdk-core/plugins/protocols/ec2.rb +2 -24
  58. data/lib/aws-sdk-core/plugins/protocols/json_rpc.rb +6 -8
  59. data/lib/aws-sdk-core/plugins/protocols/query.rb +4 -2
  60. data/lib/aws-sdk-core/plugins/protocols/rest_json.rb +3 -15
  61. data/lib/aws-sdk-core/plugins/protocols/rest_xml.rb +3 -0
  62. data/lib/aws-sdk-core/plugins/protocols/rpc_v2.rb +17 -0
  63. data/lib/aws-sdk-core/plugins/regional_endpoint.rb +162 -37
  64. data/lib/aws-sdk-core/plugins/request_compression.rb +226 -0
  65. data/lib/aws-sdk-core/plugins/retries/clock_skew.rb +28 -16
  66. data/lib/aws-sdk-core/plugins/retries/retry_quota.rb +11 -8
  67. data/lib/aws-sdk-core/plugins/retry_errors.rb +211 -110
  68. data/lib/aws-sdk-core/plugins/sign.rb +55 -33
  69. data/lib/aws-sdk-core/plugins/signature_v2.rb +2 -1
  70. data/lib/aws-sdk-core/plugins/signature_v4.rb +2 -1
  71. data/lib/aws-sdk-core/plugins/stub_responses.rb +59 -9
  72. data/lib/aws-sdk-core/plugins/telemetry.rb +75 -0
  73. data/lib/aws-sdk-core/plugins/transfer_encoding.rb +16 -9
  74. data/lib/aws-sdk-core/plugins/user_agent.rb +205 -14
  75. data/lib/aws-sdk-core/plugins.rb +39 -0
  76. data/lib/aws-sdk-core/process_credentials.rb +48 -29
  77. data/lib/aws-sdk-core/query/ec2_handler.rb +27 -0
  78. data/lib/aws-sdk-core/query/ec2_param_builder.rb +5 -7
  79. data/lib/aws-sdk-core/query/handler.rb +4 -4
  80. data/lib/aws-sdk-core/query/param_builder.rb +2 -2
  81. data/lib/aws-sdk-core/query.rb +2 -1
  82. data/lib/aws-sdk-core/refreshing_credentials.rb +20 -23
  83. data/lib/aws-sdk-core/resources.rb +8 -0
  84. data/lib/aws-sdk-core/rest/content_type_handler.rb +60 -0
  85. data/lib/aws-sdk-core/rest/handler.rb +3 -4
  86. data/lib/aws-sdk-core/rest/request/body.rb +32 -5
  87. data/lib/aws-sdk-core/rest/request/endpoint.rb +24 -4
  88. data/lib/aws-sdk-core/rest/request/headers.rb +15 -7
  89. data/lib/aws-sdk-core/rest/request/querystring_builder.rb +62 -36
  90. data/lib/aws-sdk-core/rest/response/body.rb +15 -1
  91. data/lib/aws-sdk-core/rest/response/header_list_parser.rb +79 -0
  92. data/lib/aws-sdk-core/rest/response/headers.rb +8 -3
  93. data/lib/aws-sdk-core/rest.rb +1 -0
  94. data/lib/aws-sdk-core/rpc_v2/builder.rb +62 -0
  95. data/lib/aws-sdk-core/rpc_v2/cbor_engine.rb +18 -0
  96. data/lib/aws-sdk-core/rpc_v2/content_type_handler.rb +47 -0
  97. data/lib/aws-sdk-core/rpc_v2/error_handler.rb +95 -0
  98. data/lib/aws-sdk-core/rpc_v2/handler.rb +79 -0
  99. data/lib/aws-sdk-core/rpc_v2/parser.rb +98 -0
  100. data/lib/aws-sdk-core/rpc_v2.rb +69 -0
  101. data/lib/aws-sdk-core/shared_config.rb +155 -39
  102. data/lib/aws-sdk-core/shared_credentials.rb +1 -7
  103. data/lib/aws-sdk-core/sso_credentials.rb +6 -3
  104. data/lib/aws-sdk-core/sso_token_provider.rb +1 -0
  105. data/lib/aws-sdk-core/static_token_provider.rb +1 -2
  106. data/lib/aws-sdk-core/stubbing/protocols/ec2.rb +12 -11
  107. data/lib/aws-sdk-core/stubbing/protocols/json.rb +11 -10
  108. data/lib/aws-sdk-core/stubbing/protocols/query.rb +7 -6
  109. data/lib/aws-sdk-core/stubbing/protocols/rest.rb +2 -1
  110. data/lib/aws-sdk-core/stubbing/protocols/rest_json.rb +9 -8
  111. data/lib/aws-sdk-core/stubbing/protocols/rest_xml.rb +6 -5
  112. data/lib/aws-sdk-core/stubbing/protocols/rpc_v2.rb +39 -0
  113. data/lib/aws-sdk-core/stubbing/stub_data.rb +11 -0
  114. data/lib/aws-sdk-core/stubbing.rb +22 -0
  115. data/lib/aws-sdk-core/telemetry/base.rb +177 -0
  116. data/lib/aws-sdk-core/telemetry/no_op.rb +70 -0
  117. data/lib/aws-sdk-core/telemetry/otel.rb +235 -0
  118. data/lib/aws-sdk-core/telemetry/span_kind.rb +22 -0
  119. data/lib/aws-sdk-core/telemetry/span_status.rb +59 -0
  120. data/lib/aws-sdk-core/telemetry.rb +78 -0
  121. data/lib/aws-sdk-core/token.rb +3 -3
  122. data/lib/aws-sdk-core/token_provider.rb +4 -0
  123. data/lib/aws-sdk-core/token_provider_chain.rb +2 -6
  124. data/lib/aws-sdk-core/util.rb +41 -1
  125. data/lib/aws-sdk-core/waiters/poller.rb +12 -5
  126. data/lib/aws-sdk-core/xml/builder.rb +17 -9
  127. data/lib/aws-sdk-core/xml/error_handler.rb +35 -43
  128. data/lib/aws-sdk-core/xml/parser/frame.rb +4 -20
  129. data/lib/aws-sdk-core/xml/parser/stack.rb +2 -0
  130. data/lib/aws-sdk-core/xml/parser.rb +2 -6
  131. data/lib/aws-sdk-core.rb +86 -107
  132. data/lib/aws-sdk-signin/client.rb +1008 -0
  133. data/lib/aws-sdk-signin/client_api.rb +444 -0
  134. data/lib/aws-sdk-signin/customizations.rb +1 -0
  135. data/lib/aws-sdk-signin/endpoint_parameters.rb +85 -0
  136. data/lib/aws-sdk-signin/endpoint_provider.rb +107 -0
  137. data/lib/aws-sdk-signin/endpoints.rb +133 -0
  138. data/lib/aws-sdk-signin/errors.rb +185 -0
  139. data/lib/aws-sdk-signin/plugins/endpoints.rb +77 -0
  140. data/lib/aws-sdk-signin/resource.rb +26 -0
  141. data/lib/aws-sdk-signin/types.rb +909 -0
  142. data/lib/aws-sdk-signin.rb +63 -0
  143. data/lib/aws-sdk-sso/client.rb +210 -99
  144. data/lib/aws-sdk-sso/client_api.rb +7 -0
  145. data/lib/aws-sdk-sso/endpoint_parameters.rb +13 -10
  146. data/lib/aws-sdk-sso/endpoint_provider.rb +30 -28
  147. data/lib/aws-sdk-sso/endpoints.rb +3 -54
  148. data/lib/aws-sdk-sso/plugins/endpoints.rb +23 -22
  149. data/lib/aws-sdk-sso/types.rb +1 -0
  150. data/lib/aws-sdk-sso.rb +15 -11
  151. data/lib/aws-sdk-ssooidc/client.rb +630 -132
  152. data/lib/aws-sdk-ssooidc/client_api.rb +94 -1
  153. data/lib/aws-sdk-ssooidc/endpoint_parameters.rb +13 -10
  154. data/lib/aws-sdk-ssooidc/endpoint_provider.rb +30 -28
  155. data/lib/aws-sdk-ssooidc/endpoints.rb +3 -40
  156. data/lib/aws-sdk-ssooidc/errors.rb +62 -0
  157. data/lib/aws-sdk-ssooidc/plugins/endpoints.rb +23 -20
  158. data/lib/aws-sdk-ssooidc/types.rb +419 -53
  159. data/lib/aws-sdk-ssooidc.rb +15 -11
  160. data/lib/aws-sdk-sts/client.rb +567 -158
  161. data/lib/aws-sdk-sts/client_api.rb +120 -9
  162. data/lib/aws-sdk-sts/customizations.rb +5 -2
  163. data/lib/aws-sdk-sts/endpoint_parameters.rb +15 -14
  164. data/lib/aws-sdk-sts/endpoint_provider.rb +52 -57
  165. data/lib/aws-sdk-sts/endpoints.rb +3 -118
  166. data/lib/aws-sdk-sts/errors.rb +79 -0
  167. data/lib/aws-sdk-sts/plugins/endpoints.rb +23 -30
  168. data/lib/aws-sdk-sts/presigner.rb +3 -7
  169. data/lib/aws-sdk-sts/types.rb +382 -31
  170. data/lib/aws-sdk-sts.rb +15 -11
  171. data/lib/seahorse/client/async_base.rb +4 -5
  172. data/lib/seahorse/client/async_response.rb +19 -0
  173. data/lib/seahorse/client/base.rb +18 -21
  174. data/lib/seahorse/client/configuration.rb +0 -4
  175. data/lib/seahorse/client/h2/connection.rb +18 -28
  176. data/lib/seahorse/client/h2/handler.rb +19 -3
  177. data/lib/seahorse/client/handler.rb +1 -1
  178. data/lib/seahorse/client/http/response.rb +1 -1
  179. data/lib/seahorse/client/net_http/connection_pool.rb +15 -12
  180. data/lib/seahorse/client/net_http/handler.rb +21 -9
  181. data/lib/seahorse/client/net_http/patches.rb +44 -14
  182. data/lib/seahorse/client/networking_error.rb +1 -1
  183. data/lib/seahorse/client/plugin.rb +9 -0
  184. data/lib/seahorse/client/plugins/endpoint.rb +0 -1
  185. data/lib/seahorse/client/plugins/h2.rb +4 -4
  186. data/lib/seahorse/client/plugins/net_http.rb +57 -16
  187. data/lib/seahorse/client/plugins/request_callback.rb +31 -0
  188. data/lib/seahorse/client/request_context.rb +9 -2
  189. data/lib/seahorse/client/response.rb +8 -0
  190. data/lib/seahorse/model/operation.rb +3 -0
  191. data/lib/seahorse/model/shapes.rb +2 -2
  192. data/lib/seahorse/util.rb +2 -1
  193. data/sig/aws-sdk-core/async_client_stubs.rbs +21 -0
  194. data/sig/aws-sdk-core/client_stubs.rbs +10 -0
  195. data/sig/aws-sdk-core/errors.rbs +22 -0
  196. data/sig/aws-sdk-core/resources/collection.rbs +21 -0
  197. data/sig/aws-sdk-core/structure.rbs +4 -0
  198. data/sig/aws-sdk-core/telemetry/base.rbs +46 -0
  199. data/sig/aws-sdk-core/telemetry/otel.rbs +22 -0
  200. data/sig/aws-sdk-core/telemetry/span_kind.rbs +15 -0
  201. data/sig/aws-sdk-core/telemetry/span_status.rbs +24 -0
  202. data/sig/aws-sdk-core/waiters/errors.rbs +20 -0
  203. data/sig/aws-sdk-core.rbs +7 -0
  204. data/sig/seahorse/client/async_base.rbs +18 -0
  205. data/sig/seahorse/client/base.rbs +25 -0
  206. data/sig/seahorse/client/handler_builder.rbs +16 -0
  207. data/sig/seahorse/client/response.rbs +61 -0
  208. metadata +118 -23
  209. /data/lib/aws-sdk-core/xml/parser/{engines/libxml.rb → libxml_engine.rb} +0 -0
  210. /data/lib/aws-sdk-core/xml/parser/{engines/nokogiri.rb → nokogiri_engine.rb} +0 -0
  211. /data/lib/aws-sdk-core/xml/parser/{engines/oga.rb → oga_engine.rb} +0 -0
  212. /data/lib/aws-sdk-core/xml/parser/{engines/ox.rb → ox_engine.rb} +0 -0
  213. /data/lib/aws-sdk-core/xml/parser/{engines/rexml.rb → rexml_engine.rb} +0 -0
@@ -4,17 +4,39 @@ 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
15
27
 
16
28
  # @api private
17
- class Non200Response < RuntimeError; end
29
+ class Non200Response < RuntimeError
30
+ attr_reader :status_code, :body
31
+
32
+ def initialize(status_code, body = nil)
33
+ @status_code = status_code
34
+ @body = body
35
+ msg = "HTTP #{status_code}"
36
+ msg += ": #{body}" if body && !body.empty?
37
+ super(msg)
38
+ end
39
+ end
18
40
 
19
41
  # @api private
20
42
  class TokenRetrivalError < RuntimeError; end
@@ -22,10 +44,8 @@ module Aws
22
44
  # @api private
23
45
  class TokenExpiredError < RuntimeError; end
24
46
 
25
- # These are the errors we trap when attempting to talk to the
26
- # instance metadata service. Any of these imply the service
27
- # is not present, no responding or some other non-recoverable
28
- # error.
47
+ # These are the errors we trap when attempting to talk to the instance metadata service.
48
+ # Any of these imply the service is not present, no responding or some other non-recoverable error.
29
49
  # @api private
30
50
  NETWORK_ERRORS = [
31
51
  Errno::EHOSTUNREACH,
@@ -46,84 +66,113 @@ module Aws
46
66
  METADATA_TOKEN_PATH = '/latest/api/token'.freeze
47
67
 
48
68
  # @param [Hash] options
49
- # @option options [Integer] :retries (1) Number of times to retry
50
- # when retrieving credentials.
51
- # @option options [String] :endpoint ('http://169.254.169.254') The IMDS
52
- # endpoint. This option has precedence over the :endpoint_mode.
53
- # @option options [String] :endpoint_mode ('IPv4') The endpoint mode for
54
- # the instance metadata service. This is either 'IPv4' ('169.254.169.254')
55
- # or 'IPv6' ('[fd00:ec2::254]').
56
- # @option options [String] :ip_address ('169.254.169.254') Deprecated. Use
57
- # :endpoint instead. The IP address for the endpoint.
69
+ # @option options [Integer] :retries (1) Number of times to retry when retrieving credentials.
70
+ # @option options [Numeric, Proc] :backoff By default, failures are retried with exponential back-off, i.e.
71
+ # `lambda { |num_failures| sleep(1.2 ** num_failures) }`. You can pass a number of seconds to sleep
72
+ # between failed attempts, or a Proc that accepts the number of failures.
73
+ # @option options [String] :endpoint ('http://169.254.169.254') The IMDS endpoint. This option has precedence
74
+ # over the `:endpoint_mode`.
75
+ # @option options [String] :endpoint_mode ('IPv4') The endpoint mode for the instance metadata service. This is
76
+ # either 'IPv4' (`169.254.169.254`) or IPv6' (`[fd00:ec2::254]`).
77
+ # @option options [Boolean] :disable_imds_v1 (false) Disable the use of the legacy EC2 Metadata Service v1.
78
+ # @option options [String] :ip_address ('169.254.169.254') Deprecated. Use `:endpoint` instead.
79
+ # The IP address for the endpoint.
58
80
  # @option options [Integer] :port (80)
59
81
  # @option options [Float] :http_open_timeout (1)
60
82
  # @option options [Float] :http_read_timeout (1)
61
- # @option options [Numeric, Proc] :delay By default, failures are retried
62
- # with exponential back-off, i.e. `sleep(1.2 ** num_failures)`. You can
63
- # pass a number of seconds to sleep between failed attempts, or
64
- # a Proc that accepts the number of failures.
65
- # @option options [IO] :http_debug_output (nil) HTTP wire
66
- # traces are sent to this object. You can specify something
67
- # like $stdout.
68
- # @option options [Integer] :token_ttl Time-to-Live in seconds for EC2
69
- # Metadata Token used for fetching Metadata Profile Credentials, defaults
70
- # to 21600 seconds
71
- # @option options [Callable] before_refresh Proc called before
72
- # credentials are refreshed. `before_refresh` is called
73
- # with an instance of this object when
74
- # AWS credentials are required and need to be refreshed.
83
+ # @option options [IO] :http_debug_output (nil) HTTP wire traces are sent to this object.
84
+ # You can specify something like `$stdout`.
85
+ # @option options [Integer] :token_ttl (21600) Time-to-Live in seconds for EC2 Metadata Token used for fetching
86
+ # Metadata Profile Credentials.
87
+ # @option options [Proc] :before_refresh A Proc called before credentials are refreshed. `:before_refresh`
88
+ # is called with an instance of this object when AWS credentials are required and need to be refreshed.
75
89
  def initialize(options = {})
76
- @retries = options[:retries] || 1
77
- endpoint_mode = resolve_endpoint_mode(options)
78
- @endpoint = resolve_endpoint(options, endpoint_mode)
79
- @port = options[:port] || 80
90
+ @backoff = resolve_backoff(options[:backoff])
91
+ @disable_imds_v1 = resolve_disable_v1(options)
92
+ @endpoint = resolve_endpoint(options)
80
93
  @http_open_timeout = options[:http_open_timeout] || 1
81
94
  @http_read_timeout = options[:http_read_timeout] || 1
82
95
  @http_debug_output = options[:http_debug_output]
83
- @backoff = backoff(options[:backoff])
96
+ @port = options[:port] || 80
97
+ @retries = options[:retries] || 1
84
98
  @token_ttl = options[:token_ttl] || 21_600
85
- @token = nil
86
- @no_refresh_until = nil
99
+
87
100
  @async_refresh = false
101
+ @imds_v1_fallback = false
102
+ @no_refresh_until = nil
103
+ @token = nil
104
+ @metrics = ['CREDENTIALS_IMDS']
88
105
  super
89
106
  end
90
107
 
91
- # @return [Integer] Number of times to retry when retrieving credentials
92
- # from the instance metadata service. Defaults to 0 when resolving from
93
- # the default credential chain ({Aws::CredentialProviderChain}).
108
+ # @return [Boolean]
109
+ attr_reader :disable_imds_v1
110
+
111
+ # @return [Integer]
112
+ attr_reader :token_ttl
113
+
114
+ # @return [Integer]
94
115
  attr_reader :retries
95
116
 
117
+ # @return [Proc]
118
+ attr_reader :backoff
119
+
120
+ # @return [String]
121
+ attr_reader :endpoint
122
+
123
+ # @return [Integer]
124
+ attr_reader :port
125
+
126
+ # @return [Integer]
127
+ attr_reader :http_open_timeout
128
+
129
+ # @return [Integer]
130
+ attr_reader :http_read_timeout
131
+
132
+ # @return [IO, nil]
133
+ attr_reader :http_debug_output
134
+
96
135
  private
97
136
 
98
137
  def resolve_endpoint_mode(options)
99
- value = options[:endpoint_mode]
100
- value ||= ENV['AWS_EC2_METADATA_SERVICE_ENDPOINT_MODE']
101
- value ||= Aws.shared_config.ec2_metadata_service_endpoint_mode(
102
- profile: options[:profile]
103
- )
104
- value || 'IPv4'
138
+ options[:endpoint_mode] ||
139
+ ENV['AWS_EC2_METADATA_SERVICE_ENDPOINT_MODE'] ||
140
+ Aws.shared_config.ec2_metadata_service_endpoint_mode(profile: options[:profile]) ||
141
+ 'IPv4'
105
142
  end
106
143
 
107
- def resolve_endpoint(options, endpoint_mode)
108
- value = options[:endpoint] || options[:ip_address]
109
- value ||= ENV['AWS_EC2_METADATA_SERVICE_ENDPOINT']
110
- value ||= Aws.shared_config.ec2_metadata_service_endpoint(
111
- profile: options[:profile]
112
- )
144
+ def resolve_endpoint(options)
145
+ if (value = options[:ip_address])
146
+ warn('The `:ip_address` option is deprecated. Use `:endpoint` instead.')
147
+ return value
148
+ end
113
149
 
150
+ value =
151
+ options[:endpoint] ||
152
+ ENV['AWS_EC2_METADATA_SERVICE_ENDPOINT'] ||
153
+ Aws.shared_config.ec2_metadata_service_endpoint(profile: options[:profile]) ||
154
+ nil
114
155
  return value if value
115
156
 
157
+ endpoint_mode = resolve_endpoint_mode(options)
116
158
  case endpoint_mode.downcase
117
159
  when 'ipv4' then 'http://169.254.169.254'
118
160
  when 'ipv6' then 'http://[fd00:ec2::254]'
119
161
  else
120
- raise ArgumentError,
121
- ':endpoint_mode is not valid, expected IPv4 or IPv6, '\
122
- "got: #{endpoint_mode}"
162
+ raise ArgumentError, ":endpoint_mode is not valid, expected IPv4 or IPv6, got: #{endpoint_mode}"
123
163
  end
124
164
  end
125
165
 
126
- def backoff(backoff)
166
+ def resolve_disable_v1(options)
167
+ value =
168
+ options[:disable_imds_v1] ||
169
+ ENV['AWS_EC2_METADATA_V1_DISABLED'] ||
170
+ Aws.shared_config.ec2_metadata_v1_disabled(profile: options[:profile]) ||
171
+ 'false'
172
+ Aws::Util.str_2_bool(value.to_s.downcase)
173
+ end
174
+
175
+ def resolve_backoff(backoff)
127
176
  case backoff
128
177
  when Proc then backoff
129
178
  when Numeric then ->(_) { sleep(backoff) }
@@ -137,107 +186,89 @@ module Aws
137
186
  return
138
187
  end
139
188
 
140
- # Retry loading credentials up to 3 times is the instance metadata
141
- # service is responding but is returning invalid JSON documents
142
- # in response to the GET profile credentials call.
143
- begin
144
- retry_errors([Aws::Json::ParseError, StandardError], max_retries: 3) do
145
- c = Aws::Json.load(get_credentials.to_s)
146
- if empty_credentials?(@credentials)
147
- @credentials = Credentials.new(
148
- c['AccessKeyId'],
149
- c['SecretAccessKey'],
150
- c['Token']
151
- )
152
- @expiration = c['Expiration'] ? Time.iso8601(c['Expiration']) : nil
153
- if @expiration && @expiration < Time.now
154
- @no_refresh_until = Time.now + refresh_offset
155
- warn_expired_credentials
156
- end
157
- else
158
- # credentials are already set, update them only if the new ones are not empty
159
- if !c['AccessKeyId'] || c['AccessKeyId'].empty?
160
- # error getting new credentials
161
- @no_refresh_until = Time.now + refresh_offset
162
- warn_expired_credentials
163
- else
164
- @credentials = Credentials.new(
165
- c['AccessKeyId'],
166
- c['SecretAccessKey'],
167
- c['Token']
168
- )
169
- @expiration = c['Expiration'] ? Time.iso8601(c['Expiration']) : nil
170
- if @expiration && @expiration < Time.now
171
- @no_refresh_until = Time.now + refresh_offset
172
- warn_expired_credentials
173
- end
174
- end
189
+ new_creds =
190
+ begin
191
+ # Retry loading credentials up to 3 times is the instance metadata
192
+ # service is responding but is returning invalid JSON documents
193
+ # in response to the GET profile credentials call.
194
+ retry_errors([Aws::Json::ParseError], max_retries: 3) do
195
+ Aws::Json.load(retrieve_credentials.to_s)
175
196
  end
176
-
197
+ rescue Aws::Json::ParseError
198
+ raise Aws::Errors::MetadataParserError
177
199
  end
178
- rescue Aws::Json::ParseError
179
- raise Aws::Errors::MetadataParserError
200
+
201
+ if @credentials&.set? && empty_credentials?(new_creds)
202
+ # credentials are already set, but there was an error getting new credentials
203
+ # so don't update the credentials and use stale ones (static stability)
204
+ @no_refresh_until = Time.now + rand(300..360)
205
+ warn_expired_credentials
206
+ else
207
+ # credentials are empty or successfully retrieved, update them
208
+ update_credentials(new_creds)
180
209
  end
181
210
  end
182
211
 
183
- def get_credentials
212
+ def retrieve_credentials
184
213
  # Retry loading credentials a configurable number of times if
185
214
  # the instance metadata service is not responding.
186
- if _metadata_disabled?
187
- '{}'
188
- else
189
- begin
190
- retry_errors(NETWORK_ERRORS, max_retries: @retries) do
191
- open_connection do |conn|
192
- # attempt to fetch token to start secure flow first
193
- # and rescue to failover
194
- begin
195
- retry_errors(NETWORK_ERRORS, max_retries: @retries) do
196
- unless token_set?
197
- created_time = Time.now
198
- token_value, ttl = http_put(
199
- conn, METADATA_TOKEN_PATH, @token_ttl
200
- )
201
- @token = Token.new(token_value, ttl, created_time) if token_value && ttl
202
- end
203
- end
204
- rescue *NETWORK_ERRORS
205
- # token attempt failed, reset token
206
- # fallback to non-token mode
207
- @token = nil
208
- end
209
-
210
- token = @token.value if token_set?
211
-
212
- begin
213
- metadata = http_get(conn, METADATA_PATH_BASE, token)
214
- profile_name = metadata.lines.first.strip
215
- http_get(conn, METADATA_PATH_BASE + profile_name, token)
216
- rescue TokenExpiredError
217
- # Token has expired, reset it
218
- # The next retry should fetch it
219
- @token = nil
220
- raise Non200Response
221
- end
222
- end
215
+ begin
216
+ retry_errors(NETWORK_ERRORS, max_retries: @retries) do
217
+ open_connection do |conn|
218
+ # attempt to fetch token to start secure flow first
219
+ # and rescue to failover
220
+ fetch_token(conn) unless @imds_v1_fallback || (@token && !@token.expired?)
221
+
222
+ # disable insecure flow if we couldn't get token and imds v1 is disabled
223
+ raise TokenRetrivalError if @token.nil? && @disable_imds_v1
224
+
225
+ fetch_credentials(conn)
223
226
  end
224
- rescue
225
- '{}'
226
227
  end
228
+ rescue StandardError => e
229
+ warn("Error retrieving instance profile credentials: #{e}")
230
+ '{}'
227
231
  end
228
232
  end
229
233
 
230
- def token_set?
231
- @token && !@token.expired?
234
+ def update_credentials(creds)
235
+ @credentials = Credentials.new(creds['AccessKeyId'], creds['SecretAccessKey'], creds['Token'])
236
+ @expiration = creds['Expiration'] ? Time.iso8601(creds['Expiration']) : nil
237
+ return unless @expiration && @expiration < Time.now
238
+
239
+ @no_refresh_until = Time.now + rand(300..360)
240
+ warn_expired_credentials
232
241
  end
233
242
 
234
- def _metadata_disabled?
235
- ENV.fetch('AWS_EC2_METADATA_DISABLED', 'false').downcase == 'true'
243
+ def fetch_token(conn)
244
+ created_time = Time.now
245
+ token_value, ttl = http_put(conn)
246
+ @token = Token.new(token_value, ttl, created_time) if token_value && ttl
247
+ rescue *NETWORK_ERRORS
248
+ # token attempt failed, reset token
249
+ # fallback to non-token mode
250
+ @imds_v1_fallback = true
251
+ end
252
+
253
+ def fetch_credentials(conn)
254
+ metadata = http_get(conn, METADATA_PATH_BASE)
255
+ profile_name = metadata.lines.first.strip
256
+ http_get(conn, METADATA_PATH_BASE + profile_name)
257
+ rescue TokenExpiredError
258
+ # Token has expired, reset it
259
+ # The next retry should fetch it
260
+ @token = nil
261
+ @imds_v1_fallback = false
262
+ raise Non200Response.new(401, 'Token expired')
263
+ end
264
+
265
+ def token_set?
266
+ @token && !@token.expired?
236
267
  end
237
268
 
238
269
  def open_connection
239
270
  uri = URI.parse(@endpoint)
240
- http = Net::HTTP.new(uri.hostname || @endpoint, @port || uri.port)
271
+ http = Net::HTTP.new(uri.hostname || @endpoint, uri.port || @port)
241
272
  http.open_timeout = @http_open_timeout
242
273
  http.read_timeout = @http_read_timeout
243
274
  http.set_debug_output(@http_debug_output) if @http_debug_output
@@ -246,9 +277,9 @@ module Aws
246
277
  end
247
278
 
248
279
  # GET request fetch profile and credentials
249
- def http_get(connection, path, token = nil)
280
+ def http_get(connection, path)
250
281
  headers = { 'User-Agent' => "aws-sdk-ruby3/#{CORE_GEM_VERSION}" }
251
- headers['x-aws-ec2-metadata-token'] = token if token
282
+ headers['x-aws-ec2-metadata-token'] = @token.value if @token
252
283
  response = connection.request(Net::HTTP::Get.new(path, headers))
253
284
 
254
285
  case response.code.to_i
@@ -257,17 +288,17 @@ module Aws
257
288
  when 401
258
289
  raise TokenExpiredError
259
290
  else
260
- raise Non200Response
291
+ raise Non200Response.new(response.code.to_i, response.body)
261
292
  end
262
293
  end
263
294
 
264
295
  # PUT request fetch token with ttl
265
- def http_put(connection, path, ttl)
296
+ def http_put(connection)
266
297
  headers = {
267
298
  'User-Agent' => "aws-sdk-ruby3/#{CORE_GEM_VERSION}",
268
- 'x-aws-ec2-metadata-token-ttl-seconds' => ttl.to_s
299
+ 'x-aws-ec2-metadata-token-ttl-seconds' => @token_ttl.to_s
269
300
  }
270
- response = connection.request(Net::HTTP::Put.new(path, headers))
301
+ response = connection.request(Net::HTTP::Put.new(METADATA_TOKEN_PATH, headers))
271
302
  case response.code.to_i
272
303
  when 200
273
304
  [
@@ -276,10 +307,8 @@ module Aws
276
307
  ]
277
308
  when 400
278
309
  raise TokenRetrivalError
279
- when 401
280
- raise TokenExpiredError
281
310
  else
282
- raise Non200Response
311
+ raise Non200Response.new(response.code.to_i, response.body)
283
312
  end
284
313
  end
285
314
 
@@ -298,18 +327,12 @@ module Aws
298
327
  end
299
328
 
300
329
  def warn_expired_credentials
301
- warn("Attempting credential expiration extension due to a credential "\
302
- "service availability issue. A refresh of these credentials "\
303
- "will be attempted again in 5 minutes.")
304
- end
305
-
306
- def empty_credentials?(creds)
307
- !creds || !creds.access_key_id || creds.access_key_id.empty?
330
+ warn('Attempting credential expiration extension due to a credential service availability issue. '\
331
+ 'A refresh of these credentials will be attempted again in 5 minutes.')
308
332
  end
309
333
 
310
- # Compute an offset for refresh with jitter
311
- def refresh_offset
312
- 300 + rand(0..60)
334
+ def empty_credentials?(creds_hash)
335
+ !creds_hash['AccessKeyId'] || creds_hash['AccessKeyId'].empty?
313
336
  end
314
337
 
315
338
  # @api private
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'base64'
4
+ require 'bigdecimal'
4
5
 
5
6
  module Aws
6
7
  module Json
@@ -8,7 +9,7 @@ module Aws
8
9
 
9
10
  include Seahorse::Model::Shapes
10
11
 
11
- def initialize(rules)
12
+ def initialize(rules, _options = {})
12
13
  @rules = rules
13
14
  end
14
15
 
@@ -20,6 +21,8 @@ module Aws
20
21
  private
21
22
 
22
23
  def structure(ref, values)
24
+ return nil if values.nil?
25
+
23
26
  shape = ref.shape
24
27
  values.each_pair.with_object({}) do |(key, value), data|
25
28
  if shape.member?(key) && !value.nil?
@@ -31,11 +34,15 @@ module Aws
31
34
  end
32
35
 
33
36
  def list(ref, values)
37
+ return nil if values.nil?
38
+
34
39
  member_ref = ref.shape.member
35
40
  values.collect { |value| format(member_ref, value) }
36
41
  end
37
42
 
38
43
  def map(ref, values)
44
+ return nil if values.nil?
45
+
39
46
  value_ref = ref.shape.value
40
47
  values.each.with_object({}) do |(key, value), data|
41
48
  data[key] = format(value_ref, value)
@@ -49,10 +56,25 @@ module Aws
49
56
  when MapShape then map(ref, value)
50
57
  when TimestampShape then timestamp(ref, value)
51
58
  when BlobShape then encode(value)
59
+ when FloatShape then Util.serialize_number(value)
60
+ when DocumentShape then document(value)
52
61
  else value
53
62
  end
54
63
  end
55
64
 
65
+ def document(value)
66
+ case value
67
+ when Hash
68
+ value.transform_values { |v| document(v) }
69
+ when Array
70
+ value.map { |v| document(v) }
71
+ when BigDecimal, Float
72
+ Util.serialize_number(value.to_f)
73
+ else
74
+ value
75
+ end
76
+ end
77
+
56
78
  def encode(blob)
57
79
  Base64.strict_encode64(String === blob ? blob : blob.read)
58
80
  end
@@ -2,10 +2,9 @@
2
2
 
3
3
  module Aws
4
4
  module Json
5
- class ErrorHandler < Xml::ErrorHandler
5
+ # @api private
6
+ class ErrorHandler < Aws::ErrorHandler
6
7
 
7
- # @param [Seahorse::Client::RequestContext] context
8
- # @return [Seahorse::Client::Response]
9
8
  def call(context)
10
9
  @handler.call(context).on(300..599) do |response|
11
10
  response.error = error(context)
@@ -19,24 +18,28 @@ module Aws
19
18
  json = Json.load(body)
20
19
  code = error_code(json, context)
21
20
  message = error_message(code, json)
22
- data = parse_error_data(context, code)
21
+ data = parse_error_data(context, body, code)
23
22
  [code, message, data]
24
23
  rescue Json::ParseError
25
24
  [http_status_error_code(context), '', EmptyStructure.new]
26
25
  end
27
26
 
28
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.
29
33
  code =
30
34
  if aws_query_error?(context)
31
- error = context.http_response.headers['x-amzn-query-error'].split(';')[0]
32
- remove_prefix(error, context)
35
+ aws_query_error_code(context)
33
36
  else
34
37
  json['__type']
35
38
  end
36
39
  code ||= json['code']
37
40
  code ||= context.http_response.headers['x-amzn-errortype']
38
41
  if code
39
- code.split('#').last
42
+ code.split('#').last.split(':').first
40
43
  else
41
44
  http_status_error_code(context)
42
45
  end
@@ -47,8 +50,14 @@ module Aws
47
50
  context.http_response.headers['x-amzn-query-error']
48
51
  end
49
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
+
50
59
  def remove_prefix(error_code, context)
51
- if prefix = context.config.api.metadata['errorPrefix']
60
+ if (prefix = context.config.api.metadata['errorPrefix'])
52
61
  error_code.sub(/^#{prefix}/, '')
53
62
  else
54
63
  error_code
@@ -59,26 +68,34 @@ module Aws
59
68
  if code == 'RequestEntityTooLarge'
60
69
  'Request body must be less than 1 MB'
61
70
  else
62
- json['message'] || json['Message'] || ''
71
+ # SSO OIDC returns error message in error_description, following OAuth 2.0 spec.
72
+ json['message'] || json['Message'] || json['error_description'] || ''
63
73
  end
64
74
  end
65
75
 
66
- def parse_error_data(context, code)
76
+ def parse_error_data(context, body, code)
67
77
  data = EmptyStructure.new
68
- if error_rules = context.operation.errors
78
+ if (error_rules = context.operation.errors)
69
79
  error_rules.each do |rule|
70
80
  # match modeled shape name with the type(code) only
71
81
  # some type(code) might contains invalid characters
72
82
  # such as ':' (efs) etc
73
83
  match = rule.shape.name == code.gsub(/[^^a-zA-Z0-9]/, '')
74
- if match && rule.shape.members.any?
75
- data = Parser.new(rule).parse(context.http_response.body_contents)
76
- end
84
+ next unless match && rule.shape.members.any?
85
+
86
+ data = Parser.new(rule).parse(body)
87
+ # errors support HTTP bindings
88
+ apply_error_headers(rule, context, data)
77
89
  end
78
90
  end
79
91
  data
80
92
  end
81
93
 
94
+ def apply_error_headers(rule, context, data)
95
+ headers = Aws::Rest::Response::Headers.new(rule)
96
+ headers.apply(context.http_response, data)
97
+ end
98
+
82
99
  end
83
100
  end
84
101
  end
@@ -12,8 +12,7 @@ module Aws
12
12
  build_request(context)
13
13
  response = @handler.call(context)
14
14
  response.on(200..299) { |resp| parse_response(resp) }
15
- response.on(200..599) { |resp| apply_request_id(context) }
16
- response
15
+ response.on(200..599) { |_resp| apply_request_id(context) }
17
16
  end
18
17
 
19
18
  private
@@ -22,6 +21,7 @@ module Aws
22
21
  context.http_request.http_method = 'POST'
23
22
  context.http_request.headers['Content-Type'] = content_type(context)
24
23
  context.http_request.headers['X-Amz-Target'] = target(context)
24
+ context.http_request.headers['X-Amzn-Query-Mode'] = 'true' if query_compatible?(context)
25
25
  context.http_request.body = build_body(context)
26
26
  end
27
27
 
@@ -38,10 +38,10 @@ module Aws
38
38
  end
39
39
 
40
40
  def parse_body(context)
41
+ json = context.http_response.body_contents
41
42
  if simple_json?(context)
42
- Json.load(context.http_response.body_contents)
43
- elsif rules = context.operation.output
44
- json = context.http_response.body_contents
43
+ Json.load(json)
44
+ elsif (rules = context.operation.output)
45
45
  if json.is_a?(Array)
46
46
  # an array of emitted events
47
47
  if json[0].respond_to?(:response)
@@ -59,7 +59,10 @@ module Aws
59
59
  end
60
60
  resp_struct
61
61
  else
62
- Parser.new(rules).parse(json == '' ? '{}' : json)
62
+ Parser.new(
63
+ rules,
64
+ query_compatible: query_compatible?(context)
65
+ ).parse(json)
63
66
  end
64
67
  else
65
68
  EmptyStructure.new
@@ -83,6 +86,10 @@ module Aws
83
86
  context.config.simple_json
84
87
  end
85
88
 
89
+ def query_compatible?(context)
90
+ context.config.api.metadata.key?('awsQueryCompatible')
91
+ end
92
+
86
93
  end
87
94
  end
88
95
  end