Reputation: 1635
My code is successfully uploading documents into the correct bucket. I can login and see the docs in the buckets on AWS S3. When I try to use the generate_signed_url method in boto3 to obtain a URL for these documents that can then be sent to users for accessing the doc, I'm getting a SignatureDoesNotMatch with the message saying "The request signature we calculated does not match the signature you provided. Check your key and signing method."
When i save the object (verified that it is working correctly by logging into AWS and downloading the files manually), I use:
s3 = boto3.client('s3', region_name='us-east-2', aws_access_key_id='XXXX', aws_secret_access_key='XXXX', config=Config(signature_version='s3v4'))
s3.put_object(Bucket=self.bucket_name,Key=path, Body=temp_file.getvalue(),ACL='public-read')
Then, when I try to get the URL, I'm using:
s3 = boto3.client('s3', region_name='us-east-2', aws_access_key_id='XXXX', aws_secret_access_key='XXXX', config=Config(signature_version='s3v4'))
url = s3.generate_presigned_url(
'put_object', Params={
'Bucket':self.pdffile_storage_bucket_name,
'Key':self.pdffile_url
},
ExpiresIn=604799,
)
I saw quite a bit of users on the web talking about making sure your AWS access key doesn't include any special characters. I did this, and I still get the same issue.
Upvotes: 2
Views: 12212
Reputation: 716
I tried many solutions from many different places. None of the worked for me. Then i got a solution on GitHub, that worked for me. Here is the original solution, just copy pasting his solution.
s3 = boto3.client(
's3', region_name='us-east-2',
aws_access_key_id='XXXX', aws_secret_access_key='XXXX',
config=Config(signature_version='s3v4'),
endpoint_url='https://s3.us-east-2.amazonaws.com'
)
Upvotes: 7
Reputation: 11
As stated above, adding parameter config=Config(signature_version='s3v4')
when creating the boto3 client (or boto3 Session) fixed this error.
Note also that Config is located in botocore.client
Upvotes: 0
Reputation: 595
I had a trailing space on my secret access key variable. That was causing the issue. E.g: AWS_SECRET_KEY = "xyz "
Upvotes: 1
Reputation: 807
(after 3+ hours of debugging and almost smashing the keyboard....)
in the response, it's telling you which header is missing:
<Error>
<Code>SignatureDoesNotMatch</Code>
<Message>The request signature we calculated does not match the signature you provided. Check your key and signing method.</Message>
<!-- .... -->
<CanonicalRequest>PUT (your pre-signed url)
content-type:image/jpeg
host:s3.eu-west-2.amazonaws.com
x-amz-acl:
content-type;host;x-amz-acl
UNSIGNED-PAYLOAD</CanonicalRequest>
Needed a x-amz-acl
header matching the ACL set when generating the pre-signed URL
def python_presign_url():
return s3.generate_presigned_url('put_object', Params={
'Bucket': bucket_name,
'Key': filename,
'ContentType': type,
'ACL':'public-read' # your x-amz-acl
})
curl -X PUT \
-H "content-type: image/jpeg" \
-H "Host: s3.eu-west-2.amazonaws.com" \
-H "x-amz-acl: public-read" \
-d @/path/to/upload/file.jpg "$PRE_SIGNED_URL"
Upvotes: 2
Reputation: 179084
You are generating a pre-signed URL for an upload, not a download. You don't want put_object
here... it's get_object
.
Also, as @ThijsvanDien pointed out, ACL='public-read'
may not be what you want, when uploading -- this makes the object accessible to anyone with an unsigned URL.
Upvotes: 2