Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Attach bucket policy to bucket generated by serverless

I'm attempting to create an S3 bucket with serverless, which works, however in order to manipulate files in it I need a bucket policy. I'm having a hard time understanding where and how to add a policy that uses the generated S3bucket name created when serverless deploys for the first time

##serverless.yml##

service: vcc-nametags-api

# Use the serverless-webpack plugin to transpile ES6
plugins:
  - serverless-webpack
  - serverless-offline
  - serverless-ding

# serverless-webpack configuration
# Enable auto-packing of external modules
custom:
  # Our stage is based on what is passed in when running serverless
  # commands. Or fallsback to what we have set in the provider section.
  stage: ${opt:stage, self:provider.stage}
  # Set our DynamoDB throughput for prod and all other non-prod stages.
  # Load our webpack config
  webpack:
    webpackConfig: ./webpack.config.js
    includeModules: true
  environment: ${file(env.yml):${self:custom.stage}, file(env.yml):default}

provider:
  name: aws
  runtime: nodejs8.10
  stage: dev
  region: us-east-1

  # These environment variables are made available to our functions
  # under process.env.
  environment:
    S3DBBucketName:
      Ref: NametagsDatabaseBucket

functions:
  # Defines an HTTP API endpoint that calls the main function in create.js
  # - path: url path is /tags
  # - method: POST request
  # - cors: enabled CORS (Cross-Origin Resource Sharing) for browser cross
  #     domain api call
  # - authorizer: authenticate using the AWS IAM role
  create:
    handler: create.main
    events:
      - http:
          path: tags
          method: post
          cors: true

  get:
    # Defines an HTTP API endpoint that calls the main function in get.js
    # - path: url path is /tags/{id}
    # - method: GET request
    handler: get.main
    events:
      - http:
          path: tags/{id}
          method: get
          cors: true

  list:
    # Defines an HTTP API endpoint that calls the main function in list.js
    # - path: url path is /tags
    # - method: GET request
    handler: list.main
    events:
      - http:
          path: tags
          method: get
          cors: true

  update:
    # Defines an HTTP API endpoint that calls the main function in update.js
    # - path: url path is /tags/{id}
    # - method: PUT request
    handler: update.main
    events:
      - http:
          path: tags/{id}
          method: put
          cors: true

  delete:
    # Defines an HTTP API endpoint that calls the main function in delete.js
    # - path: url path is /tags/{id}
    # - method: DELETE request
    handler: delete.main
    events:
      - http:
          path: tags/{id}
          method: delete
          cors: true
# Create our resources with separate CloudFormation templates
resources:
  # S3DB
  - ${file(resources/s3-database.yml)}

##s3-database.yml##

Resources:
  NametagsDatabaseBucket:
    Type: AWS::S3::Bucket
    Properties:
      # Set the CORS policy
      CorsConfiguration:
        CorsRules:
          -
            AllowedOrigins:
              - '*'
            AllowedHeaders:
              - '*'
            AllowedMethods:
              - GET
              - PUT
              - POST
              - DELETE
              - HEAD
            MaxAge: 3000
  NametagsDatabaseBucketPolicy:
    Type: AWS::S3::BucketPolicy
    Properties:
      Bucket:
        Ref: NametagsDatabaseBucket
      PolicyDocument:
        Statement:
          - Sid: PublicReadGetObject
            Effect: Allow
            Principal: "*"
            Action:
            - "s3:DeleteObject"
            - "s3:GetObject"
            - "s3:ListBucket"
            - "s3:PutObject"
            Resource:
              Fn::Join: [
                "", [
                  "arn:aws:s3:::",
                  {
                    "Ref": "NametagsDatabaseBucket"
                  },
                  "/*"
                ]
              ]

# Print out the name of the bucket that is created
Outputs:
  NametagsDatabaseBucketName:
    Value:
      Ref: NametagsDatabaseBucket

I've tried various combinations I've found on the internet as well as adding it to an iamroles property in the serverless.yml file but I can't seem to get anything to work

like image 208
Jordan Avatar asked Aug 08 '18 17:08

Jordan


People also ask

How do you attach a policy to a bucket?

To create or edit a bucket policyIn the Buckets list, choose the name of the bucket that you want to create a bucket policy for or whose bucket policy you want to edit. Choose Permissions. Under Bucket policy, choose Edit. This opens the Edit bucket policy page.

Can you attach multiple policies to an S3 bucket?

Multiple IAM policies can be attached to the same IAM user. In one of the policies, let's say the user is given access to a S3 Bucket and in another policy the user is denied to the same S3 Bucket.

How do I add a bucket policy to CDK?

There are 2 ways to create a bucket policy in AWS CDK:use the addToResourcePolicy method on an instance of the Bucket class. instantiate the BucketPolicy class.

What is the difference between S3 ACL and bucket policy?

The biggest advantage of using ACL is that you can control the access level of not only buckets but also of an object using it. Whereas IAM or Bucket Policies can only be attached to buckets but not to objects in the bucket, Bucket ACLs can be assigned to buckets as well as objects in it.


1 Answers

The Resource Reference Name seems to matter, I have always had to use the name of the bucket in the resource name. For example, a bucket with www.example.com needs a reference name of S3BucketWwwexamplecom.

However I also notice that the BucketName element is missing from your example.

This is from working example for a static website with a Bucket Policy:

resources:
  Resources:
    S3BucketWwwexamplecom:
      Type: AWS::S3::Bucket
      DeletionPolicy: Delete
      Properties:
        BucketName: ${self:custom.s3WwwBucket}
        CorsConfiguration:
          CorsRules:
            - AllowedMethods:
                - PUT
                - GET
                - POST
                - HEAD
              AllowedOrigins:
                - "https://${self:custom.myDomain}"
              AllowedHeaders:
                - "*"
        AccessControl: PublicRead
        WebsiteConfiguration:
          IndexDocument: index.html
    BucketPolicyWwwexamplecom:
      Type: 'AWS::S3::BucketPolicy'
      Properties:
        PolicyDocument:
          Statement:
            - Sid: PublicReadForGetBucketObjects
              Effect: Allow
              Principal: '*'
              Action:
                - 's3:GetObject'
              Resource: arn:aws:s3:::${self:custom.s3WwwBucket}/*
        Bucket:
          Ref: S3BucketWwwexamplecom
like image 181
Matt D Avatar answered Sep 19 '22 07:09

Matt D