Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Presigned POST URLs work locally but not in Lambda

I have some Python that can request a presigned POST URL to upload an object into an S3 bucket. It works running it locally, under my IAM user with Admin abilities, and I can upload things to the bucket using Postman and cURL. However, when trying to run the same code in Lambda, it says "The AWS Access Key Id you provided does not exist in our records.".

The only difference is that the Lambda function runs without Admin-rights (but it does have a policy that allows it to run any S3 action on the bucket) and is using a different (older) version of Boto3.

This is the code I'm trying to use: https://boto3.amazonaws.com/v1/documentation/api/latest/guide/s3-presigned-urls.html#generating-a-presigned-url-to-upload-a-file

I've tried to use the details returned from the Lambda function in exactly the same way as I'm using the details returned locally, but the Lambda details don't work.

like image 362
Brewmeister Avatar asked Jun 17 '19 21:06

Brewmeister


People also ask

How does a Presigned URL work?

A presigned URL gives you access to the object identified in the URL, provided that the creator of the presigned URL has permissions to access that object.

What is difference between Presigned and signed URL?

The pre-signed URLs are valid only for the specified duration. Signed Url (AWS doc): A signed URL includes additional information, for example, an expiration date and time, that gives you more control over access to your content.

How do I trigger Lambda based on S3 upload?

step 1: First create your lambda function, select the runtime and select blank function or any blue print from the list. step 2: Select the blank square and choose S3 from the list of services. step 4: Enter prefix, incase if you have any folders inside the S3 and want to triggered only uploading to that folder.


1 Answers

Here is 100% workable solution of AWS lambda

  1. Attach policy AmazonS3FullAccess

  2. Do not use multipart/form-data upload

  3. Configure S3 CORS

  4. Use next python code

     import uuid
     import boto3
    
     def lambda_handler(event, context):
    
         s3 = boto3.client('s3')
    
         upload_key = 'myfile.pdf'
         download_key = 'myfile.pdf'
    
         bucket = 'mys3storage'
    
         # Generate the presigned URL for download
         presigned_download_url = s3.generate_presigned_url(
             ClientMethod='get_object',
             Params={
                 'Bucket': bucket,
                 'Key': download_key,
                 'Expires': 3600
             }
         )
    
         # Generate the presigned URL for upload
         presigned_upload_url = s3.generate_presigned_url(
             ClientMethod='put_object',
             Params={
                 'Bucket': bucket,
                 'Key': upload_key,
                 'ContentType': 'application/pdf',
                 'Expires': 3600
             }
         )
    
         # return the result
         return {
             "upload_url": presigned_upload_url
             "download_url": download_url
         }
    
like image 114
Pavlo Datsiuk Avatar answered Oct 07 '22 15:10

Pavlo Datsiuk