1

I'm following testdrive.io's serverless-fastapi course. It uses cloudformation to setup the bucket and bucket policy. The bucket is created just fine, however there are issues creating the bucket policy. First I had to comment out # AccessControl: PublicRead due to the new policy in April (see post). However, now it is failing due to this error:

API: s3:PutBucketPolicy Access Denied

I'm deploying the serverless.yml file via github and have created a user for github that has the following permissions: AdministratorAccess

This bucket should be open to the public as it will host the files for a front end Vue webframework. How does one create the bucket policy for that?

# serverless.yml 
service: tasks-ui

frameworkVersion: "3"
useDotenv: true

provider:
  name: aws
  region: ${opt:region, 'us-east-2'}
  stage: ${opt:stage, 'development'}

plugins:
  - serverless-s3-sync

custom:
  stage: ${opt:stage, self:provider.stage}
  bucketName: ${self:custom.stage}-tasks-api-mp
  s3Sync:
    # A simple configuration for copying static assets!
    - bucketName: ${self:custom.bucketName}
      localDir: dist

resources:
  Resources:
    TasksAPIBucket:
      Type: AWS::S3::Bucket
      Properties:
        BucketName: ${self:custom.bucketName}
        # AccessControl: PublicRead
        WebsiteConfiguration:
          IndexDocument: index.html
          ErrorDocument: error.html
    TasksAPIBucketPolicy:
      Type: AWS::S3::BucketPolicy
      Properties:
        Bucket: !Ref TasksAPIBucket
        PolicyDocument:
          Version: "2012-10-17"
          Statement:
            - Sid: "PublicReadGetObject"
              Effect: "Allow"
              Principal: "*"
              Action: "s3:GetObject"
              Resource:
                Fn::Join:
                  - ""
                  - - "arn:aws:s3:::"
                    - !Ref TasksAPIBucket
                    - "/*"
  Outputs:
    TasksAPIBucketName:
      Value: !Ref TasksAPIBucket
      Export:
        Name: s3-${self:custom.bucketName}-name
    TasksAPIBucketArn:
      Value: !GetAtt TasksAPIBucket.Arn
      Export:
        Name: s3-${self:custom.bucketName}-arn

Micah Pearce
  • 1,805
  • 3
  • 28
  • 61
  • Does this answer your question? [AWS S3: Bucket cannot have ACLs set with ObjectOwnership's BucketOwnerEnforced setting)](https://stackoverflow.com/questions/76097031/aws-s3-bucket-cannot-have-acls-set-with-objectownerships-bucketownerenforced-s) – Felix May 01 '23 at 03:33
  • 1
    It sounds like the bucket has **S3 Block Public Access** activated, which blocks the creation of a Bucket Policy. You can change it using [AWS::S3::Bucket PublicAccessBlockConfiguration - AWS CloudFormation](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-s3-bucket-publicaccessblockconfiguration.html). Turn off anything related to Bucket Policies. – John Rotenstein May 01 '23 at 03:46
  • @JohnRotenstein That was it! That's exactly what I needed. Thank you. If you want to make it answer I'll accept it. – Micah Pearce May 02 '23 at 00:41

2 Answers2

0

Receiving a s3:PutBucketPolicy Access Denied error typically indicates that either:

  • You do not hav permission to set the Bucket Policy, or
  • The bucket has S3 Block Public Access enabled

Your account possibly has Block Public Access enabled by default, so each new bucket receives the setting.

From AWS::S3::Bucket PublicAccessBlockConfiguration - AWS CloudFormation:

  BlockPublicAcls: Boolean
  BlockPublicPolicy: Boolean
  IgnorePublicAcls: Boolean
  RestrictPublicBuckets: Boolean

You want to change the values that refer to Bucket Policies.

John Rotenstein
  • 241,921
  • 22
  • 380
  • 470
0

Here is the serverless.yml file I used and it worked for me

service: tasks-ui

frameworkVersion: '3'
useDotenv: true


provider:
  name: aws
  region: ${opt:region, 'us-west-2'}
  stage: ${opt:stage, 'development'}



plugins:
  - serverless-s3-sync


custom:
  stage: ${opt:stage, self:provider.stage}
  bucketName: ${self:custom.stage}-tasks-api-friar
  s3Sync:
    # A simple configuration for copying static assets
    - bucketName: ${self:custom.bucketName}
      localDir: dist


resources:
  Resources:
    TasksAPIBucket:
      Type: AWS::S3::Bucket
      Properties:
        BucketName: ${self:custom.bucketName}
        #AccessControl: PublicRead
        PublicAccessBlockConfiguration:
          BlockPublicAcls: false
        OwnershipControls:
          Rules:
            - ObjectOwnership: ObjectWriter
        WebsiteConfiguration:
          IndexDocument: index.html
          ErrorDocument: error.html
    TasksAPIBucketPolicy:
      Type: AWS::S3::BucketPolicy
      Properties:
        Bucket: !Ref TasksAPIBucket
        PolicyDocument:
          Version: "2012-10-17"
          Statement:
            - Sid: "PublicReadGetObject"
              Effect: "Allow"
              Principal: "*"
              Action: "s3:GetObject"
              Resource:
                Fn::Join:
                  - ""
                  - - "arn:aws:s3:::"
                    - !Ref TasksAPIBucket
                    - "/*"
  Outputs:
    TasksAPIBucketName:
      Value: !Ref TasksAPIBucket
      Export:
        Name: s3-${self:custom.bucketName}-name
    TasksAPIBucketArn:
      Value: !GetAtt TasksAPIBucket.Arn
      Export:
        Name: s3-${self:custom.bucketName}-arn