Benjamin Sommer
Benjamin Sommer

Reputation: 1268

AWS S3 & Serverless - Access Denied when using PUT presigned URL

I'm trying to generate presigned URLs to upload objects to an S3 bucket but whenever I execute the PUT requests to the presigned URLs, I get 'Access Denied' errors. This is the code I am using to generate the URLs (runs inside a node lambda function):

app.post('/upload', async (req, res) => {
    const filename = `${uuid()}.jpg`;

    const url = s3.getSignedUrl('putObject', {
        Bucket: BucketName,
        Key: filename,
        Expires: 3600,
        ContentType: 'image/jpeg',
        ACL: 'public-read',
    });

    res.status(200).json({ url, filename });
});

And here are the permissions from my serverless.yml file:

service: my-service

provider:
  name: aws
  runtime: nodejs12.x
  profile: my-profile
  region: eu-west-2
  iamRoleStatements:
    - Effect: 'Allow'
      Action:
        - 's3:PutObject'
        - 's3:PutObjectAcl'
      Resource:
        - !GetAtt galleryBucket.Arn

Upvotes: 0

Views: 671

Answers (1)

Benjamin Sommer
Benjamin Sommer

Reputation: 1268

I was applying the PutObject and PutObjectAcl permissions to the galleryBucket instead of the objects within it.

You must apply the PutObject permission to the objects inside the bucket, not the bucket itself

I updated my permissions to this and the PUT requests succeeded:

service: my-service

provider:
  name: aws
  runtime: nodejs12.x
  profile: my-profile
  region: eu-west-2
  iamRoleStatements:
    - Effect: 'Allow'
      Action:
        - 's3:PutObject'
        - 's3:PutObjectAcl'
      Resource:
        Fn::Join: ['', ['arn:aws:s3:::', !Ref galleryBucket, '/*']]

Note the /* at the end of the resource identifier

Upvotes: 3

Related Questions