aws-sdk-core 3.171.1 → 3.199.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 (143) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +363 -0
  3. data/VERSION +1 -1
  4. data/lib/aws-defaults/default_configuration.rb +4 -4
  5. data/lib/aws-sdk-core/binary/decode_handler.rb +3 -9
  6. data/lib/aws-sdk-core/binary/encode_handler.rb +1 -1
  7. data/lib/aws-sdk-core/binary/event_builder.rb +34 -37
  8. data/lib/aws-sdk-core/binary/event_stream_decoder.rb +1 -0
  9. data/lib/aws-sdk-core/binary/event_stream_encoder.rb +4 -3
  10. data/lib/aws-sdk-core/cbor/cbor_engine.rb +19 -0
  11. data/lib/aws-sdk-core/cbor/decoder.rb +310 -0
  12. data/lib/aws-sdk-core/cbor/encoder.rb +243 -0
  13. data/lib/aws-sdk-core/cbor.rb +106 -0
  14. data/lib/aws-sdk-core/client_stubs.rb +18 -14
  15. data/lib/aws-sdk-core/credential_provider.rb +4 -1
  16. data/lib/aws-sdk-core/ec2_metadata.rb +1 -1
  17. data/lib/aws-sdk-core/ecs_credentials.rb +78 -11
  18. data/lib/aws-sdk-core/endpoints/matchers.rb +18 -10
  19. data/lib/aws-sdk-core/endpoints.rb +6 -2
  20. data/lib/aws-sdk-core/error_handler.rb +41 -0
  21. data/lib/aws-sdk-core/errors.rb +3 -3
  22. data/lib/aws-sdk-core/event_emitter.rb +0 -16
  23. data/lib/aws-sdk-core/ini_parser.rb +7 -0
  24. data/lib/aws-sdk-core/instance_profile_credentials.rb +55 -32
  25. data/lib/aws-sdk-core/json/builder.rb +8 -1
  26. data/lib/aws-sdk-core/json/error_handler.rb +15 -10
  27. data/lib/aws-sdk-core/json/handler.rb +12 -6
  28. data/lib/aws-sdk-core/json/json_engine.rb +3 -1
  29. data/lib/aws-sdk-core/json/oj_engine.rb +7 -1
  30. data/lib/aws-sdk-core/json/parser.rb +33 -3
  31. data/lib/aws-sdk-core/json.rb +43 -14
  32. data/lib/aws-sdk-core/log/formatter.rb +6 -0
  33. data/lib/aws-sdk-core/lru_cache.rb +75 -0
  34. data/lib/aws-sdk-core/pageable_response.rb +3 -1
  35. data/lib/aws-sdk-core/param_validator.rb +9 -4
  36. data/lib/aws-sdk-core/plugins/checksum_algorithm.rb +5 -3
  37. data/lib/aws-sdk-core/plugins/client_metrics_plugin.rb +1 -0
  38. data/lib/aws-sdk-core/plugins/client_metrics_send_plugin.rb +14 -2
  39. data/lib/aws-sdk-core/plugins/credentials_configuration.rb +2 -0
  40. data/lib/aws-sdk-core/plugins/global_configuration.rb +8 -9
  41. data/lib/aws-sdk-core/plugins/http_checksum.rb +2 -1
  42. data/lib/aws-sdk-core/plugins/invocation_id.rb +1 -11
  43. data/lib/aws-sdk-core/plugins/logging.rb +2 -0
  44. data/lib/aws-sdk-core/plugins/protocols/api_gateway.rb +3 -1
  45. data/lib/aws-sdk-core/plugins/protocols/ec2.rb +2 -24
  46. data/lib/aws-sdk-core/plugins/protocols/json_rpc.rb +6 -8
  47. data/lib/aws-sdk-core/plugins/protocols/query.rb +4 -2
  48. data/lib/aws-sdk-core/plugins/protocols/rest_json.rb +3 -15
  49. data/lib/aws-sdk-core/plugins/protocols/rest_xml.rb +3 -0
  50. data/lib/aws-sdk-core/plugins/protocols/rpc_v2.rb +17 -0
  51. data/lib/aws-sdk-core/plugins/regional_endpoint.rb +109 -33
  52. data/lib/aws-sdk-core/plugins/request_compression.rb +226 -0
  53. data/lib/aws-sdk-core/plugins/retry_errors.rb +12 -3
  54. data/lib/aws-sdk-core/plugins/sign.rb +24 -13
  55. data/lib/aws-sdk-core/plugins/stub_responses.rb +1 -0
  56. data/lib/aws-sdk-core/plugins/user_agent.rb +152 -14
  57. data/lib/aws-sdk-core/process_credentials.rb +45 -27
  58. data/lib/aws-sdk-core/query/ec2_handler.rb +27 -0
  59. data/lib/aws-sdk-core/query/ec2_param_builder.rb +5 -7
  60. data/lib/aws-sdk-core/query/handler.rb +4 -4
  61. data/lib/aws-sdk-core/query/param_builder.rb +2 -2
  62. data/lib/aws-sdk-core/query.rb +2 -1
  63. data/lib/aws-sdk-core/refreshing_credentials.rb +12 -12
  64. data/lib/aws-sdk-core/rest/content_type_handler.rb +60 -0
  65. data/lib/aws-sdk-core/rest/handler.rb +3 -4
  66. data/lib/aws-sdk-core/rest/request/body.rb +32 -5
  67. data/lib/aws-sdk-core/rest/request/endpoint.rb +24 -4
  68. data/lib/aws-sdk-core/rest/request/headers.rb +15 -7
  69. data/lib/aws-sdk-core/rest/request/querystring_builder.rb +62 -36
  70. data/lib/aws-sdk-core/rest/response/body.rb +15 -1
  71. data/lib/aws-sdk-core/rest/response/header_list_parser.rb +79 -0
  72. data/lib/aws-sdk-core/rest/response/headers.rb +8 -3
  73. data/lib/aws-sdk-core/rest.rb +1 -0
  74. data/lib/aws-sdk-core/rpc_v2/builder.rb +62 -0
  75. data/lib/aws-sdk-core/rpc_v2/content_type_handler.rb +45 -0
  76. data/lib/aws-sdk-core/rpc_v2/error_handler.rb +84 -0
  77. data/lib/aws-sdk-core/rpc_v2/handler.rb +74 -0
  78. data/lib/aws-sdk-core/rpc_v2/parser.rb +90 -0
  79. data/lib/aws-sdk-core/rpc_v2.rb +6 -0
  80. data/lib/aws-sdk-core/shared_config.rb +48 -18
  81. data/lib/aws-sdk-core/sso_credentials.rb +1 -1
  82. data/lib/aws-sdk-core/stubbing/protocols/rpc_v2.rb +41 -0
  83. data/lib/aws-sdk-core/stubbing/stub_data.rb +11 -0
  84. data/lib/aws-sdk-core/util.rb +39 -0
  85. data/lib/aws-sdk-core/waiters/poller.rb +4 -2
  86. data/lib/aws-sdk-core/xml/builder.rb +17 -9
  87. data/lib/aws-sdk-core/xml/error_handler.rb +32 -42
  88. data/lib/aws-sdk-core/xml/parser/frame.rb +4 -20
  89. data/lib/aws-sdk-core/xml/parser/stack.rb +2 -0
  90. data/lib/aws-sdk-core/xml/parser.rb +2 -6
  91. data/lib/aws-sdk-core.rb +7 -2
  92. data/lib/aws-sdk-sso/client.rb +94 -46
  93. data/lib/aws-sdk-sso/endpoint_provider.rb +30 -24
  94. data/lib/aws-sdk-sso/endpoints.rb +1 -0
  95. data/lib/aws-sdk-sso/plugins/endpoints.rb +4 -2
  96. data/lib/aws-sdk-sso.rb +1 -1
  97. data/lib/aws-sdk-ssooidc/client.rb +479 -74
  98. data/lib/aws-sdk-ssooidc/client_api.rb +78 -1
  99. data/lib/aws-sdk-ssooidc/endpoint_provider.rb +30 -24
  100. data/lib/aws-sdk-ssooidc/endpoints.rb +15 -0
  101. data/lib/aws-sdk-ssooidc/errors.rb +52 -0
  102. data/lib/aws-sdk-ssooidc/plugins/endpoints.rb +6 -2
  103. data/lib/aws-sdk-ssooidc/types.rb +372 -51
  104. data/lib/aws-sdk-ssooidc.rb +1 -1
  105. data/lib/aws-sdk-sts/client.rb +219 -157
  106. data/lib/aws-sdk-sts/client_api.rb +20 -9
  107. data/lib/aws-sdk-sts/endpoint_provider.rb +81 -78
  108. data/lib/aws-sdk-sts/endpoints.rb +1 -0
  109. data/lib/aws-sdk-sts/plugins/endpoints.rb +4 -2
  110. data/lib/aws-sdk-sts/presigner.rb +1 -1
  111. data/lib/aws-sdk-sts/types.rb +49 -11
  112. data/lib/aws-sdk-sts.rb +1 -1
  113. data/lib/seahorse/client/async_base.rb +1 -1
  114. data/lib/seahorse/client/async_response.rb +19 -0
  115. data/lib/seahorse/client/base.rb +18 -7
  116. data/lib/seahorse/client/configuration.rb +0 -4
  117. data/lib/seahorse/client/h2/handler.rb +1 -0
  118. data/lib/seahorse/client/handler.rb +1 -1
  119. data/lib/seahorse/client/net_http/connection_pool.rb +3 -9
  120. data/lib/seahorse/client/net_http/patches.rb +1 -4
  121. data/lib/seahorse/client/plugin.rb +9 -0
  122. data/lib/seahorse/client/plugins/endpoint.rb +0 -1
  123. data/lib/seahorse/client/plugins/h2.rb +3 -3
  124. data/lib/seahorse/client/plugins/net_http.rb +48 -16
  125. data/lib/seahorse/client/plugins/request_callback.rb +31 -0
  126. data/lib/seahorse/client/response.rb +6 -0
  127. data/lib/seahorse/model/operation.rb +3 -0
  128. data/lib/seahorse/model/shapes.rb +2 -2
  129. data/sig/aws-sdk-core/client_stubs.rbs +10 -0
  130. data/sig/aws-sdk-core/errors.rbs +22 -0
  131. data/sig/aws-sdk-core/resources/collection.rbs +21 -0
  132. data/sig/aws-sdk-core/structure.rbs +4 -0
  133. data/sig/aws-sdk-core/waiters/errors.rbs +20 -0
  134. data/sig/aws-sdk-core.rbs +7 -0
  135. data/sig/seahorse/client/base.rbs +25 -0
  136. data/sig/seahorse/client/handler_builder.rbs +16 -0
  137. data/sig/seahorse/client/response.rbs +61 -0
  138. metadata +44 -17
  139. /data/lib/aws-sdk-core/xml/parser/{engines/libxml.rb → libxml_engine.rb} +0 -0
  140. /data/lib/aws-sdk-core/xml/parser/{engines/nokogiri.rb → nokogiri_engine.rb} +0 -0
  141. /data/lib/aws-sdk-core/xml/parser/{engines/oga.rb → oga_engine.rb} +0 -0
  142. /data/lib/aws-sdk-core/xml/parser/{engines/ox.rb → ox_engine.rb} +0 -0
  143. /data/lib/aws-sdk-core/xml/parser/{engines/rexml.rb → rexml_engine.rb} +0 -0
@@ -6,9 +6,12 @@ module Aws
6
6
  # @return [Credentials]
7
7
  attr_reader :credentials
8
8
 
9
+ # @return [Time]
10
+ attr_reader :expiration
11
+
9
12
  # @return [Boolean]
10
13
  def set?
11
- !!credentials && credentials.set?
14
+ !!@credentials && @credentials.set?
12
15
  end
13
16
 
14
17
  end
@@ -183,7 +183,7 @@ module Aws
183
183
 
184
184
  def open_connection
185
185
  uri = URI.parse(@endpoint)
186
- http = Net::HTTP.new(uri.hostname || @endpoint, @port || uri.port)
186
+ http = Net::HTTP.new(uri.hostname || @endpoint, uri.port || @port)
187
187
  http.open_timeout = @http_open_timeout
188
188
  http.read_timeout = @http_read_timeout
189
189
  http.set_debug_output(@http_debug_output) if @http_debug_output
@@ -6,7 +6,7 @@ require 'resolv'
6
6
 
7
7
  module Aws
8
8
  # An auto-refreshing credential provider that loads credentials from
9
- # instances running in ECS.
9
+ # instances running in containers.
10
10
  #
11
11
  # ecs_credentials = Aws::ECSCredentials.new(retries: 3)
12
12
  # ec2 = Aws::EC2::Client.new(credentials: ecs_credentials)
@@ -17,6 +17,12 @@ module Aws
17
17
  # @api private
18
18
  class Non200Response < RuntimeError; end
19
19
 
20
+ # Raised when the token file cannot be read.
21
+ class TokenFileReadError < RuntimeError; end
22
+
23
+ # Raised when the token file is invalid.
24
+ class InvalidTokenError < RuntimeError; end
25
+
20
26
  # These are the errors we trap when attempting to talk to the
21
27
  # instance metadata service. Any of these imply the service
22
28
  # is not present, no responding or some other non-recoverable
@@ -41,7 +47,7 @@ module Aws
41
47
  # is set and `credential_path` is not set.
42
48
  # @option options [String] :credential_path By default, the value of the
43
49
  # AWS_CONTAINER_CREDENTIALS_RELATIVE_URI environment variable.
44
- # @option options [String] :endpoint The ECS credential endpoint.
50
+ # @option options [String] :endpoint The container credential endpoint.
45
51
  # By default, this is the value of the AWS_CONTAINER_CREDENTIALS_FULL_URI
46
52
  # environment variable. This value is ignored if `credential_path` or
47
53
  # ENV['AWS_CONTAINER_CREDENTIALS_RELATIVE_URI'] is set.
@@ -64,7 +70,6 @@ module Aws
64
70
  endpoint = options[:endpoint] ||
65
71
  ENV['AWS_CONTAINER_CREDENTIALS_FULL_URI']
66
72
  initialize_uri(options, credential_path, endpoint)
67
- @authorization_token = ENV['AWS_CONTAINER_AUTHORIZATION_TOKEN']
68
73
 
69
74
  @retries = options[:retries] || 5
70
75
  @http_open_timeout = options[:http_open_timeout] || 5
@@ -103,11 +108,18 @@ module Aws
103
108
 
104
109
  def initialize_full_uri(endpoint)
105
110
  uri = URI.parse(endpoint)
111
+ validate_full_uri_scheme!(uri)
106
112
  validate_full_uri!(uri)
107
- @host = uri.host
113
+ @host = uri.hostname
108
114
  @port = uri.port
109
115
  @scheme = uri.scheme
110
- @credential_path = uri.path
116
+ @credential_path = uri.request_uri
117
+ end
118
+
119
+ def validate_full_uri_scheme!(full_uri)
120
+ return if full_uri.is_a?(URI::HTTP) || full_uri.is_a?(URI::HTTPS)
121
+
122
+ raise ArgumentError, "'#{full_uri}' must be a valid HTTP or HTTPS URI"
111
123
  end
112
124
 
113
125
  # Validate that the full URI is using a loopback address if scheme is http.
@@ -115,19 +127,24 @@ module Aws
115
127
  return unless full_uri.scheme == 'http'
116
128
 
117
129
  begin
118
- return if ip_loopback?(IPAddr.new(full_uri.host))
130
+ return if valid_ip_address?(IPAddr.new(full_uri.host))
119
131
  rescue IPAddr::InvalidAddressError
120
132
  addresses = Resolv.getaddresses(full_uri.host)
121
- return if addresses.all? { |addr| ip_loopback?(IPAddr.new(addr)) }
133
+ return if addresses.all? { |addr| valid_ip_address?(IPAddr.new(addr)) }
122
134
  end
123
135
 
124
136
  raise ArgumentError,
125
- 'AWS_CONTAINER_CREDENTIALS_FULL_URI must use a loopback '\
126
- 'address when using the http scheme.'
137
+ 'AWS_CONTAINER_CREDENTIALS_FULL_URI must use a local loopback '\
138
+ 'or an ECS or EKS link-local address when using the http scheme.'
139
+ end
140
+
141
+ def valid_ip_address?(ip_address)
142
+ ip_loopback?(ip_address) || ecs_or_eks_ip?(ip_address)
127
143
  end
128
144
 
129
145
  # loopback? method is available in Ruby 2.5+
130
146
  # Replicate the logic here.
147
+ # loopback (IPv4 127.0.0.0/8, IPv6 ::1/128)
131
148
  def ip_loopback?(ip_address)
132
149
  case ip_address.family
133
150
  when Socket::AF_INET
@@ -139,6 +156,20 @@ module Aws
139
156
  end
140
157
  end
141
158
 
159
+ # Verify that the IP address is a link-local address from ECS or EKS.
160
+ # ECS container host (IPv4 `169.254.170.2`)
161
+ # EKS container host (IPv4 `169.254.170.23`, IPv6 `fd00:ec2::23`)
162
+ def ecs_or_eks_ip?(ip_address)
163
+ case ip_address.family
164
+ when Socket::AF_INET
165
+ [0xa9feaa02, 0xa9feaa17].include?(ip_address)
166
+ when Socket::AF_INET6
167
+ ip_address == 0xfd00_0ec2_0000_0000_0000_0000_0000_0023
168
+ else
169
+ false
170
+ end
171
+ end
172
+
142
173
  def backoff(backoff)
143
174
  case backoff
144
175
  when Proc then backoff
@@ -174,10 +205,37 @@ module Aws
174
205
  http_get(conn, @credential_path)
175
206
  end
176
207
  end
177
- rescue StandardError
208
+ rescue TokenFileReadError, InvalidTokenError
209
+ raise
210
+ rescue StandardError => e
211
+ warn("Error retrieving ECS Credentials: #{e.message}")
178
212
  '{}'
179
213
  end
180
214
 
215
+ def fetch_authorization_token
216
+ if (path = ENV['AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE'])
217
+ fetch_authorization_token_file(path)
218
+ elsif (token = ENV['AWS_CONTAINER_AUTHORIZATION_TOKEN'])
219
+ token
220
+ end
221
+ end
222
+
223
+ def fetch_authorization_token_file(path)
224
+ File.read(path).strip
225
+ rescue Errno::ENOENT
226
+ raise TokenFileReadError,
227
+ 'AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE is set '\
228
+ "but the file doesn't exist: #{path}"
229
+ end
230
+
231
+ def validate_authorization_token!(token)
232
+ return unless token.include?("\r\n")
233
+
234
+ raise InvalidTokenError,
235
+ 'Invalid Authorization token: token contains '\
236
+ 'a newline and carriage return character.'
237
+ end
238
+
181
239
  def open_connection
182
240
  http = Net::HTTP.new(@host, @port, nil)
183
241
  http.open_timeout = @http_open_timeout
@@ -190,18 +248,27 @@ module Aws
190
248
 
191
249
  def http_get(connection, path)
192
250
  request = Net::HTTP::Get.new(path)
193
- request['Authorization'] = @authorization_token if @authorization_token
251
+ set_authorization_token(request)
194
252
  response = connection.request(request)
195
253
  raise Non200Response unless response.code.to_i == 200
196
254
 
197
255
  response.body
198
256
  end
199
257
 
258
+ def set_authorization_token(request)
259
+ if (authorization_token = fetch_authorization_token)
260
+ validate_authorization_token!(authorization_token)
261
+ request['Authorization'] = authorization_token
262
+ end
263
+ end
264
+
200
265
  def retry_errors(error_classes, options = {})
201
266
  max_retries = options[:max_retries]
202
267
  retries = 0
203
268
  begin
204
269
  yield
270
+ rescue TokenFileReadError, InvalidTokenError
271
+ raise
205
272
  rescue *error_classes => _e
206
273
  raise unless retries < max_retries
207
274
 
@@ -28,7 +28,11 @@ module Aws
28
28
 
29
29
  val = if (index = parts.first[BRACKET_REGEX, 1])
30
30
  # remove brackets and index from part before indexing
31
- value[parts.first.gsub(BRACKET_REGEX, '')][index.to_i]
31
+ if (base = parts.first.gsub(BRACKET_REGEX, '')) && !base.empty?
32
+ value[base][index.to_i]
33
+ else
34
+ value[index.to_i]
35
+ end
32
36
  else
33
37
  value[parts.first]
34
38
  end
@@ -79,11 +83,11 @@ module Aws
79
83
  return false if value.empty?
80
84
 
81
85
  if allow_sub_domains
82
- labels = value.split('.')
86
+ labels = value.split('.', -1)
83
87
  return labels.all? { |l| valid_host_label?(l) }
84
88
  end
85
89
 
86
- value =~ /\A(?!-)[a-zA-Z0-9-]{1,63}(?<!-)\z/
90
+ !!(value =~ /\A(?!-)[a-zA-Z0-9-]{1,63}(?<!-)\z/)
87
91
  end
88
92
 
89
93
  # AWS
@@ -114,13 +118,17 @@ module Aws
114
118
 
115
119
  # aws.isVirtualHostableS3Bucket(value: string, allowSubDomains: bool) bool
116
120
  def self.aws_virtual_hostable_s3_bucket?(value, allow_sub_domains = false)
117
- !!(value.size < 64 &&
118
- # regular naming rules
119
- value =~ /^[a-z0-9][a-z0-9\-#{'.' if allow_sub_domains}]+[a-z0-9]$/ &&
120
- # not IP address
121
- value !~ /(\d+\.){3}\d+/ &&
122
- # no dash and hyphen together
123
- value !~ /[.-]{2}/)
121
+ return false if value.empty?
122
+
123
+ if allow_sub_domains
124
+ labels = value.split('.', -1)
125
+ return labels.all? { |l| aws_virtual_hostable_s3_bucket?(l) }
126
+ end
127
+
128
+ # must be between 3 and 63 characters long, no uppercase
129
+ value =~ /\A(?!-)[a-z0-9-]{3,63}(?<!-)\z/ &&
130
+ # not an IP address
131
+ value !~ /(\d+\.){3}\d+/
124
132
  end
125
133
  end
126
134
  end
@@ -39,7 +39,11 @@ module Aws
39
39
  auth_scheme = { 'name' => 'sigv4' }
40
40
  merge_signing_defaults(auth_scheme, context.config)
41
41
  when 's3', 's3v4'
42
- auth_scheme = { 'name' => 'sigv4', 'disableDoubleEncoding' => true }
42
+ auth_scheme = {
43
+ 'name' => 'sigv4',
44
+ 'disableDoubleEncoding' => true,
45
+ 'disableNormalizePath' => true
46
+ }
43
47
  merge_signing_defaults(auth_scheme, context.config)
44
48
  when 'bearer'
45
49
  { 'name' => 'bearer' }
@@ -49,7 +53,7 @@ module Aws
49
53
  end
50
54
 
51
55
  def merge_signing_defaults(auth_scheme, config)
52
- if %w[sigv4 sigv4a].include?(auth_scheme['name'])
56
+ if %w[sigv4 sigv4a sigv4-s3express].include?(auth_scheme['name'])
53
57
  auth_scheme['signingName'] ||= sigv4_name(config)
54
58
  if auth_scheme['name'] == 'sigv4a'
55
59
  auth_scheme['signingRegionSet'] ||= ['*']
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Aws
4
+ class ErrorHandler < Seahorse::Client::Handler
5
+
6
+ private
7
+
8
+ def error(context)
9
+ body = context.http_response.body_contents
10
+ if body.empty?
11
+ code, message, data = http_status_error(context)
12
+ else
13
+ code, message, data = extract_error(body, context)
14
+ end
15
+ build_error(context, code, message, data)
16
+ end
17
+
18
+ def build_error(context, code, message, data)
19
+ errors_module = context.client.class.errors_module
20
+ errors_module.error_class(code).new(context, message, data)
21
+ end
22
+
23
+ def http_status_error(context)
24
+ [http_status_error_code(context), '', EmptyStructure.new]
25
+ end
26
+
27
+ def http_status_error_code(context)
28
+ status_code = context.http_response.status_code
29
+ {
30
+ 302 => 'MovedTemporarily',
31
+ 304 => 'NotModified',
32
+ 400 => 'BadRequest',
33
+ 403 => 'Forbidden',
34
+ 404 => 'NotFound',
35
+ 412 => 'PreconditionFailed',
36
+ 413 => 'RequestEntityTooLarge',
37
+ }[status_code] || "Http#{status_code}Error"
38
+ end
39
+
40
+ end
41
+ end
@@ -12,7 +12,7 @@ module Aws
12
12
  class ServiceError < RuntimeError
13
13
 
14
14
  # @param [Seahorse::Client::RequestContext] context
15
- # @param [String] message
15
+ # @param [String, nil] message
16
16
  # @param [Aws::Structure] data
17
17
  def initialize(context, message, data = Aws::EmptyStructure.new)
18
18
  @code = self.class.code
@@ -30,11 +30,11 @@ module Aws
30
30
  attr_reader :context
31
31
 
32
32
  # @return [Aws::Structure]
33
- attr_reader :data
33
+ attr_accessor :data
34
34
 
35
35
  class << self
36
36
 
37
- # @return [String]
37
+ # @return [String, nil]
38
38
  attr_accessor :code
39
39
 
40
40
  end
@@ -6,7 +6,6 @@ module Aws
6
6
  def initialize
7
7
  @listeners = {}
8
8
  @validate_event = true
9
- @status = :sleep
10
9
  @signal_queue = Queue.new
11
10
  end
12
11
 
@@ -40,25 +39,10 @@ module Aws
40
39
  Aws::ParamValidator.validate!(
41
40
  @encoder.rules.shape.member(type), params)
42
41
  end
43
- _ready_for_events?
44
42
  @stream.data(
45
43
  @encoder.encode(type, params),
46
44
  end_stream: type == :end_stream
47
45
  )
48
46
  end
49
-
50
- private
51
-
52
- def _ready_for_events?
53
- return true if @status == :ready
54
-
55
- # blocked until once initial 200 response is received
56
- # signal will be available in @signal_queue
57
- # and this check will no longer be blocked
58
- @signal_queue.pop
59
- @status = :ready
60
- true
61
- end
62
-
63
47
  end
64
48
  end
@@ -8,6 +8,8 @@ module Aws
8
8
  def ini_parse(raw)
9
9
  current_profile = nil
10
10
  current_prefix = nil
11
+ item = nil
12
+ previous_item = nil
11
13
  raw.lines.inject({}) do |acc, line|
12
14
  line = line.split(/^|\s;/).first # remove comments
13
15
  profile = line.match(/^\[([^\[\]]+)\]\s*(#.+)?$/) unless line.nil?
@@ -17,11 +19,16 @@ module Aws
17
19
  current_profile = named_profile[1] if named_profile
18
20
  elsif current_profile
19
21
  unless line.nil?
22
+ previous_item = item
20
23
  item = line.match(/^(.+?)\s*=\s*(.+?)\s*$/)
21
24
  prefix = line.match(/^(.+?)\s*=\s*$/)
22
25
  end
23
26
  if item && item[1].match(/^\s+/)
24
27
  # Need to add lines to a nested configuration.
28
+ if current_prefix.nil? && previous_item[2].strip.empty?
29
+ current_prefix = previous_item[1]
30
+ acc[current_profile][current_prefix] = {}
31
+ end
25
32
  inner_item = line.match(/^\s*(.+?)\s*=\s*(.+?)\s*$/)
26
33
  acc[current_profile] ||= {}
27
34
  acc[current_profile][current_prefix] ||= {}
@@ -53,6 +53,8 @@ module Aws
53
53
  # @option options [String] :endpoint_mode ('IPv4') The endpoint mode for
54
54
  # the instance metadata service. This is either 'IPv4' ('169.254.169.254')
55
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.
56
58
  # @option options [String] :ip_address ('169.254.169.254') Deprecated. Use
57
59
  # :endpoint instead. The IP address for the endpoint.
58
60
  # @option options [Integer] :port (80)
@@ -77,6 +79,9 @@ module Aws
77
79
  endpoint_mode = resolve_endpoint_mode(options)
78
80
  @endpoint = resolve_endpoint(options, endpoint_mode)
79
81
  @port = options[:port] || 80
82
+ @disable_imds_v1 = resolve_disable_v1(options)
83
+ # Flag for if v2 flow fails, skip future attempts
84
+ @imds_v1_fallback = false
80
85
  @http_open_timeout = options[:http_open_timeout] || 1
81
86
  @http_read_timeout = options[:http_read_timeout] || 1
82
87
  @http_debug_output = options[:http_debug_output]
@@ -123,6 +128,16 @@ module Aws
123
128
  end
124
129
  end
125
130
 
131
+ 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
139
+ end
140
+
126
141
  def backoff(backoff)
127
142
  case backoff
128
143
  when Proc then backoff
@@ -141,7 +156,7 @@ module Aws
141
156
  # service is responding but is returning invalid JSON documents
142
157
  # in response to the GET profile credentials call.
143
158
  begin
144
- retry_errors([Aws::Json::ParseError, StandardError], max_retries: 3) do
159
+ retry_errors([Aws::Json::ParseError], max_retries: 3) do
145
160
  c = Aws::Json.load(get_credentials.to_s)
146
161
  if empty_credentials?(@credentials)
147
162
  @credentials = Credentials.new(
@@ -173,7 +188,6 @@ module Aws
173
188
  end
174
189
  end
175
190
  end
176
-
177
191
  end
178
192
  rescue Aws::Json::ParseError
179
193
  raise Aws::Errors::MetadataParserError
@@ -191,42 +205,53 @@ module Aws
191
205
  open_connection do |conn|
192
206
  # attempt to fetch token to start secure flow first
193
207
  # 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
-
208
+ fetch_token(conn) unless @imds_v1_fallback
210
209
  token = @token.value if token_set?
211
210
 
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
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)
222
216
  end
223
217
  end
224
- rescue
218
+ rescue => e
219
+ warn("Error retrieving instance profile credentials: #{e}")
225
220
  '{}'
226
221
  end
227
222
  end
228
223
  end
229
224
 
225
+ 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
235
+ rescue *NETWORK_ERRORS
236
+ # token attempt failed, reset token
237
+ # fallback to non-token mode
238
+ @token = nil
239
+ @imds_v1_fallback = true
240
+ end
241
+
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)
245
+ profile_name = metadata.lines.first.strip
246
+ http_get(conn, METADATA_PATH_BASE + profile_name, token)
247
+ rescue TokenExpiredError
248
+ # Token has expired, reset it
249
+ # The next retry should fetch it
250
+ @token = nil
251
+ @imds_v1_fallback = false
252
+ raise Non200Response
253
+ end
254
+
230
255
  def token_set?
231
256
  @token && !@token.expired?
232
257
  end
@@ -237,7 +262,7 @@ module Aws
237
262
 
238
263
  def open_connection
239
264
  uri = URI.parse(@endpoint)
240
- http = Net::HTTP.new(uri.hostname || @endpoint, @port || uri.port)
265
+ http = Net::HTTP.new(uri.hostname || @endpoint, uri.port || @port)
241
266
  http.open_timeout = @http_open_timeout
242
267
  http.read_timeout = @http_read_timeout
243
268
  http.set_debug_output(@http_debug_output) if @http_debug_output
@@ -276,8 +301,6 @@ module Aws
276
301
  ]
277
302
  when 400
278
303
  raise TokenRetrivalError
279
- when 401
280
- raise TokenExpiredError
281
304
  else
282
305
  raise Non200Response
283
306
  end
@@ -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,8 @@
2
2
 
3
3
  module Aws
4
4
  module Json
5
- class ErrorHandler < Xml::ErrorHandler
5
+ class ErrorHandler < Aws::ErrorHandler
6
6
 
7
- # @param [Seahorse::Client::RequestContext] context
8
- # @return [Seahorse::Client::Response]
9
7
  def call(context)
10
8
  @handler.call(context).on(300..599) do |response|
11
9
  response.error = error(context)
@@ -19,7 +17,7 @@ module Aws
19
17
  json = Json.load(body)
20
18
  code = error_code(json, context)
21
19
  message = error_message(code, json)
22
- data = parse_error_data(context, code)
20
+ data = parse_error_data(context, body, code)
23
21
  [code, message, data]
24
22
  rescue Json::ParseError
25
23
  [http_status_error_code(context), '', EmptyStructure.new]
@@ -48,7 +46,7 @@ module Aws
48
46
  end
49
47
 
50
48
  def remove_prefix(error_code, context)
51
- if prefix = context.config.api.metadata['errorPrefix']
49
+ if (prefix = context.config.api.metadata['errorPrefix'])
52
50
  error_code.sub(/^#{prefix}/, '')
53
51
  else
54
52
  error_code
@@ -63,22 +61,29 @@ module Aws
63
61
  end
64
62
  end
65
63
 
66
- def parse_error_data(context, code)
64
+ def parse_error_data(context, body, code)
67
65
  data = EmptyStructure.new
68
- if error_rules = context.operation.errors
66
+ if (error_rules = context.operation.errors)
69
67
  error_rules.each do |rule|
70
68
  # match modeled shape name with the type(code) only
71
69
  # some type(code) might contains invalid characters
72
70
  # such as ':' (efs) etc
73
71
  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
72
+ next unless match && rule.shape.members.any?
73
+
74
+ data = Parser.new(rule).parse(body)
75
+ # errors support HTTP bindings
76
+ apply_error_headers(rule, context, data)
77
77
  end
78
78
  end
79
79
  data
80
80
  end
81
81
 
82
+ def apply_error_headers(rule, context, data)
83
+ headers = Aws::Rest::Response::Headers.new(rule)
84
+ headers.apply(context.http_response, data)
85
+ end
86
+
82
87
  end
83
88
  end
84
89
  end