aws/aws-sdk-core-ruby — pull request #163 by JAndritsch (2014-11-25 23:06:19+00:00)
Title: V4 Signer does not properly set the "Signed headers" section of the canonical request

I'm trying to use Aws::Signers::V4 to generate signatures for a multipart upload, but I keep getting a signature mismatch error when using this class. I tracked the problem down to the canonical request. I believe the issue is that the "signed headers" section of the canonical request doesn't lowercase the header names before sorting them. This results in a canonical request that differs from what the API returns.

Adding a simple "downcase" to each of the keys seems to fix the problem.

There's already test coverage for this method, but I believe it's passing because of a false-positive. Here is the test:

context '#signed_headers' do

it 'lower-cases and sort all header keys except authorization' do
http_request.headers['Xyz'] = '1'
http_request.headers['Abc'] = '2'
http_request.headers['Mno'] = '3'
http_request.headers['Authorization'] = '4'
http_request.headers['authorization'] = '5'

expect(signer.signed_headers(http_request)).to eq('abc;mno;xyz')
end

end

It looks like this passes because the http_request object is of type Seahorse::Client::Http::Request. If you were to add a puts statement right before the "expect" line, you can see the keys are already downcased. Perhaps Seahorse already does this for you. I don't actually use Seahorse in my code that uses this class. Rather, I'm passing in a custom request object that has a similar interface to the Seahorse request object. This is how I came to discover the issue.

I've modified the test to not use Seahorse to prove that the signed_headers method actually downcases all header names. Please have a look and let me know if there are any questions.