Aurelia Peters
Aurelia Peters

Reputation: 2209

Why am I getting "AccessDenied" from S3 DeleteObjects?

I'm trying to delete a number of objects in an S3 bucket like so (Lambda / Node.js):

exports.handler =  async function(event, context) {
  const s3Params = {
    Bucket: 'my-bucket',
    Delete: {
      Objects: [ 'my-bucket/dir/file1.json', 'my-bucket/dir/file2.json' ],
      Quiet: False
    }
  }
  const result = await s3.deleteObjects(s3Params).promise()
  return result
}

But I get:

{ 
  result: { 
    Deleted: [],
    Errors: [ 
        {Key: "my-bucket/dir/file1.json", Code: "AccessDenied", Message: "Access Denied"},
        {Key: "my-bucket/dir/file1.json", Code: "AccessDenied", Message: "Access Denied"}
    ]
  }
}  

Here is my role policy:

{
    "RoleName": "S3CleanupRole", 
    "PolicyDocument": {
        "Version": "2012-10-17", 
        "Statement": [
            {
                "Action": [
                    "s3:ListBucket", 
                    "s3:DeleteObject"
                ], 
                "Resource": [
                    "arn:aws:s3:::my-bucket"
                ], 
                "Effect": "Allow"
            }, 
            {
                "Action": [
                    "DynamoDB:Query"
                ], 
                "Resource": [
                    "arn:aws:dynamodb:us-east-1:514141358776:table/buckets-to-clean-out"
                ], 
                "Effect": "Allow"
            }
        ]
    }, 
    "PolicyName": "S3CleanupPolicy"
}

What's the problem?

Upvotes: 1

Views: 4970

Answers (1)

Aurelia Peters
Aurelia Peters

Reputation: 2209

(Kudos to Ravi Ramanujam for this - his answer to AWS S3 Access Denied on delete helped me solve this problem.)

My policy is wrong. The permission for s3:DeleteObject applies only to the bucket arn:aws:dynamodb:us-east-1:514141358776:table/buckets-to-clean-out and not any of its contents. The correct policy allows s3:DeleteObject on the bucket contents, viz:

{
    "RoleName": "S3CleanupRole", 
    "PolicyDocument": {
        "Version": "2012-10-17", 
        "Statement": [
            {
                "Action": [
                    "s3:ListBucket"
                ], 
                "Resource": [
                    "arn:aws:s3:::my-bucket"
                ], 
                "Effect": "Allow"
            }, 
            {
                "Action": [
                    "s3:DeleteObject"
                ], 
                "Resource": [
                    "arn:aws:s3:::my-bucket/*"
                ], 
                "Effect": "Allow"
            }, 
            {
                "Action": [
                    "DynamoDB:Query"
                ], 
                "Resource": [
                     "arn:aws:dynamodb:us-east-1:514141358776:table/buckets-to-clean-out"
                ], 
                "Effect": "Allow"
            }
        ]
    }, 
    "PolicyName": "S3CleanupPolicy"
}

The crucial piece is below. Note that the "Resource" section contains arn:aws:s3:::my-bucket/* rather than just arn:aws:s3:::my-bucket

 {
     "Action": [
         "s3:DeleteObject"
     ], 
     "Resource": [
          "arn:aws:s3:::my-bucket/*"
     ], 
     "Effect": "Allow"
 } 

Upvotes: 3

Related Questions