Search code examples
amazon-web-servicesamazon-s3serverless

How to create public S3 bucket in Serverless


I have the following Servlerless config that is trying to create a public access S3 bucket that I can use for hosting images for a website. I want to make sure that it has GetObject access to anybody since they will be public images.

provider:
  name: aws
  runtime: nodejs18.x
  timeout: 25
  iam:
    role:
      statements:
        - Effect: Allow
          Action:
            - 's3:GetObject'
            - 's3:PutBucketPolicy'
          Resource:
            - 'arn:aws:s3:::my-bucket-name/*'


resources:
  Resources:

    WebImagesBucket:
      Type: AWS::S3::Bucket
      Properties:
        BucketName: my-bucket-name
        # AccessControl: PublicRead
        # PublicAccessBlockConfiguration:
        #   BlockPublicAcls: false
        #   BlockPublicPolicy: false
        #   IgnorePublicAcls: false
        #   RestrictPublicBuckets: false

    PublicReadGetObject:
      Type: AWS::S3::BucketPolicy
      Properties: 
        Bucket:
          Ref: "WebImagesBucket"
        PolicyDocument:
          Statement:
            - Effect: Allow
              Sid: PublicReadGetObject
              Action:
                - 's3:GetObject'
              Resource:
                - 'arn:aws:s3:::my-bucket-name/*'
              Principal: "*"

I am creating the S3 bucket resource but creating the PublicReadGetObject policy fails with a 403:

CREATE_FAILED: PublicReadGetObject (AWS::S3::BucketPolicy)
Resource handler returned message: "Access Denied (Service: S3, Status Code: 403

Do I need to update the provider iam to have some other policy actions?

I tried using AccessControl but seems like that has been deprecated in favour of policy.

Any help on getting this working would be greatly appreciated. Thanks


Solution

  • This is probably related to account-level or default bucket-level Block Public Access. See Configuring Block Public Access. You will need to disable BPA if you want to put a bucket policy that allows public access.

    Also, note that s3:PutBucketPolicy is a bucket-level action, not object-level, so the ARN arn:aws:s3:::my-bucket-name/* is incorrect. It needs to be arn:aws:s3:::my-bucket-name, for example:

    provider:
      name: aws
      runtime: nodejs18.x
      timeout: 25
      iam:
        role:
          statements:
            - Effect: Allow
              Action:
                - 's3:GetObject'
              Resource:
                - 'arn:aws:s3:::my-bucket-name/*'
            - Effect: Allow
              Action:
                - 's3:PutBucketPolicy'
              Resource:
                - 'arn:aws:s3:::my-bucket-name'