aws-sdk-core 3.197.0 → 3.220.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 (139) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +297 -0
  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 +12 -5
  8. data/lib/aws-sdk-core/assume_role_web_identity_credentials.rb +13 -7
  9. data/lib/aws-sdk-core/binary/decode_handler.rb +3 -4
  10. data/lib/aws-sdk-core/binary/encode_handler.rb +1 -1
  11. data/lib/aws-sdk-core/binary/event_stream_decoder.rb +1 -0
  12. data/lib/aws-sdk-core/binary/event_stream_encoder.rb +4 -3
  13. data/lib/aws-sdk-core/cbor/decoder.rb +308 -0
  14. data/lib/aws-sdk-core/cbor/encoder.rb +243 -0
  15. data/lib/aws-sdk-core/cbor.rb +53 -0
  16. data/lib/aws-sdk-core/client_side_monitoring.rb +9 -0
  17. data/lib/aws-sdk-core/client_stubs.rb +8 -7
  18. data/lib/aws-sdk-core/credential_provider_chain.rb +13 -6
  19. data/lib/aws-sdk-core/credentials.rb +13 -6
  20. data/lib/aws-sdk-core/endpoints/endpoint.rb +3 -1
  21. data/lib/aws-sdk-core/endpoints/matchers.rb +6 -9
  22. data/lib/aws-sdk-core/endpoints.rb +74 -18
  23. data/lib/aws-sdk-core/error_handler.rb +41 -0
  24. data/lib/aws-sdk-core/errors.rb +9 -0
  25. data/lib/aws-sdk-core/json/error_handler.rb +8 -9
  26. data/lib/aws-sdk-core/json/handler.rb +6 -6
  27. data/lib/aws-sdk-core/json/json_engine.rb +3 -1
  28. data/lib/aws-sdk-core/json/oj_engine.rb +7 -1
  29. data/lib/aws-sdk-core/json/parser.rb +2 -0
  30. data/lib/aws-sdk-core/json.rb +43 -14
  31. data/lib/aws-sdk-core/log/param_filter.rb +2 -2
  32. data/lib/aws-sdk-core/log/param_formatter.rb +7 -3
  33. data/lib/aws-sdk-core/log.rb +10 -0
  34. data/lib/aws-sdk-core/param_validator.rb +1 -1
  35. data/lib/aws-sdk-core/plugins/bearer_authorization.rb +2 -0
  36. data/lib/aws-sdk-core/plugins/checksum_algorithm.rb +332 -169
  37. data/lib/aws-sdk-core/plugins/credentials_configuration.rb +7 -3
  38. data/lib/aws-sdk-core/plugins/global_configuration.rb +8 -9
  39. data/lib/aws-sdk-core/plugins/http_checksum.rb +2 -8
  40. data/lib/aws-sdk-core/plugins/protocols/api_gateway.rb +3 -1
  41. data/lib/aws-sdk-core/plugins/protocols/ec2.rb +2 -24
  42. data/lib/aws-sdk-core/plugins/protocols/json_rpc.rb +6 -8
  43. data/lib/aws-sdk-core/plugins/protocols/query.rb +4 -2
  44. data/lib/aws-sdk-core/plugins/protocols/rest_json.rb +4 -3
  45. data/lib/aws-sdk-core/plugins/protocols/rest_xml.rb +5 -1
  46. data/lib/aws-sdk-core/plugins/protocols/rpc_v2.rb +17 -0
  47. data/lib/aws-sdk-core/plugins/regional_endpoint.rb +74 -25
  48. data/lib/aws-sdk-core/plugins/retry_errors.rb +0 -1
  49. data/lib/aws-sdk-core/plugins/sign.rb +13 -11
  50. data/lib/aws-sdk-core/plugins/signature_v2.rb +2 -1
  51. data/lib/aws-sdk-core/plugins/signature_v4.rb +2 -1
  52. data/lib/aws-sdk-core/plugins/stub_responses.rb +29 -2
  53. data/lib/aws-sdk-core/plugins/telemetry.rb +75 -0
  54. data/lib/aws-sdk-core/plugins/transfer_encoding.rb +16 -9
  55. data/lib/aws-sdk-core/plugins/user_agent.rb +26 -8
  56. data/lib/aws-sdk-core/plugins.rb +39 -0
  57. data/lib/aws-sdk-core/process_credentials.rb +47 -28
  58. data/lib/aws-sdk-core/query/ec2_handler.rb +27 -0
  59. data/lib/aws-sdk-core/query/handler.rb +4 -4
  60. data/lib/aws-sdk-core/query.rb +2 -1
  61. data/lib/aws-sdk-core/resources.rb +8 -0
  62. data/lib/aws-sdk-core/rest/{request/content_type.rb → content_type_handler.rb} +1 -1
  63. data/lib/aws-sdk-core/rest/handler.rb +3 -4
  64. data/lib/aws-sdk-core/rest/request/endpoint.rb +3 -1
  65. data/lib/aws-sdk-core/rest/request/headers.rb +2 -2
  66. data/lib/aws-sdk-core/rest.rb +1 -1
  67. data/lib/aws-sdk-core/rpc_v2/builder.rb +62 -0
  68. data/lib/aws-sdk-core/rpc_v2/cbor_engine.rb +18 -0
  69. data/lib/aws-sdk-core/rpc_v2/content_type_handler.rb +47 -0
  70. data/lib/aws-sdk-core/rpc_v2/error_handler.rb +85 -0
  71. data/lib/aws-sdk-core/rpc_v2/handler.rb +79 -0
  72. data/lib/aws-sdk-core/rpc_v2/parser.rb +90 -0
  73. data/lib/aws-sdk-core/rpc_v2.rb +69 -0
  74. data/lib/aws-sdk-core/shared_config.rb +7 -2
  75. data/lib/aws-sdk-core/shared_credentials.rb +0 -7
  76. data/lib/aws-sdk-core/sso_credentials.rb +2 -1
  77. data/lib/aws-sdk-core/stubbing/protocols/ec2.rb +12 -11
  78. data/lib/aws-sdk-core/stubbing/protocols/json.rb +11 -10
  79. data/lib/aws-sdk-core/stubbing/protocols/query.rb +7 -6
  80. data/lib/aws-sdk-core/stubbing/protocols/rest.rb +2 -1
  81. data/lib/aws-sdk-core/stubbing/protocols/rest_json.rb +9 -8
  82. data/lib/aws-sdk-core/stubbing/protocols/rest_xml.rb +6 -5
  83. data/lib/aws-sdk-core/stubbing/protocols/rpc_v2.rb +39 -0
  84. data/lib/aws-sdk-core/stubbing.rb +22 -0
  85. data/lib/aws-sdk-core/telemetry/base.rb +177 -0
  86. data/lib/aws-sdk-core/telemetry/no_op.rb +70 -0
  87. data/lib/aws-sdk-core/telemetry/otel.rb +235 -0
  88. data/lib/aws-sdk-core/telemetry/span_kind.rb +22 -0
  89. data/lib/aws-sdk-core/telemetry/span_status.rb +59 -0
  90. data/lib/aws-sdk-core/telemetry.rb +78 -0
  91. data/lib/aws-sdk-core/waiters/poller.rb +9 -4
  92. data/lib/aws-sdk-core/xml/error_handler.rb +11 -37
  93. data/lib/aws-sdk-core/xml/parser.rb +2 -6
  94. data/lib/aws-sdk-core.rb +82 -108
  95. data/lib/aws-sdk-sso/client.rb +99 -37
  96. data/lib/aws-sdk-sso/client_api.rb +7 -0
  97. data/lib/aws-sdk-sso/endpoint_parameters.rb +9 -6
  98. data/lib/aws-sdk-sso/endpoint_provider.rb +14 -18
  99. data/lib/aws-sdk-sso/endpoints.rb +2 -54
  100. data/lib/aws-sdk-sso/plugins/endpoints.rb +19 -20
  101. data/lib/aws-sdk-sso/types.rb +1 -0
  102. data/lib/aws-sdk-sso.rb +15 -11
  103. data/lib/aws-sdk-ssooidc/client.rb +123 -55
  104. data/lib/aws-sdk-ssooidc/client_api.rb +5 -0
  105. data/lib/aws-sdk-ssooidc/endpoint_parameters.rb +9 -6
  106. data/lib/aws-sdk-ssooidc/endpoint_provider.rb +14 -18
  107. data/lib/aws-sdk-ssooidc/endpoints.rb +2 -54
  108. data/lib/aws-sdk-ssooidc/plugins/endpoints.rb +19 -20
  109. data/lib/aws-sdk-ssooidc/types.rb +21 -15
  110. data/lib/aws-sdk-ssooidc.rb +15 -11
  111. data/lib/aws-sdk-sts/client.rb +307 -89
  112. data/lib/aws-sdk-sts/client_api.rb +28 -2
  113. data/lib/aws-sdk-sts/customizations.rb +5 -1
  114. data/lib/aws-sdk-sts/endpoint_parameters.rb +10 -9
  115. data/lib/aws-sdk-sts/endpoint_provider.rb +33 -38
  116. data/lib/aws-sdk-sts/endpoints.rb +2 -118
  117. data/lib/aws-sdk-sts/errors.rb +16 -0
  118. data/lib/aws-sdk-sts/plugins/endpoints.rb +19 -28
  119. data/lib/aws-sdk-sts/types.rb +171 -28
  120. data/lib/aws-sdk-sts.rb +15 -11
  121. data/lib/seahorse/client/base.rb +17 -7
  122. data/lib/seahorse/client/h2/handler.rb +13 -3
  123. data/lib/seahorse/client/handler.rb +1 -1
  124. data/lib/seahorse/client/net_http/connection_pool.rb +10 -2
  125. data/lib/seahorse/client/net_http/handler.rb +21 -9
  126. data/lib/seahorse/client/plugins/endpoint.rb +0 -1
  127. data/lib/seahorse/client/plugins/net_http.rb +9 -0
  128. data/lib/seahorse/client/request_context.rb +8 -1
  129. data/lib/seahorse/client/response.rb +2 -0
  130. data/sig/aws-sdk-core/telemetry/base.rbs +46 -0
  131. data/sig/aws-sdk-core/telemetry/otel.rbs +22 -0
  132. data/sig/aws-sdk-core/telemetry/span_kind.rbs +15 -0
  133. data/sig/aws-sdk-core/telemetry/span_status.rbs +24 -0
  134. metadata +62 -18
  135. /data/lib/aws-sdk-core/xml/parser/{engines/libxml.rb → libxml_engine.rb} +0 -0
  136. /data/lib/aws-sdk-core/xml/parser/{engines/nokogiri.rb → nokogiri_engine.rb} +0 -0
  137. /data/lib/aws-sdk-core/xml/parser/{engines/oga.rb → oga_engine.rb} +0 -0
  138. /data/lib/aws-sdk-core/xml/parser/{engines/ox.rb → ox_engine.rb} +0 -0
  139. /data/lib/aws-sdk-core/xml/parser/{engines/rexml.rb → rexml_engine.rb} +0 -0
@@ -13,34 +13,131 @@ module Aws
13
13
  begin
14
14
  require 'aws-crt'
15
15
  supported << 'CRC32C'
16
+ supported << 'CRC64NVME' if Aws::Crt::GEM_VERSION >= '0.3.0'
16
17
  rescue LoadError
18
+ # Ignored
17
19
  end
18
20
  supported
19
21
  end.freeze
20
22
 
21
- # priority order of checksum algorithms to validate responses against
22
- # Remove any algorithms not supported by client (ie, depending on CRT availability)
23
- CHECKSUM_ALGORITHM_PRIORITIES = %w[CRC32C SHA1 CRC32 SHA256] & CLIENT_ALGORITHMS
23
+ CRT_ALGORITHMS = %w[CRC32C CRC64NVME].freeze
24
+
25
+ # Priority order of checksum algorithms to validate responses against.
26
+ # Remove any algorithms not supported by client (ie, depending on CRT availability).
27
+ # This list was chosen based on average performance.
28
+ CHECKSUM_ALGORITHM_PRIORITIES = %w[CRC32 CRC32C CRC64NVME SHA1 SHA256] & CLIENT_ALGORITHMS
24
29
 
25
30
  # byte size of checksums, used in computing the trailer length
26
31
  CHECKSUM_SIZE = {
27
- 'CRC32' => 16,
28
- 'CRC32C' => 16,
29
- 'SHA1' => 36,
30
- 'SHA256' => 52
31
- }
32
+ 'CRC32' => 9,
33
+ 'CRC32C' => 9,
34
+ 'CRC64NVME' => 13,
35
+ # SHA functions need 1 byte padding because of how they are encoded
36
+ 'SHA1' => 28 + 1,
37
+ 'SHA256' => 44 + 1
38
+ }.freeze
39
+
40
+ DEFAULT_CHECKSUM = 'CRC32'
41
+
42
+ option(:request_checksum_calculation,
43
+ doc_default: 'when_supported',
44
+ doc_type: 'String',
45
+ docstring: <<~DOCS) do |cfg|
46
+ Determines when a checksum will be calculated for request payloads. Values are:
47
+
48
+ * `when_supported` - (default) When set, a checksum will be
49
+ calculated for all request payloads of operations modeled with the
50
+ `httpChecksum` trait where `requestChecksumRequired` is `true` and/or a
51
+ `requestAlgorithmMember` is modeled.
52
+ * `when_required` - When set, a checksum will only be calculated for
53
+ request payloads of operations modeled with the `httpChecksum` trait where
54
+ `requestChecksumRequired` is `true` or where a `requestAlgorithmMember`
55
+ is modeled and supplied.
56
+ DOCS
57
+ resolve_request_checksum_calculation(cfg)
58
+ end
32
59
 
33
- # Interface for computing digests on request/response bodies
34
- # which may be files, strings or IO like objects
35
- # Applies only to digest functions that produce 32 bit integer checksums
36
- # (eg CRC32)
37
- class Digest32
60
+ option(:response_checksum_validation,
61
+ doc_default: 'when_supported',
62
+ doc_type: 'String',
63
+ docstring: <<~DOCS) do |cfg|
64
+ Determines when checksum validation will be performed on response payloads. Values are:
65
+
66
+ * `when_supported` - (default) When set, checksum validation is performed on all
67
+ response payloads of operations modeled with the `httpChecksum` trait where
68
+ `responseAlgorithms` is modeled, except when no modeled checksum algorithms
69
+ are supported.
70
+ * `when_required` - When set, checksum validation is not performed on
71
+ response payloads of operations unless the checksum algorithm is supported and
72
+ the `requestValidationModeMember` member is set to `ENABLED`.
73
+ DOCS
74
+ resolve_response_checksum_validation(cfg)
75
+ end
76
+
77
+ class << self
78
+ def digest_for_algorithm(algorithm)
79
+ case algorithm
80
+ when 'CRC32'
81
+ Digest.new(Zlib.method(:crc32), 'N')
82
+ when 'CRC32C'
83
+ Digest.new(Aws::Crt::Checksums.method(:crc32c), 'N')
84
+ when 'CRC64NVME'
85
+ Digest.new(Aws::Crt::Checksums.method(:crc64nvme), 'Q>')
86
+ when 'SHA1'
87
+ ::Digest::SHA1.new
88
+ when 'SHA256'
89
+ ::Digest::SHA256.new
90
+ else
91
+ raise ArgumentError,
92
+ "#{algorithm} is not a supported checksum algorithm."
93
+ end
94
+ end
38
95
 
39
- attr_reader :value
96
+ # The trailer size (in bytes) is the overhead (0, \r, \n) + the trailer
97
+ # name + the bytesize of the base64 encoded checksum.
98
+ def trailer_length(algorithm, location_name)
99
+ 7 + location_name.size + CHECKSUM_SIZE[algorithm]
100
+ end
101
+
102
+ private
103
+
104
+ def resolve_request_checksum_calculation(cfg)
105
+ mode = ENV['AWS_REQUEST_CHECKSUM_CALCULATION'] ||
106
+ Aws.shared_config.request_checksum_calculation(profile: cfg.profile) ||
107
+ 'when_supported'
108
+ mode = mode.downcase
109
+ unless %w[when_supported when_required].include?(mode)
110
+ raise ArgumentError,
111
+ 'expected :request_checksum_calculation or' \
112
+ " ENV['AWS_REQUEST_CHECKSUM_CALCULATION'] to be " \
113
+ '`when_supported` or `when_required`.'
114
+ end
115
+ mode
116
+ end
117
+
118
+ def resolve_response_checksum_validation(cfg)
119
+ mode = ENV['AWS_RESPONSE_CHECKSUM_VALIDATION'] ||
120
+ Aws.shared_config.response_checksum_validation(profile: cfg.profile) ||
121
+ 'when_supported'
122
+ mode = mode.downcase
123
+ unless %w[when_supported when_required].include?(mode)
124
+ raise ArgumentError,
125
+ 'expected :response_checksum_validation or' \
126
+ " ENV['AWS_RESPONSE_CHECKSUM_VALIDATION'] to be " \
127
+ '`when_supported` or `when_required`.'
128
+ end
129
+ mode
130
+ end
131
+ end
40
132
 
41
- # @param [Object] digest_fn
42
- def initialize(digest_fn)
133
+ # Interface for computing digests on request/response bodies
134
+ # which may be files, strings or IO like objects.
135
+ # Applies only to digest functions that produce 32 or 64 bit
136
+ # integer checksums (eg CRC32 or CRC64).
137
+ class Digest
138
+ def initialize(digest_fn, directive)
43
139
  @digest_fn = digest_fn
140
+ @directive = directive
44
141
  @value = 0
45
142
  end
46
143
 
@@ -49,125 +146,223 @@ module Aws
49
146
  end
50
147
 
51
148
  def base64digest
52
- Base64.encode64([@value].pack('N')).chomp
149
+ Base64.encode64([@value].pack(@directive)).chomp
53
150
  end
54
151
  end
55
152
 
56
153
  def add_handlers(handlers, _config)
57
154
  handlers.add(OptionHandler, step: :initialize)
58
- # priority set low to ensure checksum is computed AFTER the request is
59
- # built but before it is signed
155
+ # Priority is set low to ensure the checksum is computed AFTER the
156
+ # request is built but before it is signed.
60
157
  handlers.add(ChecksumHandler, priority: 15, step: :build)
61
158
  end
62
159
 
63
- private
64
-
65
- def self.request_algorithm_selection(context)
66
- return unless context.operation.http_checksum
67
-
68
- input_member = context.operation.http_checksum['requestAlgorithmMember']
69
- context.params[input_member.to_sym]&.upcase if input_member
70
- end
71
-
72
- def self.request_validation_mode(context)
73
- return unless context.operation.http_checksum
74
-
75
- input_member = context.operation.http_checksum['requestValidationModeMember']
76
- context.params[input_member.to_sym] if input_member
77
- end
78
-
79
- def self.operation_response_algorithms(context)
80
- return unless context.operation.http_checksum
81
-
82
- context.operation.http_checksum['responseAlgorithms']
83
- end
84
-
85
-
86
- # @api private
87
160
  class OptionHandler < Seahorse::Client::Handler
88
161
  def call(context)
89
162
  context[:http_checksum] ||= {}
90
163
 
91
- # validate request configuration
92
- if (request_input = ChecksumAlgorithm.request_algorithm_selection(context))
93
- unless CLIENT_ALGORITHMS.include? request_input
94
- if (request_input == 'CRC32C')
95
- raise ArgumentError, "CRC32C requires crt support - install the aws-crt gem for support."
96
- else
97
- raise ArgumentError, "#{request_input} is not a supported checksum algorithm."
98
- end
99
- end
100
- end
101
-
102
- # validate response configuration
103
- if (ChecksumAlgorithm.request_validation_mode(context))
104
- # Compute an ordered list as the union between priority supported and the
105
- # operation's modeled response algorithms.
106
- validation_list = CHECKSUM_ALGORITHM_PRIORITIES &
107
- ChecksumAlgorithm.operation_response_algorithms(context)
108
- context[:http_checksum][:validation_list] = validation_list
164
+ # Set validation mode to enabled when supported.
165
+ if context.config.response_checksum_validation == 'when_supported'
166
+ enable_request_validation_mode(context)
109
167
  end
110
168
 
111
169
  @handler.call(context)
112
170
  end
171
+
172
+ private
173
+
174
+ def enable_request_validation_mode(context)
175
+ return unless context.operation.http_checksum
176
+
177
+ input_member = context.operation.http_checksum['requestValidationModeMember']
178
+ context.params[input_member.to_sym] ||= 'ENABLED' if input_member
179
+ end
113
180
  end
114
181
 
115
- # @api private
116
182
  class ChecksumHandler < Seahorse::Client::Handler
117
-
118
183
  def call(context)
184
+ algorithm = nil
119
185
  if should_calculate_request_checksum?(context)
120
- request_algorithm_input = ChecksumAlgorithm.request_algorithm_selection(context) ||
121
- context[:default_request_checksum_algorithm]
122
- context[:checksum_algorithms] = request_algorithm_input
123
-
124
- request_checksum_property = {
125
- 'algorithm' => request_algorithm_input,
126
- 'in' => checksum_request_in(context),
127
- 'name' => "x-amz-checksum-#{request_algorithm_input.downcase}"
186
+ algorithm = choose_request_algorithm!(context)
187
+ request_algorithm = {
188
+ algorithm: algorithm,
189
+ in: checksum_request_in(context),
190
+ name: "x-amz-checksum-#{algorithm.downcase}",
191
+ request_algorithm_header: request_algorithm_header(context)
128
192
  }
129
193
 
130
- calculate_request_checksum(context, request_checksum_property)
194
+ context[:http_checksum][:request_algorithm] = request_algorithm
195
+ calculate_request_checksum(context, request_algorithm)
131
196
  end
132
197
 
133
198
  if should_verify_response_checksum?(context)
134
199
  add_verify_response_checksum_handlers(context)
135
200
  end
136
201
 
137
- @handler.call(context)
202
+ with_metrics(context.config, algorithm) { @handler.call(context) }
138
203
  end
139
204
 
140
205
  private
141
206
 
142
- def should_calculate_request_checksum?(context)
207
+ def with_metrics(config, algorithm, &block)
208
+ metrics = []
209
+ add_request_config_metric(config, metrics)
210
+ add_response_config_metric(config, metrics)
211
+ add_request_checksum_metrics(algorithm, metrics)
212
+ Aws::Plugins::UserAgent.metric(*metrics, &block)
213
+ end
214
+
215
+ def add_request_config_metric(config, metrics)
216
+ case config.request_checksum_calculation
217
+ when 'when_supported'
218
+ metrics << 'FLEXIBLE_CHECKSUMS_REQ_WHEN_SUPPORTED'
219
+ when 'when_required'
220
+ metrics << 'FLEXIBLE_CHECKSUMS_REQ_WHEN_REQUIRED'
221
+ end
222
+ end
223
+
224
+ def add_response_config_metric(config, metrics)
225
+ case config.response_checksum_validation
226
+ when 'when_supported'
227
+ metrics << 'FLEXIBLE_CHECKSUMS_RES_WHEN_SUPPORTED'
228
+ when 'when_required'
229
+ metrics << 'FLEXIBLE_CHECKSUMS_RES_WHEN_REQUIRED'
230
+ end
231
+ end
232
+
233
+ def add_request_checksum_metrics(algorithm, metrics)
234
+ case algorithm
235
+ when 'CRC32'
236
+ metrics << 'FLEXIBLE_CHECKSUMS_REQ_CRC32'
237
+ when 'CRC32C'
238
+ metrics << 'FLEXIBLE_CHECKSUMS_REQ_CRC32C'
239
+ when 'CRC64NVME'
240
+ metrics << 'FLEXIBLE_CHECKSUMS_REQ_CRC64'
241
+ when 'SHA1'
242
+ metrics << 'FLEXIBLE_CHECKSUMS_REQ_SHA1'
243
+ when 'SHA256'
244
+ metrics << 'FLEXIBLE_CHECKSUMS_REQ_SHA256'
245
+ end
246
+ end
247
+
248
+ def request_algorithm_selection(context)
249
+ return unless context.operation.http_checksum
250
+
251
+ input_member = context.operation.http_checksum['requestAlgorithmMember']
252
+ context.params[input_member.to_sym] ||= DEFAULT_CHECKSUM if input_member
253
+ end
254
+
255
+ def request_algorithm_header(context)
256
+ input_member = context.operation.http_checksum['requestAlgorithmMember']
257
+ shape = context.operation.input.shape.member(input_member)
258
+ shape.location_name if shape && shape.location == 'header'
259
+ end
260
+
261
+ def request_validation_mode(context)
262
+ return unless context.operation.http_checksum
263
+
264
+ input_member = context.operation.http_checksum['requestValidationModeMember']
265
+ context.params[input_member.to_sym] if input_member
266
+ end
267
+
268
+ def operation_response_algorithms(context)
269
+ return unless context.operation.http_checksum
270
+
271
+ context.operation.http_checksum['responseAlgorithms']
272
+ end
273
+
274
+ def checksum_required?(context)
275
+ (http_checksum = context.operation.http_checksum) &&
276
+ (checksum_required = http_checksum['requestChecksumRequired']) &&
277
+ (checksum_required && context.config.request_checksum_calculation == 'when_required')
278
+ end
279
+
280
+ def checksum_optional?(context)
143
281
  context.operation.http_checksum &&
144
- (ChecksumAlgorithm.request_algorithm_selection(context) ||
145
- context[:default_request_checksum_algorithm])
282
+ context.config.request_checksum_calculation != 'when_required'
146
283
  end
147
284
 
148
- def should_verify_response_checksum?(context)
149
- context[:http_checksum][:validation_list] && !context[:http_checksum][:validation_list].empty?
285
+ def checksum_provided_as_header?(headers)
286
+ headers.any? { |k, _| k.start_with?('x-amz-checksum-') }
287
+ end
288
+
289
+ def should_calculate_request_checksum?(context)
290
+ !checksum_provided_as_header?(context.http_request.headers) &&
291
+ request_algorithm_selection(context) &&
292
+ (checksum_required?(context) || checksum_optional?(context))
293
+ end
294
+
295
+ def choose_request_algorithm!(context)
296
+ algorithm = request_algorithm_selection(context).upcase
297
+ return algorithm if CLIENT_ALGORITHMS.include?(algorithm)
298
+
299
+ if CRT_ALGORITHMS.include?(algorithm)
300
+ raise ArgumentError,
301
+ 'CRC32C and CRC64NVME requires CRT support ' \
302
+ '- install the aws-crt gem'
303
+ end
304
+
305
+ raise ArgumentError,
306
+ "#{algorithm} is not a supported checksum algorithm."
307
+ end
308
+
309
+ def checksum_request_in(context)
310
+ if context.operation['unsignedPayload'] ||
311
+ context.operation['authtype'] == 'v4-unsigned-body'
312
+ 'trailer'
313
+ else
314
+ 'header'
315
+ end
150
316
  end
151
317
 
152
318
  def calculate_request_checksum(context, checksum_properties)
153
- case checksum_properties['in']
319
+ headers = context.http_request.headers
320
+ if (algorithm_header = checksum_properties[:request_algorithm_header])
321
+ headers[algorithm_header] = checksum_properties[:algorithm]
322
+ end
323
+ case checksum_properties[:in]
154
324
  when 'header'
155
- header_name = checksum_properties['name']
156
- body = context.http_request.body_contents
157
- if body
158
- context.http_request.headers[header_name] ||=
159
- ChecksumAlgorithm.calculate_checksum(checksum_properties['algorithm'], body)
160
- end
325
+ apply_request_checksum(context, headers, checksum_properties)
161
326
  when 'trailer'
162
- apply_request_trailer_checksum(context, checksum_properties)
327
+ apply_request_trailer_checksum(context, headers, checksum_properties)
328
+ else
329
+ # nothing
330
+ end
331
+ end
332
+
333
+ def apply_request_checksum(context, headers, checksum_properties)
334
+ header_name = checksum_properties[:name]
335
+ body = context.http_request.body_contents
336
+ headers[header_name] = calculate_checksum(
337
+ checksum_properties[:algorithm],
338
+ body
339
+ )
340
+ end
341
+
342
+ def calculate_checksum(algorithm, body)
343
+ digest = ChecksumAlgorithm.digest_for_algorithm(algorithm)
344
+ if body.respond_to?(:read)
345
+ update_in_chunks(digest, body)
346
+ else
347
+ digest.update(body)
348
+ end
349
+ digest.base64digest
350
+ end
351
+
352
+ def update_in_chunks(digest, io)
353
+ loop do
354
+ chunk = io.read(CHUNK_SIZE)
355
+ break unless chunk
356
+
357
+ digest.update(chunk)
163
358
  end
359
+ io.rewind
164
360
  end
165
361
 
166
- def apply_request_trailer_checksum(context, checksum_properties)
167
- location_name = checksum_properties['name']
362
+ def apply_request_trailer_checksum(context, headers, checksum_properties)
363
+ location_name = checksum_properties[:name]
168
364
 
169
365
  # set required headers
170
- headers = context.http_request.headers
171
366
  headers['Content-Encoding'] = 'aws-chunked'
172
367
  headers['X-Amz-Content-Sha256'] = 'STREAMING-UNSIGNED-PAYLOAD-TRAILER'
173
368
  headers['X-Amz-Trailer'] = location_name
@@ -176,120 +371,88 @@ module Aws
176
371
  # to set the Content-Length header (set by content_length plugin).
177
372
  # This means we cannot use Transfer-Encoding=chunked
178
373
 
179
- if !context.http_request.body.respond_to?(:size)
374
+ unless context.http_request.body.respond_to?(:size)
180
375
  raise Aws::Errors::ChecksumError, 'Could not determine length of the body'
181
376
  end
182
377
  headers['X-Amz-Decoded-Content-Length'] = context.http_request.body.size
183
378
 
184
379
  context.http_request.body = AwsChunkedTrailerDigestIO.new(
185
380
  context.http_request.body,
186
- checksum_properties['algorithm'],
381
+ checksum_properties[:algorithm],
187
382
  location_name
188
383
  )
189
384
  end
190
385
 
386
+ def should_verify_response_checksum?(context)
387
+ request_validation_mode(context) == 'ENABLED'
388
+ end
389
+
191
390
  # Add events to the http_response to verify the checksum as its read
192
391
  # This prevents the body from being read multiple times
193
392
  # verification is done only once a successful response has completed
194
393
  def add_verify_response_checksum_handlers(context)
195
- http_response = context.http_response
196
- checksum_context = { }
197
- http_response.on_headers do |_status, headers|
198
- header_name, algorithm = response_header_to_verify(headers, context[:http_checksum][:validation_list])
199
- if header_name
200
- expected = headers[header_name]
201
-
202
- unless context[:http_checksum][:skip_on_suffix] && /-[\d]+$/.match(expected)
203
- checksum_context[:algorithm] = algorithm
204
- checksum_context[:header_name] = header_name
205
- checksum_context[:digest] = ChecksumAlgorithm.digest_for_algorithm(algorithm)
206
- checksum_context[:expected] = expected
207
- end
208
- end
209
- end
394
+ checksum_context = {}
395
+ add_verify_response_headers_handler(context, checksum_context)
396
+ add_verify_response_data_handler(context, checksum_context)
397
+ add_verify_response_success_handler(context, checksum_context)
398
+ end
210
399
 
211
- http_response.on_data do |chunk|
212
- checksum_context[:digest].update(chunk) if checksum_context[:digest]
400
+ def add_verify_response_headers_handler(context, checksum_context)
401
+ validation_list = CHECKSUM_ALGORITHM_PRIORITIES &
402
+ operation_response_algorithms(context)
403
+ context[:http_checksum][:validation_list] = validation_list
404
+
405
+ context.http_response.on_headers do |_status, headers|
406
+ header_name, algorithm = response_header_to_verify(
407
+ headers,
408
+ validation_list
409
+ )
410
+ next unless header_name
411
+
412
+ expected = headers[header_name]
413
+ next if context[:http_checksum][:skip_on_suffix] && /-\d+$/.match(expected)
414
+
415
+ checksum_context[:algorithm] = algorithm
416
+ checksum_context[:header_name] = header_name
417
+ checksum_context[:digest] = ChecksumAlgorithm.digest_for_algorithm(algorithm)
418
+ checksum_context[:expected] = expected
213
419
  end
420
+ end
214
421
 
215
- http_response.on_success do
216
- if checksum_context[:digest] &&
217
- (computed = checksum_context[:digest].base64digest)
422
+ def add_verify_response_data_handler(context, checksum_context)
423
+ context.http_response.on_data do |chunk|
424
+ checksum_context[:digest]&.update(chunk)
425
+ end
426
+ end
218
427
 
219
- if computed != checksum_context[:expected]
220
- raise Aws::Errors::ChecksumError,
221
- "Checksum validation failed on #{checksum_context[:header_name]} "\
222
- "computed: #{computed}, expected: #{checksum_context[:expected]}"
223
- end
428
+ def add_verify_response_success_handler(context, checksum_context)
429
+ context.http_response.on_success do
430
+ next unless checksum_context[:digest]
224
431
 
432
+ computed = checksum_context[:digest].base64digest
433
+ if computed == checksum_context[:expected]
225
434
  context[:http_checksum][:validated] = checksum_context[:algorithm]
435
+ else
436
+ raise Aws::Errors::ChecksumError,
437
+ "Checksum validation failed on #{checksum_context[:header_name]} "\
438
+ "computed: #{computed}, expected: #{checksum_context[:expected]}"
226
439
  end
227
440
  end
228
441
  end
229
442
 
230
- # returns nil if no headers to verify
231
443
  def response_header_to_verify(headers, validation_list)
232
444
  validation_list.each do |algorithm|
233
- header_name = "x-amz-checksum-#{algorithm}"
445
+ header_name = "x-amz-checksum-#{algorithm.downcase}"
234
446
  return [header_name, algorithm] if headers[header_name]
235
447
  end
236
448
  nil
237
449
  end
238
-
239
- # determine where (header vs trailer) a request checksum should be added
240
- def checksum_request_in(context)
241
- if context.operation['authtype'].eql?('v4-unsigned-body')
242
- 'trailer'
243
- else
244
- 'header'
245
- end
246
- end
247
-
248
- end
249
-
250
- def self.calculate_checksum(algorithm, body)
251
- digest = ChecksumAlgorithm.digest_for_algorithm(algorithm)
252
- if body.respond_to?(:read)
253
- ChecksumAlgorithm.update_in_chunks(digest, body)
254
- else
255
- digest.update(body)
256
- end
257
- digest.base64digest
258
- end
259
-
260
- def self.digest_for_algorithm(algorithm)
261
- case algorithm
262
- when 'CRC32'
263
- Digest32.new(Zlib.method(:crc32))
264
- when 'CRC32C'
265
- # this will only be used if input algorithm is CRC32C AND client supports it (crt available)
266
- Digest32.new(Aws::Crt::Checksums.method(:crc32c))
267
- when 'SHA1'
268
- Digest::SHA1.new
269
- when 'SHA256'
270
- Digest::SHA256.new
271
- end
272
- end
273
-
274
- # The trailer size (in bytes) is the overhead + the trailer name +
275
- # the length of the base64 encoded checksum
276
- def self.trailer_length(algorithm, location_name)
277
- CHECKSUM_SIZE[algorithm] + location_name.size
278
- end
279
-
280
- def self.update_in_chunks(digest, io)
281
- loop do
282
- chunk = io.read(CHUNK_SIZE)
283
- break unless chunk
284
- digest.update(chunk)
285
- end
286
- io.rewind
287
450
  end
288
451
 
289
452
  # Wrapper for request body that implements application-layer
290
453
  # chunking with Digest computed on chunks + added as a trailer
291
454
  class AwsChunkedTrailerDigestIO
292
- CHUNK_SIZE = 16384
455
+ CHUNK_SIZE = 16_384
293
456
 
294
457
  def initialize(io, algorithm, location_name)
295
458
  @io = io
@@ -330,7 +493,7 @@ module Aws
330
493
  else
331
494
  trailers = {}
332
495
  trailers[@location_name] = @digest.base64digest
333
- trailers = trailers.map { |k,v| "#{k}:#{v}"}.join("\r\n")
496
+ trailers = trailers.map { |k,v| "#{k}:#{v}" }.join("\r\n")
334
497
  @trailer_io = StringIO.new("0\r\n#{trailers}\r\n\r\n")
335
498
  chunk = @trailer_io.read(length, buf)
336
499
  end
@@ -12,6 +12,8 @@ module Aws
12
12
 
13
13
  option(:session_token, doc_type: String, docstring: '')
14
14
 
15
+ option(:account_id, doc_type: String, docstring: '')
16
+
15
17
  option(:profile,
16
18
  doc_default: 'default',
17
19
  doc_type: String,
@@ -58,13 +60,15 @@ When `:credentials` are not configured directly, the following
58
60
  locations will be searched for credentials:
59
61
 
60
62
  * `Aws.config[:credentials]`
61
- * The `:access_key_id`, `:secret_access_key`, and `:session_token` options.
62
- * ENV['AWS_ACCESS_KEY_ID'], ENV['AWS_SECRET_ACCESS_KEY']
63
+ * The `:access_key_id`, `:secret_access_key`, `:session_token`, and
64
+ `:account_id` options.
65
+ * ENV['AWS_ACCESS_KEY_ID'], ENV['AWS_SECRET_ACCESS_KEY'],
66
+ ENV['AWS_SESSION_TOKEN'], and ENV['AWS_ACCOUNT_ID']
63
67
  * `~/.aws/credentials`
64
68
  * `~/.aws/config`
65
69
  * EC2/ECS IMDS instance profile - When used by default, the timeouts
66
70
  are very aggressive. Construct and pass an instance of
67
- `Aws::InstanceProfileCredentails` or `Aws::ECSCredentials` to
71
+ `Aws::InstanceProfileCredentials` or `Aws::ECSCredentials` to
68
72
  enable retries and extended timeouts. Instance profile credential
69
73
  fetching can be disabled by setting ENV['AWS_EC2_METADATA_DISABLED']
70
74
  to true.