aws-sdk-core 3.178.0 → 3.233.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 (196) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +709 -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 +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 +33 -55
  19. data/lib/aws-sdk-core/credential_provider.rb +5 -1
  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 +79 -11
  24. data/lib/aws-sdk-core/endpoints/endpoint.rb +3 -1
  25. data/lib/aws-sdk-core/endpoints/matchers.rb +21 -19
  26. data/lib/aws-sdk-core/endpoints.rb +101 -21
  27. data/lib/aws-sdk-core/error_handler.rb +46 -0
  28. data/lib/aws-sdk-core/errors.rb +14 -5
  29. data/lib/aws-sdk-core/event_emitter.rb +1 -17
  30. data/lib/aws-sdk-core/ini_parser.rb +8 -1
  31. data/lib/aws-sdk-core/instance_profile_credentials.rb +168 -155
  32. data/lib/aws-sdk-core/json/builder.rb +8 -1
  33. data/lib/aws-sdk-core/json/error_handler.rb +29 -13
  34. data/lib/aws-sdk-core/json/handler.rb +13 -6
  35. data/lib/aws-sdk-core/json/json_engine.rb +3 -1
  36. data/lib/aws-sdk-core/json/oj_engine.rb +7 -1
  37. data/lib/aws-sdk-core/json/parser.rb +33 -3
  38. data/lib/aws-sdk-core/json.rb +43 -14
  39. data/lib/aws-sdk-core/log/param_filter.rb +2 -2
  40. data/lib/aws-sdk-core/log/param_formatter.rb +7 -3
  41. data/lib/aws-sdk-core/log.rb +10 -0
  42. data/lib/aws-sdk-core/lru_cache.rb +75 -0
  43. data/lib/aws-sdk-core/pageable_response.rb +1 -1
  44. data/lib/aws-sdk-core/param_validator.rb +9 -4
  45. data/lib/aws-sdk-core/plugins/bearer_authorization.rb +2 -0
  46. data/lib/aws-sdk-core/plugins/checksum_algorithm.rb +332 -167
  47. data/lib/aws-sdk-core/plugins/client_metrics_plugin.rb +1 -1
  48. data/lib/aws-sdk-core/plugins/client_metrics_send_plugin.rb +14 -2
  49. data/lib/aws-sdk-core/plugins/credentials_configuration.rb +78 -56
  50. data/lib/aws-sdk-core/plugins/endpoint_pattern.rb +40 -32
  51. data/lib/aws-sdk-core/plugins/global_configuration.rb +8 -9
  52. data/lib/aws-sdk-core/plugins/http_checksum.rb +3 -8
  53. data/lib/aws-sdk-core/plugins/invocation_id.rb +1 -11
  54. data/lib/aws-sdk-core/plugins/logging.rb +2 -0
  55. data/lib/aws-sdk-core/plugins/protocols/api_gateway.rb +3 -1
  56. data/lib/aws-sdk-core/plugins/protocols/ec2.rb +2 -24
  57. data/lib/aws-sdk-core/plugins/protocols/json_rpc.rb +6 -8
  58. data/lib/aws-sdk-core/plugins/protocols/query.rb +4 -2
  59. data/lib/aws-sdk-core/plugins/protocols/rest_json.rb +3 -15
  60. data/lib/aws-sdk-core/plugins/protocols/rest_xml.rb +3 -0
  61. data/lib/aws-sdk-core/plugins/protocols/rpc_v2.rb +17 -0
  62. data/lib/aws-sdk-core/plugins/regional_endpoint.rb +74 -25
  63. data/lib/aws-sdk-core/plugins/request_compression.rb +11 -2
  64. data/lib/aws-sdk-core/plugins/retry_errors.rb +12 -3
  65. data/lib/aws-sdk-core/plugins/sign.rb +55 -34
  66. data/lib/aws-sdk-core/plugins/signature_v2.rb +2 -1
  67. data/lib/aws-sdk-core/plugins/signature_v4.rb +2 -1
  68. data/lib/aws-sdk-core/plugins/stub_responses.rb +59 -9
  69. data/lib/aws-sdk-core/plugins/telemetry.rb +75 -0
  70. data/lib/aws-sdk-core/plugins/transfer_encoding.rb +16 -9
  71. data/lib/aws-sdk-core/plugins/user_agent.rb +101 -26
  72. data/lib/aws-sdk-core/plugins.rb +39 -0
  73. data/lib/aws-sdk-core/process_credentials.rb +48 -29
  74. data/lib/aws-sdk-core/query/ec2_handler.rb +27 -0
  75. data/lib/aws-sdk-core/query/ec2_param_builder.rb +5 -7
  76. data/lib/aws-sdk-core/query/handler.rb +4 -4
  77. data/lib/aws-sdk-core/query/param_builder.rb +2 -2
  78. data/lib/aws-sdk-core/query.rb +2 -1
  79. data/lib/aws-sdk-core/refreshing_credentials.rb +12 -6
  80. data/lib/aws-sdk-core/resources.rb +8 -0
  81. data/lib/aws-sdk-core/rest/content_type_handler.rb +60 -0
  82. data/lib/aws-sdk-core/rest/handler.rb +3 -4
  83. data/lib/aws-sdk-core/rest/request/body.rb +32 -5
  84. data/lib/aws-sdk-core/rest/request/endpoint.rb +24 -4
  85. data/lib/aws-sdk-core/rest/request/headers.rb +15 -7
  86. data/lib/aws-sdk-core/rest/request/querystring_builder.rb +62 -36
  87. data/lib/aws-sdk-core/rest/response/body.rb +15 -1
  88. data/lib/aws-sdk-core/rest/response/header_list_parser.rb +79 -0
  89. data/lib/aws-sdk-core/rest/response/headers.rb +8 -3
  90. data/lib/aws-sdk-core/rest.rb +1 -0
  91. data/lib/aws-sdk-core/rpc_v2/builder.rb +62 -0
  92. data/lib/aws-sdk-core/rpc_v2/cbor_engine.rb +18 -0
  93. data/lib/aws-sdk-core/rpc_v2/content_type_handler.rb +47 -0
  94. data/lib/aws-sdk-core/rpc_v2/error_handler.rb +95 -0
  95. data/lib/aws-sdk-core/rpc_v2/handler.rb +79 -0
  96. data/lib/aws-sdk-core/rpc_v2/parser.rb +98 -0
  97. data/lib/aws-sdk-core/rpc_v2.rb +69 -0
  98. data/lib/aws-sdk-core/shared_config.rb +113 -41
  99. data/lib/aws-sdk-core/shared_credentials.rb +1 -7
  100. data/lib/aws-sdk-core/sso_credentials.rb +4 -1
  101. data/lib/aws-sdk-core/static_token_provider.rb +1 -2
  102. data/lib/aws-sdk-core/stubbing/protocols/ec2.rb +12 -11
  103. data/lib/aws-sdk-core/stubbing/protocols/json.rb +11 -10
  104. data/lib/aws-sdk-core/stubbing/protocols/query.rb +7 -6
  105. data/lib/aws-sdk-core/stubbing/protocols/rest.rb +2 -1
  106. data/lib/aws-sdk-core/stubbing/protocols/rest_json.rb +9 -8
  107. data/lib/aws-sdk-core/stubbing/protocols/rest_xml.rb +6 -5
  108. data/lib/aws-sdk-core/stubbing/protocols/rpc_v2.rb +39 -0
  109. data/lib/aws-sdk-core/stubbing/stub_data.rb +11 -0
  110. data/lib/aws-sdk-core/stubbing.rb +22 -0
  111. data/lib/aws-sdk-core/telemetry/base.rb +177 -0
  112. data/lib/aws-sdk-core/telemetry/no_op.rb +70 -0
  113. data/lib/aws-sdk-core/telemetry/otel.rb +235 -0
  114. data/lib/aws-sdk-core/telemetry/span_kind.rb +22 -0
  115. data/lib/aws-sdk-core/telemetry/span_status.rb +59 -0
  116. data/lib/aws-sdk-core/telemetry.rb +78 -0
  117. data/lib/aws-sdk-core/token.rb +3 -3
  118. data/lib/aws-sdk-core/token_provider.rb +4 -0
  119. data/lib/aws-sdk-core/token_provider_chain.rb +2 -6
  120. data/lib/aws-sdk-core/util.rb +41 -1
  121. data/lib/aws-sdk-core/waiters/poller.rb +10 -5
  122. data/lib/aws-sdk-core/xml/builder.rb +17 -9
  123. data/lib/aws-sdk-core/xml/error_handler.rb +35 -43
  124. data/lib/aws-sdk-core/xml/parser/frame.rb +4 -20
  125. data/lib/aws-sdk-core/xml/parser/stack.rb +2 -0
  126. data/lib/aws-sdk-core/xml/parser.rb +2 -6
  127. data/lib/aws-sdk-core.rb +82 -107
  128. data/lib/aws-sdk-sso/client.rb +189 -96
  129. data/lib/aws-sdk-sso/client_api.rb +7 -0
  130. data/lib/aws-sdk-sso/endpoint_parameters.rb +9 -6
  131. data/lib/aws-sdk-sso/endpoint_provider.rb +30 -28
  132. data/lib/aws-sdk-sso/endpoints.rb +2 -54
  133. data/lib/aws-sdk-sso/plugins/endpoints.rb +23 -22
  134. data/lib/aws-sdk-sso/types.rb +1 -0
  135. data/lib/aws-sdk-sso.rb +15 -11
  136. data/lib/aws-sdk-ssooidc/client.rb +609 -129
  137. data/lib/aws-sdk-ssooidc/client_api.rb +94 -1
  138. data/lib/aws-sdk-ssooidc/endpoint_parameters.rb +9 -6
  139. data/lib/aws-sdk-ssooidc/endpoint_provider.rb +30 -28
  140. data/lib/aws-sdk-ssooidc/endpoints.rb +2 -40
  141. data/lib/aws-sdk-ssooidc/errors.rb +62 -0
  142. data/lib/aws-sdk-ssooidc/plugins/endpoints.rb +23 -20
  143. data/lib/aws-sdk-ssooidc/types.rb +419 -53
  144. data/lib/aws-sdk-ssooidc.rb +15 -11
  145. data/lib/aws-sdk-sts/client.rb +414 -147
  146. data/lib/aws-sdk-sts/client_api.rb +48 -9
  147. data/lib/aws-sdk-sts/customizations.rb +5 -2
  148. data/lib/aws-sdk-sts/endpoint_parameters.rb +10 -9
  149. data/lib/aws-sdk-sts/endpoint_provider.rb +52 -57
  150. data/lib/aws-sdk-sts/endpoints.rb +2 -118
  151. data/lib/aws-sdk-sts/errors.rb +15 -0
  152. data/lib/aws-sdk-sts/plugins/endpoints.rb +23 -30
  153. data/lib/aws-sdk-sts/presigner.rb +3 -7
  154. data/lib/aws-sdk-sts/types.rb +209 -27
  155. data/lib/aws-sdk-sts.rb +15 -11
  156. data/lib/seahorse/client/async_base.rb +4 -5
  157. data/lib/seahorse/client/async_response.rb +19 -0
  158. data/lib/seahorse/client/base.rb +18 -21
  159. data/lib/seahorse/client/h2/connection.rb +18 -28
  160. data/lib/seahorse/client/h2/handler.rb +14 -3
  161. data/lib/seahorse/client/handler.rb +1 -1
  162. data/lib/seahorse/client/http/response.rb +1 -1
  163. data/lib/seahorse/client/net_http/connection_pool.rb +15 -12
  164. data/lib/seahorse/client/net_http/handler.rb +21 -9
  165. data/lib/seahorse/client/net_http/patches.rb +1 -4
  166. data/lib/seahorse/client/networking_error.rb +1 -1
  167. data/lib/seahorse/client/plugin.rb +9 -0
  168. data/lib/seahorse/client/plugins/endpoint.rb +0 -1
  169. data/lib/seahorse/client/plugins/h2.rb +4 -4
  170. data/lib/seahorse/client/plugins/net_http.rb +57 -16
  171. data/lib/seahorse/client/plugins/request_callback.rb +31 -0
  172. data/lib/seahorse/client/request_context.rb +9 -2
  173. data/lib/seahorse/client/response.rb +8 -0
  174. data/lib/seahorse/model/shapes.rb +2 -2
  175. data/lib/seahorse/util.rb +2 -1
  176. data/sig/aws-sdk-core/async_client_stubs.rbs +21 -0
  177. data/sig/aws-sdk-core/client_stubs.rbs +10 -0
  178. data/sig/aws-sdk-core/errors.rbs +22 -0
  179. data/sig/aws-sdk-core/resources/collection.rbs +21 -0
  180. data/sig/aws-sdk-core/structure.rbs +4 -0
  181. data/sig/aws-sdk-core/telemetry/base.rbs +46 -0
  182. data/sig/aws-sdk-core/telemetry/otel.rbs +22 -0
  183. data/sig/aws-sdk-core/telemetry/span_kind.rbs +15 -0
  184. data/sig/aws-sdk-core/telemetry/span_status.rbs +24 -0
  185. data/sig/aws-sdk-core/waiters/errors.rbs +20 -0
  186. data/sig/aws-sdk-core.rbs +7 -0
  187. data/sig/seahorse/client/async_base.rbs +18 -0
  188. data/sig/seahorse/client/base.rbs +25 -0
  189. data/sig/seahorse/client/handler_builder.rbs +16 -0
  190. data/sig/seahorse/client/response.rbs +61 -0
  191. metadata +105 -23
  192. /data/lib/aws-sdk-core/xml/parser/{engines/libxml.rb → libxml_engine.rb} +0 -0
  193. /data/lib/aws-sdk-core/xml/parser/{engines/nokogiri.rb → nokogiri_engine.rb} +0 -0
  194. /data/lib/aws-sdk-core/xml/parser/{engines/oga.rb → oga_engine.rb} +0 -0
  195. /data/lib/aws-sdk-core/xml/parser/{engines/ox.rb → ox_engine.rb} +0 -0
  196. /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,123 +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[:checksum_algorithms] = request_algorithm_input
122
-
123
- request_checksum_property = {
124
- 'algorithm' => request_algorithm_input,
125
- 'in' => checksum_request_in(context),
126
- '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)
127
192
  }
128
193
 
129
- calculate_request_checksum(context, request_checksum_property)
194
+ context[:http_checksum][:request_algorithm] = request_algorithm
195
+ calculate_request_checksum(context, request_algorithm)
130
196
  end
131
197
 
132
198
  if should_verify_response_checksum?(context)
133
199
  add_verify_response_checksum_handlers(context)
134
200
  end
135
201
 
136
- @handler.call(context)
202
+ with_metrics(context.config, algorithm) { @handler.call(context) }
137
203
  end
138
204
 
139
205
  private
140
206
 
141
- 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)
142
281
  context.operation.http_checksum &&
143
- ChecksumAlgorithm.request_algorithm_selection(context)
282
+ context.config.request_checksum_calculation != 'when_required'
144
283
  end
145
284
 
146
- def should_verify_response_checksum?(context)
147
- 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
148
316
  end
149
317
 
150
318
  def calculate_request_checksum(context, checksum_properties)
151
- 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]
152
324
  when 'header'
153
- header_name = checksum_properties['name']
154
- body = context.http_request.body_contents
155
- if body
156
- context.http_request.headers[header_name] ||=
157
- ChecksumAlgorithm.calculate_checksum(checksum_properties['algorithm'], body)
158
- end
325
+ apply_request_checksum(context, headers, checksum_properties)
159
326
  when 'trailer'
160
- 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)
161
348
  end
349
+ digest.base64digest
162
350
  end
163
351
 
164
- def apply_request_trailer_checksum(context, checksum_properties)
165
- location_name = checksum_properties['name']
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)
358
+ end
359
+ io.rewind
360
+ end
361
+
362
+ def apply_request_trailer_checksum(context, headers, checksum_properties)
363
+ location_name = checksum_properties[:name]
166
364
 
167
365
  # set required headers
168
- headers = context.http_request.headers
169
366
  headers['Content-Encoding'] = 'aws-chunked'
170
367
  headers['X-Amz-Content-Sha256'] = 'STREAMING-UNSIGNED-PAYLOAD-TRAILER'
171
368
  headers['X-Amz-Trailer'] = location_name
@@ -174,120 +371,88 @@ module Aws
174
371
  # to set the Content-Length header (set by content_length plugin).
175
372
  # This means we cannot use Transfer-Encoding=chunked
176
373
 
177
- if !context.http_request.body.respond_to?(:size)
374
+ unless context.http_request.body.respond_to?(:size)
178
375
  raise Aws::Errors::ChecksumError, 'Could not determine length of the body'
179
376
  end
180
377
  headers['X-Amz-Decoded-Content-Length'] = context.http_request.body.size
181
378
 
182
379
  context.http_request.body = AwsChunkedTrailerDigestIO.new(
183
380
  context.http_request.body,
184
- checksum_properties['algorithm'],
381
+ checksum_properties[:algorithm],
185
382
  location_name
186
383
  )
187
384
  end
188
385
 
386
+ def should_verify_response_checksum?(context)
387
+ request_validation_mode(context) == 'ENABLED'
388
+ end
389
+
189
390
  # Add events to the http_response to verify the checksum as its read
190
391
  # This prevents the body from being read multiple times
191
392
  # verification is done only once a successful response has completed
192
393
  def add_verify_response_checksum_handlers(context)
193
- http_response = context.http_response
194
- checksum_context = { }
195
- http_response.on_headers do |_status, headers|
196
- header_name, algorithm = response_header_to_verify(headers, context[:http_checksum][:validation_list])
197
- if header_name
198
- expected = headers[header_name]
199
-
200
- unless context[:http_checksum][:skip_on_suffix] && /-[\d]+$/.match(expected)
201
- checksum_context[:algorithm] = algorithm
202
- checksum_context[:header_name] = header_name
203
- checksum_context[:digest] = ChecksumAlgorithm.digest_for_algorithm(algorithm)
204
- checksum_context[:expected] = expected
205
- end
206
- end
207
- 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
208
399
 
209
- http_response.on_data do |chunk|
210
- 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
211
419
  end
420
+ end
212
421
 
213
- http_response.on_success do
214
- if checksum_context[:digest] &&
215
- (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
216
427
 
217
- if computed != checksum_context[:expected]
218
- raise Aws::Errors::ChecksumError,
219
- "Checksum validation failed on #{checksum_context[:header_name]} "\
220
- "computed: #{computed}, expected: #{checksum_context[:expected]}"
221
- end
428
+ def add_verify_response_success_handler(context, checksum_context)
429
+ context.http_response.on_success do
430
+ next unless checksum_context[:digest]
222
431
 
432
+ computed = checksum_context[:digest].base64digest
433
+ if computed == checksum_context[:expected]
223
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]}"
224
439
  end
225
440
  end
226
441
  end
227
442
 
228
- # returns nil if no headers to verify
229
443
  def response_header_to_verify(headers, validation_list)
230
444
  validation_list.each do |algorithm|
231
- header_name = "x-amz-checksum-#{algorithm}"
445
+ header_name = "x-amz-checksum-#{algorithm.downcase}"
232
446
  return [header_name, algorithm] if headers[header_name]
233
447
  end
234
448
  nil
235
449
  end
236
-
237
- # determine where (header vs trailer) a request checksum should be added
238
- def checksum_request_in(context)
239
- if context.operation['authtype'].eql?('v4-unsigned-body')
240
- 'trailer'
241
- else
242
- 'header'
243
- end
244
- end
245
-
246
- end
247
-
248
- def self.calculate_checksum(algorithm, body)
249
- digest = ChecksumAlgorithm.digest_for_algorithm(algorithm)
250
- if body.respond_to?(:read)
251
- ChecksumAlgorithm.update_in_chunks(digest, body)
252
- else
253
- digest.update(body)
254
- end
255
- digest.base64digest
256
- end
257
-
258
- def self.digest_for_algorithm(algorithm)
259
- case algorithm
260
- when 'CRC32'
261
- Digest32.new(Zlib.method(:crc32))
262
- when 'CRC32C'
263
- # this will only be used if input algorithm is CRC32C AND client supports it (crt available)
264
- Digest32.new(Aws::Crt::Checksums.method(:crc32c))
265
- when 'SHA1'
266
- Digest::SHA1.new
267
- when 'SHA256'
268
- Digest::SHA256.new
269
- end
270
- end
271
-
272
- # The trailer size (in bytes) is the overhead + the trailer name +
273
- # the length of the base64 encoded checksum
274
- def self.trailer_length(algorithm, location_name)
275
- CHECKSUM_SIZE[algorithm] + location_name.size
276
- end
277
-
278
- def self.update_in_chunks(digest, io)
279
- loop do
280
- chunk = io.read(CHUNK_SIZE)
281
- break unless chunk
282
- digest.update(chunk)
283
- end
284
- io.rewind
285
450
  end
286
451
 
287
452
  # Wrapper for request body that implements application-layer
288
453
  # chunking with Digest computed on chunks + added as a trailer
289
454
  class AwsChunkedTrailerDigestIO
290
- CHUNK_SIZE = 16384
455
+ CHUNK_SIZE = 16_384
291
456
 
292
457
  def initialize(io, algorithm, location_name)
293
458
  @io = io
@@ -328,7 +493,7 @@ module Aws
328
493
  else
329
494
  trailers = {}
330
495
  trailers[@location_name] = @digest.base64digest
331
- trailers = trailers.map { |k,v| "#{k}:#{v}"}.join("\r\n")
496
+ trailers = trailers.map { |k,v| "#{k}:#{v}" }.join("\r\n")
332
497
  @trailer_io = StringIO.new("0\r\n#{trailers}\r\n\r\n")
333
498
  chunk = @trailer_io.read(length, buf)
334
499
  end
@@ -40,6 +40,7 @@ side monitoring agent is running on, where client metrics will be published via
40
40
  option(:client_side_monitoring_publisher,
41
41
  default: ClientSideMonitoring::Publisher,
42
42
  doc_type: Aws::ClientSideMonitoring::Publisher,
43
+ rbs_type: 'untyped',
43
44
  docstring: <<-DOCS) do |cfg|
44
45
  Allows you to provide a custom client-side monitoring publisher class. By default,
45
46
  will use the Client Side Monitoring Agent Publisher.
@@ -179,7 +180,6 @@ all generated client side metrics. Defaults to an empty string.
179
180
  complete_opts = {
180
181
  latency: end_time - start_time,
181
182
  attempt_count: context.retries + 1,
182
- user_agent: context.http_request.headers["user-agent"],
183
183
  final_error_retryable: final_error_retryable,
184
184
  final_http_status_code: context.http_response.status_code,
185
185
  final_aws_exception: final_aws_exception,
@@ -11,6 +11,8 @@ module Aws
11
11
  # AttemptHandler comes just before we would retry an error.
12
12
  # Or before we would follow redirects.
13
13
  handlers.add(AttemptHandler, step: :sign, priority: 39)
14
+ # ErrorHandler comes after we have parsed an error.
15
+ handlers.add(ErrorHandler, step: :sign, priority: 95)
14
16
  # LatencyHandler is as close to sending as possible.
15
17
  handlers.add(LatencyHandler, step: :sign, priority: 0)
16
18
  end
@@ -62,17 +64,27 @@ module Aws
62
64
  call_attempt.x_amzn_request_id = headers["x-amzn-request-id"]
63
65
  end
64
66
  call_attempt.http_status_code = context.http_response.status_code
65
- if e = resp.error
67
+ context.metadata[:current_call_attempt] = call_attempt
68
+ request_metrics.add_call_attempt(call_attempt)
69
+ resp
70
+ end
71
+ end
72
+
73
+ class ErrorHandler < Seahorse::Client::Handler
74
+ def call(context)
75
+ resp = @handler.call(context)
76
+ call_attempt = context.metadata[:current_call_attempt]
77
+ if (e = resp.error)
66
78
  e_name = _extract_error_name(e)
67
79
  e_msg = e.message
68
80
  call_attempt.aws_exception = "#{e_name}"
69
81
  call_attempt.aws_exception_msg = "#{e_msg}"
70
82
  end
71
- request_metrics.add_call_attempt(call_attempt)
72
83
  resp
73
84
  end
74
85
 
75
86
  private
87
+
76
88
  def _extract_error_name(error)
77
89
  if error.is_a?(Aws::Errors::ServiceError)
78
90
  error.class.code