aws-sdk-core 3.191.1 → 3.229.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (181) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +539 -1
  3. data/VERSION +1 -1
  4. data/lib/aws-defaults/default_configuration.rb +1 -2
  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 +13 -5
  8. data/lib/aws-sdk-core/assume_role_web_identity_credentials.rb +14 -7
  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 +308 -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 +30 -55
  19. data/lib/aws-sdk-core/credential_provider.rb +4 -0
  20. data/lib/aws-sdk-core/credential_provider_chain.rb +38 -11
  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 +1 -0
  24. data/lib/aws-sdk-core/endpoints/endpoint.rb +3 -1
  25. data/lib/aws-sdk-core/endpoints/matchers.rb +8 -10
  26. data/lib/aws-sdk-core/endpoints.rb +101 -21
  27. data/lib/aws-sdk-core/error_handler.rb +46 -0
  28. data/lib/aws-sdk-core/errors.rb +11 -2
  29. data/lib/aws-sdk-core/event_emitter.rb +1 -17
  30. data/lib/aws-sdk-core/instance_profile_credentials.rb +148 -158
  31. data/lib/aws-sdk-core/json/builder.rb +8 -1
  32. data/lib/aws-sdk-core/json/error_handler.rb +29 -13
  33. data/lib/aws-sdk-core/json/handler.rb +6 -6
  34. data/lib/aws-sdk-core/json/json_engine.rb +3 -1
  35. data/lib/aws-sdk-core/json/oj_engine.rb +7 -1
  36. data/lib/aws-sdk-core/json/parser.rb +6 -1
  37. data/lib/aws-sdk-core/json.rb +43 -14
  38. data/lib/aws-sdk-core/log/param_filter.rb +2 -2
  39. data/lib/aws-sdk-core/log/param_formatter.rb +7 -3
  40. data/lib/aws-sdk-core/log.rb +10 -0
  41. data/lib/aws-sdk-core/lru_cache.rb +75 -0
  42. data/lib/aws-sdk-core/pageable_response.rb +1 -1
  43. data/lib/aws-sdk-core/param_validator.rb +7 -2
  44. data/lib/aws-sdk-core/plugins/bearer_authorization.rb +2 -0
  45. data/lib/aws-sdk-core/plugins/checksum_algorithm.rb +332 -169
  46. data/lib/aws-sdk-core/plugins/client_metrics_plugin.rb +0 -1
  47. data/lib/aws-sdk-core/plugins/client_metrics_send_plugin.rb +14 -2
  48. data/lib/aws-sdk-core/plugins/credentials_configuration.rb +77 -57
  49. data/lib/aws-sdk-core/plugins/endpoint_pattern.rb +40 -32
  50. data/lib/aws-sdk-core/plugins/global_configuration.rb +8 -9
  51. data/lib/aws-sdk-core/plugins/http_checksum.rb +2 -8
  52. data/lib/aws-sdk-core/plugins/invocation_id.rb +1 -11
  53. data/lib/aws-sdk-core/plugins/protocols/api_gateway.rb +3 -1
  54. data/lib/aws-sdk-core/plugins/protocols/ec2.rb +2 -24
  55. data/lib/aws-sdk-core/plugins/protocols/json_rpc.rb +6 -8
  56. data/lib/aws-sdk-core/plugins/protocols/query.rb +4 -2
  57. data/lib/aws-sdk-core/plugins/protocols/rest_json.rb +3 -15
  58. data/lib/aws-sdk-core/plugins/protocols/rest_xml.rb +3 -0
  59. data/lib/aws-sdk-core/plugins/protocols/rpc_v2.rb +17 -0
  60. data/lib/aws-sdk-core/plugins/regional_endpoint.rb +74 -25
  61. data/lib/aws-sdk-core/plugins/request_compression.rb +11 -2
  62. data/lib/aws-sdk-core/plugins/retry_errors.rb +10 -3
  63. data/lib/aws-sdk-core/plugins/sign.rb +42 -26
  64. data/lib/aws-sdk-core/plugins/signature_v2.rb +2 -1
  65. data/lib/aws-sdk-core/plugins/signature_v4.rb +2 -1
  66. data/lib/aws-sdk-core/plugins/stub_responses.rb +58 -9
  67. data/lib/aws-sdk-core/plugins/telemetry.rb +75 -0
  68. data/lib/aws-sdk-core/plugins/transfer_encoding.rb +16 -9
  69. data/lib/aws-sdk-core/plugins/user_agent.rb +101 -26
  70. data/lib/aws-sdk-core/plugins.rb +39 -0
  71. data/lib/aws-sdk-core/process_credentials.rb +48 -29
  72. data/lib/aws-sdk-core/query/ec2_handler.rb +27 -0
  73. data/lib/aws-sdk-core/query/ec2_param_builder.rb +5 -7
  74. data/lib/aws-sdk-core/query/handler.rb +4 -4
  75. data/lib/aws-sdk-core/query/param_builder.rb +2 -2
  76. data/lib/aws-sdk-core/query.rb +2 -1
  77. data/lib/aws-sdk-core/resources.rb +8 -0
  78. data/lib/aws-sdk-core/rest/content_type_handler.rb +60 -0
  79. data/lib/aws-sdk-core/rest/handler.rb +3 -4
  80. data/lib/aws-sdk-core/rest/request/body.rb +32 -5
  81. data/lib/aws-sdk-core/rest/request/endpoint.rb +24 -4
  82. data/lib/aws-sdk-core/rest/request/headers.rb +15 -7
  83. data/lib/aws-sdk-core/rest/request/querystring_builder.rb +23 -11
  84. data/lib/aws-sdk-core/rest/response/body.rb +15 -1
  85. data/lib/aws-sdk-core/rest/response/header_list_parser.rb +79 -0
  86. data/lib/aws-sdk-core/rest/response/headers.rb +8 -3
  87. data/lib/aws-sdk-core/rest.rb +1 -0
  88. data/lib/aws-sdk-core/rpc_v2/builder.rb +62 -0
  89. data/lib/aws-sdk-core/rpc_v2/cbor_engine.rb +18 -0
  90. data/lib/aws-sdk-core/rpc_v2/content_type_handler.rb +47 -0
  91. data/lib/aws-sdk-core/rpc_v2/error_handler.rb +95 -0
  92. data/lib/aws-sdk-core/rpc_v2/handler.rb +79 -0
  93. data/lib/aws-sdk-core/rpc_v2/parser.rb +98 -0
  94. data/lib/aws-sdk-core/rpc_v2.rb +69 -0
  95. data/lib/aws-sdk-core/shared_config.rb +79 -22
  96. data/lib/aws-sdk-core/shared_credentials.rb +1 -7
  97. data/lib/aws-sdk-core/sso_credentials.rb +4 -1
  98. data/lib/aws-sdk-core/static_token_provider.rb +1 -2
  99. data/lib/aws-sdk-core/stubbing/protocols/ec2.rb +12 -11
  100. data/lib/aws-sdk-core/stubbing/protocols/json.rb +11 -10
  101. data/lib/aws-sdk-core/stubbing/protocols/query.rb +7 -6
  102. data/lib/aws-sdk-core/stubbing/protocols/rest.rb +2 -1
  103. data/lib/aws-sdk-core/stubbing/protocols/rest_json.rb +9 -8
  104. data/lib/aws-sdk-core/stubbing/protocols/rest_xml.rb +6 -5
  105. data/lib/aws-sdk-core/stubbing/protocols/rpc_v2.rb +39 -0
  106. data/lib/aws-sdk-core/stubbing.rb +22 -0
  107. data/lib/aws-sdk-core/telemetry/base.rb +177 -0
  108. data/lib/aws-sdk-core/telemetry/no_op.rb +70 -0
  109. data/lib/aws-sdk-core/telemetry/otel.rb +235 -0
  110. data/lib/aws-sdk-core/telemetry/span_kind.rb +22 -0
  111. data/lib/aws-sdk-core/telemetry/span_status.rb +59 -0
  112. data/lib/aws-sdk-core/telemetry.rb +78 -0
  113. data/lib/aws-sdk-core/token.rb +3 -3
  114. data/lib/aws-sdk-core/token_provider.rb +4 -0
  115. data/lib/aws-sdk-core/token_provider_chain.rb +2 -6
  116. data/lib/aws-sdk-core/util.rb +41 -1
  117. data/lib/aws-sdk-core/waiters/poller.rb +10 -5
  118. data/lib/aws-sdk-core/xml/builder.rb +17 -9
  119. data/lib/aws-sdk-core/xml/error_handler.rb +35 -43
  120. data/lib/aws-sdk-core/xml/parser/frame.rb +4 -20
  121. data/lib/aws-sdk-core/xml/parser/stack.rb +2 -0
  122. data/lib/aws-sdk-core/xml/parser.rb +2 -6
  123. data/lib/aws-sdk-core.rb +82 -107
  124. data/lib/aws-sdk-sso/client.rb +189 -96
  125. data/lib/aws-sdk-sso/client_api.rb +7 -0
  126. data/lib/aws-sdk-sso/endpoint_parameters.rb +9 -6
  127. data/lib/aws-sdk-sso/endpoint_provider.rb +14 -18
  128. data/lib/aws-sdk-sso/endpoints.rb +2 -54
  129. data/lib/aws-sdk-sso/plugins/endpoints.rb +19 -20
  130. data/lib/aws-sdk-sso/types.rb +1 -0
  131. data/lib/aws-sdk-sso.rb +15 -11
  132. data/lib/aws-sdk-ssooidc/client.rb +274 -116
  133. data/lib/aws-sdk-ssooidc/client_api.rb +33 -0
  134. data/lib/aws-sdk-ssooidc/endpoint_parameters.rb +9 -6
  135. data/lib/aws-sdk-ssooidc/endpoint_provider.rb +14 -18
  136. data/lib/aws-sdk-ssooidc/endpoints.rb +2 -54
  137. data/lib/aws-sdk-ssooidc/errors.rb +21 -0
  138. data/lib/aws-sdk-ssooidc/plugins/endpoints.rb +19 -20
  139. data/lib/aws-sdk-ssooidc/types.rb +125 -24
  140. data/lib/aws-sdk-ssooidc.rb +15 -11
  141. data/lib/aws-sdk-sts/client.rb +397 -148
  142. data/lib/aws-sdk-sts/client_api.rb +36 -8
  143. data/lib/aws-sdk-sts/customizations.rb +5 -1
  144. data/lib/aws-sdk-sts/endpoint_parameters.rb +10 -9
  145. data/lib/aws-sdk-sts/endpoint_provider.rb +50 -55
  146. data/lib/aws-sdk-sts/endpoints.rb +2 -118
  147. data/lib/aws-sdk-sts/errors.rb +15 -0
  148. data/lib/aws-sdk-sts/plugins/endpoints.rb +19 -28
  149. data/lib/aws-sdk-sts/presigner.rb +2 -6
  150. data/lib/aws-sdk-sts/types.rb +171 -28
  151. data/lib/aws-sdk-sts.rb +15 -11
  152. data/lib/seahorse/client/async_base.rb +4 -5
  153. data/lib/seahorse/client/async_response.rb +19 -0
  154. data/lib/seahorse/client/base.rb +18 -21
  155. data/lib/seahorse/client/h2/connection.rb +18 -28
  156. data/lib/seahorse/client/h2/handler.rb +14 -3
  157. data/lib/seahorse/client/handler.rb +1 -1
  158. data/lib/seahorse/client/http/response.rb +1 -1
  159. data/lib/seahorse/client/net_http/connection_pool.rb +15 -12
  160. data/lib/seahorse/client/net_http/handler.rb +21 -9
  161. data/lib/seahorse/client/networking_error.rb +1 -1
  162. data/lib/seahorse/client/plugin.rb +8 -0
  163. data/lib/seahorse/client/plugins/endpoint.rb +0 -1
  164. data/lib/seahorse/client/plugins/h2.rb +4 -4
  165. data/lib/seahorse/client/plugins/net_http.rb +57 -16
  166. data/lib/seahorse/client/request_context.rb +9 -2
  167. data/lib/seahorse/client/response.rb +2 -0
  168. data/lib/seahorse/model/shapes.rb +2 -2
  169. data/lib/seahorse/util.rb +2 -1
  170. data/sig/aws-sdk-core/async_client_stubs.rbs +21 -0
  171. data/sig/aws-sdk-core/telemetry/base.rbs +46 -0
  172. data/sig/aws-sdk-core/telemetry/otel.rbs +22 -0
  173. data/sig/aws-sdk-core/telemetry/span_kind.rbs +15 -0
  174. data/sig/aws-sdk-core/telemetry/span_status.rbs +24 -0
  175. data/sig/seahorse/client/async_base.rbs +18 -0
  176. metadata +96 -23
  177. /data/lib/aws-sdk-core/xml/parser/{engines/libxml.rb → libxml_engine.rb} +0 -0
  178. /data/lib/aws-sdk-core/xml/parser/{engines/nokogiri.rb → nokogiri_engine.rb} +0 -0
  179. /data/lib/aws-sdk-core/xml/parser/{engines/oga.rb → oga_engine.rb} +0 -0
  180. /data/lib/aws-sdk-core/xml/parser/{engines/ox.rb → ox_engine.rb} +0 -0
  181. /data/lib/aws-sdk-core/xml/parser/{engines/rexml.rb → rexml_engine.rb} +0 -0
@@ -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
- # instance metadata service. Any of these imply the service
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
- # 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 [Boolean] :disable_imds_v1 (false) Disable the use of the
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
- # with exponential back-off, i.e. `sleep(1.2 ** num_failures)`. You can
65
- # pass a number of seconds to sleep between failed attempts, or
66
- # a Proc that accepts the number of failures.
67
- # @option options [IO] :http_debug_output (nil) HTTP wire
68
- # traces are sent to this object. You can specify something
69
- # like $stdout.
70
- # @option options [Integer] :token_ttl Time-to-Live in seconds for EC2
71
- # Metadata Token used for fetching Metadata Profile Credentials, defaults
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
- @retries = options[:retries] || 1
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
- # Flag for if v2 flow fails, skip future attempts
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
- @backoff = backoff(options[:backoff])
86
+ @port = options[:port] || 80
87
+ @retries = options[:retries] || 1
89
88
  @token_ttl = options[:token_ttl] || 21_600
90
- @token = nil
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 [Integer] Number of times to retry when retrieving credentials
97
- # from the instance metadata service. Defaults to 0 when resolving from
98
- # the default credential chain ({Aws::CredentialProviderChain}).
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
- value = options[:endpoint_mode]
105
- value ||= ENV['AWS_EC2_METADATA_SERVICE_ENDPOINT_MODE']
106
- value ||= Aws.shared_config.ec2_metadata_service_endpoint_mode(
107
- profile: options[:profile]
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, endpoint_mode)
113
- value = options[:endpoint] || options[:ip_address]
114
- value ||= ENV['AWS_EC2_METADATA_SERVICE_ENDPOINT']
115
- value ||= Aws.shared_config.ec2_metadata_service_endpoint(
116
- profile: options[:profile]
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 = options[:disable_imds_v1]
133
- value ||= ENV['AWS_EC2_METADATA_V1_DISABLED']
134
- value ||= Aws.shared_config.ec2_metadata_v1_disabled(
135
- profile: options[:profile]
136
- )
137
- value = value.to_s.downcase if 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 backoff(backoff)
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
- # Retry loading credentials up to 3 times is the instance metadata
156
- # service is responding but is returning invalid JSON documents
157
- # in response to the GET profile credentials call.
158
- begin
159
- retry_errors([Aws::Json::ParseError], max_retries: 3) do
160
- c = Aws::Json.load(get_credentials.to_s)
161
- if empty_credentials?(@credentials)
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
- rescue Aws::Json::ParseError
193
- raise Aws::Errors::MetadataParserError
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 get_credentials
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
- if _metadata_disabled?
201
- '{}'
202
- else
203
- begin
204
- retry_errors(NETWORK_ERRORS, max_retries: @retries) do
205
- open_connection do |conn|
206
- # attempt to fetch token to start secure flow first
207
- # and rescue to failover
208
- fetch_token(conn) unless @imds_v1_fallback
209
- token = @token.value if token_set?
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
- retry_errors(NETWORK_ERRORS, max_retries: @retries) do
227
- unless token_set?
228
- created_time = Time.now
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
- # token is optional - if nil, uses v1 (insecure) flow
243
- def _get_credentials(conn, token)
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, token)
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,13 +256,9 @@ 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
- http = Net::HTTP.new(uri.hostname || @endpoint, @port || uri.port)
261
+ http = Net::HTTP.new(uri.hostname || @endpoint, uri.port || @port)
266
262
  http.open_timeout = @http_open_timeout
267
263
  http.read_timeout = @http_read_timeout
268
264
  http.set_debug_output(@http_debug_output) if @http_debug_output
@@ -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, token = nil)
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, path, ttl)
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' => ttl.to_s
289
+ 'x-aws-ec2-metadata-token-ttl-seconds' => @token_ttl.to_s
294
290
  }
295
- response = connection.request(Net::HTTP::Put.new(path, headers))
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("Attempting credential expiration extension due to a credential "\
325
- "service availability issue. A refresh of these credentials "\
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
- # Compute an offset for refresh with jitter
334
- def refresh_offset
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
@@ -8,7 +8,7 @@ module Aws
8
8
 
9
9
  include Seahorse::Model::Shapes
10
10
 
11
- def initialize(rules)
11
+ def initialize(rules, _options = {})
12
12
  @rules = rules
13
13
  end
14
14
 
@@ -20,6 +20,8 @@ module Aws
20
20
  private
21
21
 
22
22
  def structure(ref, values)
23
+ return nil if values.nil?
24
+
23
25
  shape = ref.shape
24
26
  values.each_pair.with_object({}) do |(key, value), data|
25
27
  if shape.member?(key) && !value.nil?
@@ -31,11 +33,15 @@ module Aws
31
33
  end
32
34
 
33
35
  def list(ref, values)
36
+ return nil if values.nil?
37
+
34
38
  member_ref = ref.shape.member
35
39
  values.collect { |value| format(member_ref, value) }
36
40
  end
37
41
 
38
42
  def map(ref, values)
43
+ return nil if values.nil?
44
+
39
45
  value_ref = ref.shape.value
40
46
  values.each.with_object({}) do |(key, value), data|
41
47
  data[key] = format(value_ref, value)
@@ -49,6 +55,7 @@ module Aws
49
55
  when MapShape then map(ref, value)
50
56
  when TimestampShape then timestamp(ref, value)
51
57
  when BlobShape then encode(value)
58
+ when FloatShape then Util.serialize_number(value)
52
59
  else value
53
60
  end
54
61
  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
@@ -63,22 +72,29 @@ module Aws
63
72
  end
64
73
  end
65
74
 
66
- def parse_error_data(context, code)
75
+ def parse_error_data(context, body, code)
67
76
  data = EmptyStructure.new
68
- if error_rules = context.operation.errors
77
+ if (error_rules = context.operation.errors)
69
78
  error_rules.each do |rule|
70
79
  # match modeled shape name with the type(code) only
71
80
  # some type(code) might contains invalid characters
72
81
  # such as ':' (efs) etc
73
82
  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
83
+ next unless match && rule.shape.members.any?
84
+
85
+ data = Parser.new(rule).parse(body)
86
+ # errors support HTTP bindings
87
+ apply_error_headers(rule, context, data)
77
88
  end
78
89
  end
79
90
  data
80
91
  end
81
92
 
93
+ def apply_error_headers(rule, context, data)
94
+ headers = Aws::Rest::Response::Headers.new(rule)
95
+ headers.apply(context.http_response, data)
96
+ end
97
+
82
98
  end
83
99
  end
84
100
  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)
@@ -62,7 +62,7 @@ module Aws
62
62
  Parser.new(
63
63
  rules,
64
64
  query_compatible: query_compatible?(context)
65
- ).parse(json == '' ? '{}' : json)
65
+ ).parse(json)
66
66
  end
67
67
  else
68
68
  EmptyStructure.new
@@ -1,8 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'json'
4
+
3
5
  module Aws
4
6
  module Json
5
- module JSONEngine
7
+ module JsonEngine
6
8
  class << self
7
9
  def load(json)
8
10
  JSON.parse(json)
@@ -1,10 +1,16 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'oj'
4
+
3
5
  module Aws
4
6
  module Json
5
7
  module OjEngine
6
8
  # @api private
7
- LOAD_OPTIONS = { mode: :compat, symbol_keys: false, empty_string: false }.freeze
9
+ LOAD_OPTIONS = {
10
+ mode: :compat,
11
+ symbol_keys: false,
12
+ empty_string: false
13
+ }.freeze
8
14
 
9
15
  # @api private
10
16
  DUMP_OPTIONS = { mode: :compat }.freeze
@@ -17,6 +17,8 @@ module Aws
17
17
 
18
18
  # @param [String<JSON>] json
19
19
  def parse(json, target = nil)
20
+ json = '{}' if json.empty?
21
+
20
22
  parse_ref(@rules, Json.load(json), target)
21
23
  end
22
24
 
@@ -69,6 +71,8 @@ module Aws
69
71
  def map(ref, values, target = nil)
70
72
  target = {} if target.nil?
71
73
  values.each do |key, value|
74
+ next if value.nil?
75
+
72
76
  target[key] = parse_ref(ref.shape.value, value)
73
77
  end
74
78
  target
@@ -85,6 +89,7 @@ module Aws
85
89
  when TimestampShape then time(value)
86
90
  when BlobShape then Base64.decode64(value)
87
91
  when BooleanShape then value.to_s == 'true'
92
+ when FloatShape then Util.deserialize_number(value)
88
93
  else value
89
94
  end
90
95
  end
@@ -93,7 +98,7 @@ module Aws
93
98
  # @param [String, Integer] value
94
99
  # @return [Time]
95
100
  def time(value)
96
- value.is_a?(Numeric) ? Time.at(value) : Time.parse(value)
101
+ value.is_a?(Numeric) ? Time.at(value) : Aws::Util.deserialize_time(value)
97
102
  end
98
103
 
99
104
  def flattened_list?(shape)