4

I'm creating an AWS Lambda and API using Python's Chalice library. My AWS Credentials are injected using github workflow aws-actions and its able to chalice deploy. The endpoints are working and it's deploying perfectly to AWS.

The problem is:

I use Boto3 to create a presigned upload form using its function generate_presigned_post located in docs here: https://boto3.amazonaws.com/v1/documentation/api/latest/guide/s3-presigned-urls.html

But when I use the response from that function and generate an html with it, after submitting the files to upload, it returns me

<Error>
<Code>InvalidAccessKeyId</Code>
<Message>
The AWS Access Key Id you provided does not exist in our records.
</Message>

I checked everything and it seems it's using wrong AWS_ACCESS_KEY but if it's deploying to AWS perfectly, I figured it isn't the issue (at least for now). I use boto3 client and it seems to locate aws credentials automatically but it seems that it does not locate mine (or whatever is happening) and provides a wrong AWS_ACCESS_KEY.

import boto3

S3_CLIENT = boto3.client('s3')
BUCKET = 'bucket_name'

response = S3_CLIENT.generate_presigned_post(
            BUCKET,
            Key="{$filename}",
            Fields=None,
            Conditions=None,
            ExpiresIn=3600
        )

It returns correct response but when integrated with a form and used, the form returns the error.

1 Answers1

1

This is actually a little bit more complicated than it seems because of the nature of lambda and temporary keys. Suffice to say you should follow these steps:

  1. Create an IAM role with permissions to generate presigned urls for the bucket in question.

  2. Take a lambda basic execution role and add permissions for that role to assume the role in step 1.

  3. In your boto3 code, add a step to assume the role in step 1 before generating the signed url. Something like this:

    import boto3
    
    sts_client = boto3.client('sts')
    
    assumed_role_object = sts_client.assume_role(
        RoleArn='arn_of_role_to_assume'
    )
    
    credentials = assumed_role_object['Credentials']
    
    s3_client = boto3.client(
        's3',
        aws_access_key_id=credentials['AccessKeyId'],
        aws_secret_access_key=credentials['SecretAccessKey'],
        aws_session_token=credentials['SessionToken'],
    )
    
    s3_client.generate_presigned_url......
    
Coin Graham
  • 1,343
  • 3
  • 11