Search code examples
amazon-web-servicesamazon-s3yamlserverless-framework

Uploading static files to an S3 as part of a Serverless deploy


I'm extending an existing tool that runs as a bunch of lambdas. It has several components to it (sftp handling, RDS Postgres updates, etc) and a small UI element. The UI needs has a few pages that now need some shared JS added, you'd think that the simplest thing would be to serve it from a public folder. Of course, given this is a lambda, I thought the most reliable way would actually be to serve them from an S3 bucket, and upload them during the deployment. I'm using serverless to provision this whole ball of code.

Here's the top of my serverless.yml file:

service: myproject
frameworkVersion: "3"

provider:
  name: aws
  runtime: nodejs18.x
  region: eu-north-1
  iam:
    role:
      statements:
        - Effect: "Allow"
          Action:
            - "s3:*"
          Resource:
            - "arn:aws:s3:::myproject-input"
            - "arn:aws:s3:::myproject-input/*"
            - "arn:aws:s3:::myproject-static-assets"
            - "arn:aws:s3:::myproject-static-assets/*"
        - Effect: "Allow"
          Action:
            - "s3:CreateBucket"
            - "s3:PutBucketPolicy"
            - "s3:GetBucketPolicy"
            - "s3:DeleteBucketPolicy"
          Resource:
            - "arn:aws:s3:::myproject-input"
            - "arn:aws:s3:::myproject-static-assets"

package:
  individually: true

plugins:
  - serverless-s3-sync

custom:
  s3Sync:
    noSync: false
    buckets:
      - bucketName: myproject-static-assets
        bucketPrefix: public/
        localDir: public
        deleteRemoved: true

resources:
  Resources:
    AssetsBucket:
      Type: AWS::S3::Bucket
      Properties:
        BucketName: myproject-static-assets
    AssetsPolicy:
      Type: AWS::S3::BucketPolicy
      Properties:
        Bucket: myproject-static-assets
        PolicyDocument:
          Version: "2012-10-17"
          Statement:
            - Effect: "Allow"
              Principal: "*"
              Action:
                - "s3:GetObject"
              Resource:
                - "arn:aws:s3:::myproject-static-assets/*"

The S3 bucket is created, and then I get this Serverless error:

CREATE_FAILED: AssetsPolicy (AWS::S3::BucketPolicy) Resource handler returned message: "Access Denied (Service: S3, Status Code: 403, Request ID: 4M61DWVFAM566RS8, Extended Request ID: xxxxxx/xxxxxxxxxxxxxxxxxxxxx+bcRMWf9x9iUg=)" (RequestToken: xxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx, HandlerErrorCode: AccessDenied)

Is this something wrong in the YAML, or is this a permission higher up?


Solution

  • Thanks to SAE's helpful pointer, I managed to bodge together this replacement addendum to the serverless.yaml file, which does the trick:

    
    #  ....existing file..... 
    
    plugins:
      - serverless-s3-sync
    
    custom:
      s3Sync:
        noSync: false
        buckets:
          - bucketName: myproject-static-assets
            bucketPrefix: /
            localDir: public
            deleteRemoved: true
    
    resources:
      Resources:
        AssetsBucket:
          Type: AWS::S3::Bucket
          Properties:
            BucketName: myproject-static-assets
            PublicAccessBlockConfiguration:
              BlockPublicPolicy: false
              RestrictPublicBuckets: false
        AssetsPolicy:
          Type: AWS::S3::BucketPolicy
          Properties:
            Bucket: myproject-static-assets
            PolicyDocument:
              Version: "2012-10-17"
              Statement:
                - Effect: "Allow"
                  Principal: "*"
                  Action:
                    - "s3:GetObject"
                  Resource:
                    - "arn:aws:s3:::myproject-static-assets/*"