1

Several questions and answers on SO and elsewhere have outlined possible solutions for resolving the SignatureDoesNotMatch error thrown when calling 'generate_presigned_url' from the boto3 SDK. Few are in boto3 and most answers suggest getting new credentials to resolve this exception. You can see more (but this is in PHP) here.

But these do not work for me, because I am using correct credentials and the correct bucket name and key path.

Originally, I was calling this to generate my client and then call generate_presigned_url.

client_s3 = boto3.client(
    's3',
    # Hard coded strings as credentials, not recommended.
    aws_access_key_id='XXX',
    aws_secret_access_key='XXX',
    region_name='us-east-2',
    # EDIT: Previously, I used signature_version='v4' here, but as a user here pointed out, this might not work. Regardless, I tried 's3v4' prior to trying 'v4' and neither worked for me.
    config=Config(signature_version='s3v4')
)

url = client_s3.generate_presigned_url(
    ClientMethod='get_object',
    Params={
        'Bucket': 'BUCKET_NAME',
        'Key': 'CORRECT_KEY'
    }
)

What could create this error when all of the parameters used are seemingly correct? How do I resolve it?

5 Answers 5

7

It is clearly mentioned in the documentation of boto3 that the option should look like config=Config(signature_version='s3v4'). v4 wouldn't work.

This is an example of boto3 documentation.

import boto3
from botocore.client import Config

# Get the service client with sigv4 configured
s3 = boto3.client('s3', config=Config(signature_version='s3v4'))

# Generate the URL to get 'key-name' from 'bucket-name'
url = s3.generate_presigned_url(
    ClientMethod='get_object',
    Params={
        'Bucket': 'bucket-name',
        'Key': 'key-name'
    }
)

Btw, us-east-2 only allow signature verion 4 and so you don't need to specify that. See This.

Sign up to request clarification or add additional context in comments.

6 Comments

Hi, I used that as well, and later changed it to v4 after I saw another user tried 'v4' instead. Both did not work for me. Thank you for your answer.
your original region don't need to specify the signature version, cuz v4 is default and only option for that.
Yup, it does not work without specification of the signature version either.
Then, please check your bucket location by dong client_s3.get_bucket_location(Bucket='string').
Furthermore, try to use the config Config(s3={'addressing_style': 'path'}). What version of boto3 are u using?
|
1

I know this is a bit late to answer, but I solved my problem by following the method as specified in this GitHub link.

import boto3
import requests

parts = s3_client.generate_presigned_post(Bucket=bucket_name,
                                          Key=key,
                                          Fields={
                                            'acl': 'public-read',
                                            'Content-MD5': str(md5),
                                            'Content-Type': 'binary/octet-stream'
                                            },
                                          Conditions=[
                                              {"acl": "public-read"},
                                              ["starts-with", "$Content-Type", ""],
                                              ["starts-with", "$Content-MD5", ""]
                                          ]
                                      )

url = parts['url']
data = parts['fields']
files = {'file': open(local_path, 'rb')} # the key supposed to be file may be
response = requests.post(url, data=data, files=files)

Comments

1

Specifying region_name and signature_version using a Config Object in the client is what worked for me. If you wanna know more about Config https://boto3.amazonaws.com/v1/documentation/api/latest/guide/configuration.html

    s3_client: Session = boto3.client(
        "s3",`enter code here`
        config=Config(
            signature_version="s3v4",
            region_name="us-west-2"
            ),
        )

Comments

0

Late to the party here, but I have a solution that works for me and I anticipate it may work for others.

    s3_client: Session = boto3.client(
        "s3",
        aws_access_key_id=kwargs["aws_access_key_id"],
        aws_secret_access_key=kwargs["aws_secret_access_key"],
        config=Config(
            signature_version="s3v4",
            region_name="us-east-2",
        ),
    )

    response: str = s3_client.generate_presigned_url(
        "put_object",
        Params={"Bucket": "example-bucket", "Key": "subfolder/file_name.zip"},
        ExpiresIn=expiration,
    )

The response will contain the pre-signed URL. I then take the URL and paste it into Postman to test it out and make sure you use PUT instead of POST and add your file as a binary payload. I've tested and verified this method.

Comments

-4

After seeing this AWS forum, I figured something fishy might be going on, but I really just wanted to resolve the issue with a secure solution.

My resolution is definitely not optimal for everyone, but it worked for me.

I copied everything from my bucket in 'us-east-2' into a new bucket in 'us-east-1' and I was able to access that bucket correctly with the exact same access/secret keys and bucket/key paths. I simply used:

client_s3 = boto3.client(
    's3',
    # Hard coded strings as credentials, not recommended.
    aws_access_key_id='XXX',
    aws_secret_access_key='XXX'
)

If you're like me and don't want to spend hours trying to decipher AWS's poor docs, just do this if you can. If you have a real solution, please add it here.

I still am unsure what causes this, but likely has something to do with the 'v4' signing method, which is region-dependent.

1 Comment

To the two downvoters --- easy to downvote, but realize first I posted the question and answer before any existed for the purpose of helping. My answer, while suboptimal, was the only answer at the time. If you have feedback, post it here.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.