Skip to content

Commit

Permalink
Default algorithm header test cases
Browse files Browse the repository at this point in the history
  • Loading branch information
mullermp committed Nov 18, 2024
1 parent e738d04 commit 5e65945
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 36 deletions.
39 changes: 26 additions & 13 deletions gems/aws-sdk-core/lib/aws-sdk-core/plugins/checksum_algorithm.rb
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,8 @@ def call(context)
request_algorithm = {
algorithm: algorithm,
in: checksum_request_in(context),
name: "x-amz-checksum-#{algorithm.downcase}"
name: "x-amz-checksum-#{algorithm.downcase}",
request_algorithm_header: request_algorithm_header(context)
}

context[:http_checksum][:request_algorithm] = request_algorithm
Expand Down Expand Up @@ -251,6 +252,12 @@ def request_algorithm_selection(context)
context.params[input_member.to_sym] ||= DEFAULT_CHECKSUM if input_member
end

def request_algorithm_header(context)
input_member = context.operation.http_checksum['requestAlgorithmMember']
shape = context.operation.input.shape.member(input_member)
shape.location_name if shape && shape.location == 'header'
end

def request_validation_mode(context)
return unless context.operation.http_checksum

Expand Down Expand Up @@ -309,22 +316,29 @@ def checksum_request_in(context)
end

def calculate_request_checksum(context, checksum_properties)
headers = context.http_request.headers
if (algorithm_header = checksum_properties[:request_algorithm_header])
headers[algorithm_header] = checksum_properties[:algorithm]
end
case checksum_properties[:in]
when 'header'
header_name = checksum_properties[:name]
headers = context.http_request.headers
unless headers[header_name]
body = context.http_request.body_contents
headers[header_name] = calculate_checksum(
checksum_properties[:algorithm],
body
)
end
apply_request_checksum(context, headers, checksum_properties)
when 'trailer'
apply_request_trailer_checksum(context, checksum_properties)
apply_request_trailer_checksum(context, headers, checksum_properties)
else
# nothing
end
end

def apply_request_checksum(context, headers, checksum_properties)
header_name = checksum_properties[:name]
body = context.http_request.body_contents
headers[header_name] = calculate_checksum(
checksum_properties[:algorithm],
body
)
end

def calculate_checksum(algorithm, body)
digest = ChecksumAlgorithm.digest_for_algorithm(algorithm)
if body.respond_to?(:read)
Expand All @@ -345,11 +359,10 @@ def update_in_chunks(digest, io)
io.rewind
end

def apply_request_trailer_checksum(context, checksum_properties)
def apply_request_trailer_checksum(context, headers, checksum_properties)
location_name = checksum_properties[:name]

# set required headers
headers = context.http_request.headers
headers['Content-Encoding'] = 'aws-chunked'
headers['X-Amz-Content-Sha256'] = 'STREAMING-UNSIGNED-PAYLOAD-TRAILER'
headers['X-Amz-Trailer'] = location_name
Expand Down
45 changes: 22 additions & 23 deletions gems/aws-sdk-core/spec/aws/plugins/checksum_algorithm_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -175,13 +175,13 @@ module Plugins
allow_any_instance_of(Aws::SharedConfig)
.to receive(:response_checksum_validation)
.and_return('when_supported')
ENV['AWS_response_checksum_validation'] = 'when_required'
ENV['AWS_RESPONSE_CHECKSUM_VALIDATION'] = 'when_required'
expect(client.config.response_checksum_validation)
.to eq('when_required')
end

it 'raises when response_checksum_validation is not valid' do
ENV['AWS_response_checksum_validation'] = 'peccy'
ENV['AWS_RESPONSE_CHECKSUM_VALIDATION'] = 'peccy'
expect { client }.to raise_error(ArgumentError, /when_supported/)
end
end
Expand All @@ -193,26 +193,23 @@ module Plugins
end.to raise_error(ArgumentError)
end

it 'with requestAlgorithmMember; will use a CRC32 as a default' do
resp = client.http_checksum_operation
header = resp.context.http_request.headers['x-amz-checksum-crc32']
expect(header).to eq('AAAAAA==')
end

file = File.expand_path('checksum_request.json', __dir__)
test_cases = JSON.load_file(file)

test_cases.each do |test_case|
it "passes test: #{test_case['documentation']}" do
algorithm = test_case['checksumAlgorithm'].upcase
unless ChecksumAlgorithm::CLIENT_ALGORITHMS.include?(algorithm)
skip "Algorithm #{algorithm} not supported"
options = {
body: test_case['requestPayload']
}
if (algorithm = test_case['checksumAlgorithm'])
algorithm.upcase!
unless ChecksumAlgorithm::CLIENT_ALGORITHMS.include?(algorithm)
skip "Algorithm #{algorithm} not supported"
end
options[:checksum_algorithm] = algorithm
end

resp = client.http_checksum_operation(
checksum_algorithm: algorithm,
body: test_case['requestPayload']
)
resp = client.http_checksum_operation(**options)
headers = resp.context.http_request.headers
test_case['expectHeaders'].each do |key, value|
expect(headers[key]).to eq(value)
Expand All @@ -227,12 +224,17 @@ module Plugins

test_cases.each do |test_case|
it "passes test: #{test_case['documentation']}" do
algorithm = test_case['checksumAlgorithm'].upcase
unless ChecksumAlgorithm::CLIENT_ALGORITHMS.include?(algorithm)
skip "Algorithm #{algorithm} not supported"
options = {
body: test_case['requestPayload']
}
if (algorithm = test_case['checksumAlgorithm'])
algorithm.upcase!
unless ChecksumAlgorithm::CLIENT_ALGORITHMS.include?(algorithm)
skip "Algorithm #{algorithm} not supported"
end
options[:checksum_algorithm] = algorithm
end

body = test_case['requestPayload']
client.stub_responses(:http_checksum_streaming_operation, lambda do |context|
headers = context.http_request.headers

Expand All @@ -256,10 +258,7 @@ module Plugins
context
end)

client.http_checksum_streaming_operation(
checksum_algorithm: algorithm,
body: body
)
client.http_checksum_streaming_operation(**options)
end
end
end
Expand Down
8 changes: 8 additions & 0 deletions gems/aws-sdk-core/spec/aws/plugins/checksum_request.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,12 @@
[
{
"documentation": "Defaults to CRC32.",
"requestPayload": "Hello world",
"expectHeaders": {
"x-amz-request-algorithm": "CRC32",
"x-amz-checksum-crc32": "i9aeUg=="
}
},
{
"documentation": "CRC32 checksum calculation works.",
"requestPayload": "Hello world",
Expand Down
17 changes: 17 additions & 0 deletions gems/aws-sdk-core/spec/aws/plugins/checksum_streaming_request.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,23 @@
[
{
"documentation": "Defaults to CRC32.",
"requestPayload": "Hello world",
"expectHeaders": {
"content-encoding": "aws-chunked",
"x-amz-request-algorithm": "CRC32",
"x-amz-trailer": "x-amz-checksum-crc32"
},
"expectTrailers": {
"x-amz-checksum-crc32": "i9aeUg=="
}
},
{
"documentation": "CRC32 streaming checksum calculation works.",
"requestPayload": "Hello world",
"checksumAlgorithm": "Crc32",
"expectHeaders": {
"content-encoding": "aws-chunked",
"x-amz-request-algorithm": "CRC32",
"x-amz-trailer": "x-amz-checksum-crc32"
},
"expectTrailers": {
Expand All @@ -17,6 +30,7 @@
"checksumAlgorithm": "Crc32C",
"expectHeaders": {
"content-encoding": "aws-chunked",
"x-amz-request-algorithm": "CRC32C",
"x-amz-trailer": "x-amz-checksum-crc32c"
},
"expectTrailers": {
Expand All @@ -29,6 +43,7 @@
"checksumAlgorithm": "Crc64Nvme",
"expectHeaders": {
"content-encoding": "aws-chunked",
"x-amz-request-algorithm": "CRC64NVME",
"x-amz-trailer": "x-amz-checksum-crc64nvme"
},
"expectTrailers": {
Expand All @@ -41,6 +56,7 @@
"checksumAlgorithm": "Sha1",
"expectHeaders": {
"content-encoding": "aws-chunked",
"x-amz-request-algorithm": "SHA1",
"x-amz-trailer": "x-amz-checksum-sha1"
},
"expectTrailers": {
Expand All @@ -53,6 +69,7 @@
"checksumAlgorithm": "Sha256",
"expectHeaders": {
"content-encoding": "aws-chunked",
"x-amz-request-algorithm": "SHA256",
"x-amz-trailer": "x-amz-checksum-sha256"
},
"expectTrailers": {
Expand Down

0 comments on commit 5e65945

Please sign in to comment.