4

I'm following AWS Walkthrough on setting up AWS Lambda that generates thumbnails from an S3 bucket: when a sourcebucket receives a new object it invokes a lambda to transform that object and save its thumbnails into a destination bucket. Everything works with the default code snippet where no ACL is specified for the object, in which case S3 automatically sets it to private. However, when I modify code and set object's ACL to 'public-read', Lambda fails to save the object into destination bucket and throws an 'Access Denied' error.

s3.putObject({
    Bucket: dstBucket,
    Key: dstKey,
    Body: data,
    ContentType: 'image/jpeg',
    ACL: 'public-read',
    StorageClass: style.storageClass})

Following the tutorial I've added the following access policy to the lambda via an IAM adminuser:

aws lambda add-permission \
--function-name CreateThumbnail \
--region eu-west-1 \
--statement-id some-unique-id \
--action "lambda:InvokeFunction" \
--principal s3.amazonaws.com \
--source-arn arn:aws:s3:::sourcebucket \
--source-account bucket-owner-account-id \
--profile adminuser

The adminuser is part of a group with AdministratorAccess allowing to perform all actions on all resources:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "*",
      "Resource": "*"
    }
  ]
}

So I'm really not sure why Lambda doesn't have the permission to save 'public-read' objects.

Following the tutorial the Lambda also has an AWSLambdaExecute role that gives it permissions to perform all the necessary actions on the bucket:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "logs:*"
      ],
      "Resource": "arn:aws:logs:*:*:*"
    },
    {
      "Effect": "Allow",
      "Action": [
        "s3:GetObject",
        "s3:PutObject"
      ],
      "Resource": "arn:aws:s3:::*"
    }
  ]
}

While I could set a 'public-read' policy on all resources at the bucket level, I would like to keep some objects private in the destination bucket.

enter image description here

Jedi
  • 3,088
  • 2
  • 28
  • 47
Sbbs
  • 1,610
  • 3
  • 22
  • 34

1 Answers1

6

Looks like AWSLambdaExecute Role Policy that the tutorial recommends to attach to the Lambda lacks the permission to specify object's ACL. To solve this I've attached an extra inline policy that grants lambda the permission for "s3:PutObjectAcl" action as well:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "s3:PutObjectAcl"
            ],
            "Resource": "arn:aws:s3:::*"
        }
    ]
}

To avoid having two policies for the lambda, you can just specify one custom policy as follows:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "s3:GetObject",
        "s3:PutObject",
        "s3:PutObjectAcl"
      ],
      "Resource": "arn:aws:s3:::*"
    }
  ]
}

Thanks to this answer.

Community
  • 1
  • 1
Sbbs
  • 1,610
  • 3
  • 22
  • 34