diff --git a/aws_requests_auth/aws_auth.py b/aws_requests_auth/aws_auth.py index 1ac00e1..daa8621 100644 --- a/aws_requests_auth/aws_auth.py +++ b/aws_requests_auth/aws_auth.py @@ -1,6 +1,7 @@ import hmac import hashlib import datetime +from io import BufferedIOBase try: # python 2 @@ -129,6 +130,10 @@ def get_aws_request_headers(self, r, aws_access_key, aws_secret_access_key, aws_ if aws_token: signed_headers += ';x-amz-security-token' + # Materialize body if it is a Reader/BufferedReader + if isinstance(r.body, BufferedIOBase): + r.body = r.body.read() + # Create payload hash (hash of the request body content). For GET # requests, the payload is an empty string (''). body = r.body if r.body else bytes() diff --git a/aws_requests_auth/tests/test_aws_auth.py b/aws_requests_auth/tests/test_aws_auth.py index 9e9308f..07e6fd1 100644 --- a/aws_requests_auth/tests/test_aws_auth.py +++ b/aws_requests_auth/tests/test_aws_auth.py @@ -3,6 +3,7 @@ import mock import sys import unittest +from io import BufferedReader, BytesIO from aws_requests_auth.aws_auth import AWSRequestsAuth @@ -220,3 +221,38 @@ def test_auth_for_post_with_unicode_body_python3(self): 'x-amz-content-sha256': hashlib.sha256(mock_request.body.encode()).hexdigest(), }, mock_request.headers) + + @unittest.skipIf( + int(sys.version[0]) < 3, + 'python3 produces a different hash that we\'re comparing.' + ) + def test_auth_for_post_with_buffered_reader_body(self): + self.maxDiff = None + auth = AWSRequestsAuth(aws_access_key='YOURKEY', + aws_secret_access_key='YOURSECRET', + aws_host='search-foo.us-east-1.es.amazonaws.com', + aws_region='us-east-1', + aws_service='es') + url = 'http://search-foo.us-east-1.es.amazonaws.com:80/' + body = b'{"foo":"bar"}' + mock_request = mock.Mock() + mock_request.url = url + mock_request.method = "POST" + mock_request.body = BufferedReader(BytesIO(body)) + mock_request.headers = { + 'Content-Type': 'application/json', + } + + frozen_datetime = datetime.datetime(2016, 6, 18, 22, 4, 5) + with mock.patch('datetime.datetime') as mock_datetime: + mock_datetime.utcnow.return_value = frozen_datetime + auth(mock_request) + self.assertEqual({ + 'Authorization': 'AWS4-HMAC-SHA256 Credential=YOURKEY/20160618/us-east-1/es/aws4_request, ' + 'SignedHeaders=host;x-amz-date, ' + 'Signature=9726d4d0214a875dcaca166e0599dd4ff94816f1cf9d43351d3b2521928b1823', + 'Content-Type': 'application/json', + 'x-amz-date': '20160618T220405Z', + 'x-amz-content-sha256': hashlib.sha256(body).hexdigest(), + + }, mock_request.headers)