I have a serverless service running with the below configuration in the serverless.yml file:
service: tableau-export-rest
custom:
dev:
tableauBookmarksBucket: tmt-${self:provider.stage}-tableau-bookmarks
qa:
tableauBookmarksBucket: tmt-${self:provider.stage}-tableau-bookmarks
prod:
tableauBookmarksBucket: tmt-${self:provider.stage}-tableau-bookmarks
provider:
name: aws
runtime: nodejs12.x
region: eu-west-1
stage: ${opt:stage, 'dev'}
timeout: 900
memorySize: 3008
environment:
TABLEAU_BOOKMARKS_BUCKET: ${self:custom.${self:provider.stage}.tableauBookmarksBucket}
iamRoleStatements:
- Effect: Allow
Action:
- s3:PutObject
- s3:GetObject
- s3:ListBucket
Resource: "arn:aws:s3:::${self:custom.${self:provider.stage}.tableauBookmarksBucket}/*"
- Effect: Allow
Action:
- lambda:InvokeFunction
Resource: "arn:aws:lambda:*"
functions:
saveBookmark:
handler: index.saveBookmark
timeout: 30
events:
- http:
path: /save-bookmark
method: post
cors:
origin: '*'
The saveBookmark function looks something like this:
const params = {
Bucket: process.env.TABLEAU_BOOKMARKS_BUCKET,
Key: 'ABC123'
}
s3.headObject(params, (err, data) => {
if (err) {
console.log(err);
} else {
console.log(data);
}
})
I am for some reason getting a 403 error when attempting to HEAD a file in the bucket which does not exist. After looking into the issue I discovered that I should add the permission s3:ListBucket to the list of serverless permissions to allow the headObject method which I did. This didn't seem to have any effect as I am still getting a 403 when trying to head an object in the bucket.
The bucket is not public and when I try to use the putObject method to upload a file into the bucket it works fine. Also, when the file exists in the bucket, the headObject method works just fine with a 403.
Why would I be getting a 403 instead of a 404 when a file is not present in a bucket?
Thanks
Try changing from
iamRoleStatements:
- Effect: Allow
Action:
- s3:PutObject
- s3:GetObject
- s3:ListBucket
Resource: "arn:aws:s3:::${self:custom.${self:provider.stage}.tableauBookmarksBucket}/*"
to
iamRoleStatements:
- Effect: Allow
Action:
- s3:PutObject
- s3:GetObject
Resource: "arn:aws:s3:::${self:custom.${self:provider.stage}.tableauBookmarksBucket}/*"
- Effect: Allow
Action: s3:ListBucket
Resource: "arn:aws:s3:::${self:custom.${self:provider.stage}.tableauBookmarksBucket}"
I think you are missing GetObjectAttributes permisson. so your complete policy will look like below.
iamRoleStatements:
- Effect: Allow
Action:
- s3:PutObject
- s3:GetObject
- s3:ListBucket
- s3:GetObjectAttributes
Resource: "arn:aws:s3:::${self:custom.${self:provider.stage}.tableauBookmarksBucket}/*"
here quote from official documentation
You need the relevant read object (or version) permission for this operation. For more information, see Specifying Permissions in a Policy. If the object you request does not exist, the error Amazon S3 returns depends on whether you also have the s3:ListBucket permission.
If you have the s3:ListBucket permission on the bucket, Amazon S3 returns an HTTP status code 404 ("no such key") error.
If you don’t have the s3:ListBucket permission, Amazon S3 returns an HTTP status code 403 ("access denied") error.
The following actions are related to HeadObject:
- GetObject
- GetObjectAttributes
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With