Reputation: 133
I´d like to enable Public Read-Access on all items in my Bucket that are in the "public" folder in the serverless.yml file.
Currently this is definition code i use to declare my bucket. Its a bit of copy and paste from one of the serverless-stack examples.
Resources:
AttachmentsBucket:
Type: AWS::S3::Bucket
Properties:
AccessControl: PublicRead
# Set the CORS policy
BucketName: range-picker-bucket-${self:custom.stage}
CorsConfiguration:
CorsRules:
-
AllowedOrigins:
- '*'
AllowedHeaders:
- '*'
AllowedMethods:
- GET
- PUT
- POST
- DELETE
- HEAD
MaxAge: 3000
# Print out the name of the bucket that is created
Outputs:
AttachmentsBucketName:
Value:
Ref: AttachmentsBucket
Now when i try to use a url for a file, it returns access denied. I manually have to set the public read permission for every file by hand in the aws-s3 web interface.
What am i doing wrong?
Upvotes: 13
Views: 5756
Reputation: 8716
This approach worked for me:
Resources:
StaticAssetsBucket:
Type: AWS::S3::Bucket
Properties:
BucketName: ${sls:stage}.${self:service}.static-assets
AccessControl: PublicRead
PublicBucketPolicy:
Type: AWS::S3::BucketPolicy
Properties:
Bucket: !Ref StaticAssetsBucket
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Action:
- "s3:GetObject"
Resource:
- !Sub "${StaticAssetsBucket.Arn}/*"
Principal: "*"
Upvotes: 0
Reputation: 6561
Accepted answer didn't work for me. CloudFormation failed to update the resource with the error:
Action does not apply to any resource(s) in statement (Service: Amazon S3; Status Code: 400; Error Code: MalformedPolicy; Request ID: <...>; S3 Extended Request ID: <...>; Proxy: null)
It appears the wildcard was missing in the resource definition. Full snippet that worked for me:
PublicBucket:
Type: AWS::S3::Bucket
Properties:
BucketName: 'public-bucket-name'
PublicBucketPolicy:
Type: AWS::S3::BucketPolicy
Properties:
Bucket: !Ref PublicBucket
PolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Action:
- 's3:GetObject'
Resource:
- !Join ['/', [!GetAtt [PublicBucket, Arn], '*']]
Principal: '*'
Upvotes: 7
Reputation: 1661
As the others have said, you need to implement a Bucket Policy such as this one:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "PublicReadForGetBucketObjects",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::{NAME_OF_YOUR_BUCKET_HERE}/*"
}
]
}
This can be done in the AWS console by selecting the Bucket, then Permissions, then Bucket Policy. Looks like @Milan C. is indicating how to declare this in a serverless.yml file.
Upvotes: 1
Reputation: 8064
Instead of using CorsConfiguration
on the bucket, you need to attach a bucket policy to it. Try the following:
Resources:
AttachmentsBucket:
Type: AWS::S3::Bucket
Properties:
BucketName: range-picker-bucket-${self:custom.stage}
AttachmentsBucketAllowPublicReadPolicy:
Type: AWS::S3::BucketPolicy
Properties:
Bucket: !Ref AttachmentsBucket
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Action:
- "s3:GetObject"
Resource:
- !Join ['/', [!Ref AttachmentsBucket, 'public']]
Principal: "*"
Upvotes: 12