getlift / lift

Expanding Serverless Framework beyond functions using the AWS CDK
MIT License
912 stars 111 forks source link

static-site construct will not deploy #320

Closed ktwbc closed 2 months ago

ktwbc commented 1 year ago

Description

As of April 2023, the default security on an S3 bucket is to Block Public access. This creates a conflict with the native behavior of the static-site construct which sets a Policy s3:GetObject using AWS:"*" as the Principle. The deployment will fail with an API: Access Denied error when using this with lift and serverless.

How to Reproduce

1

Additional Information

No response

joconor commented 1 year ago

I'm also running into this. 100% fatal issue for the static-website construct

ktwbc commented 1 year ago

single-page-app will work as a workaround for now

mnapoli commented 1 year ago

Thanks for the report, anyone has a good suggestion for a solution/PR?

joconor commented 1 year ago

FYI, it looks like this is Amazon's announcement of the change in default policy: Advanced Notice: Amazon S3 will automatically enable S3 Block Public Access and disable access control lists for all new buckets starting in April 2023

The exact error that occurs is API: s3:PutBucketPolicy Access Denied while creating the webBucketPolicy for the publicly accessible web bucket.

I wish I could suggest a solution, but I'm afraid that at this time, the problem exceeds the limits of my AWS policy/permissions knowledge. Of course, this is a big reason why I use Serverless Framework & serverless-lift.

peebam commented 1 year ago

Workaround : you can disable the BlocPublicPolicy with the PublicAccessBlockConfiguration property of the S3 bucket CloudFormation structure. Use the extension property of your Lift construct :

extensions: {
  bucket: {
    Properties: {
      PublicAccessBlockConfiguration: {
        BlockPublicPolicy: false,
      },
    },
  },
},
joconor commented 1 year ago

@peebam Since the bucket is created by serverless-lift, how do you know the BucketName?

peebam commented 1 year ago

The BuckName property is not mandatory. In this extract of code, we manage the bucket name. I fixed my comment.

joconor commented 1 year ago

@peebam Thanks for that workaround! Looks like that's working

hacknaked commented 1 year ago

Workaround : you can disable the BlocPublicPolicy with the PublicAccessBlockConfiguration property of the S3 bucket CloudFormation structure. Use the extension property of your Lift construct :

extensions: {
  bucket: {
    Properties: {
      PublicAccessBlockConfiguration: {
        BlockPublicPolicy: false,
      },
    },
  },
},

(dummy question here) Where should I put this snippet? I guess is not in serverless.yml given that is not in yml format.

raffclar commented 1 year ago

Workaround : you can disable the BlocPublicPolicy with the PublicAccessBlockConfiguration property of the S3 bucket CloudFormation structure. Use the extension property of your Lift construct :

extensions: {
  bucket: {
    Properties: {
      PublicAccessBlockConfiguration: {
        BlockPublicPolicy: false,
      },
    },
  },
},

(dummy question here) Where should I put this snippet? I guess is not in serverless.yml given that is not in yml format.

Like so:

constructs:
  landing:
    type: static-website
    path: public
    extensions:
      bucket:
        Properties:
          PublicAccessBlockConfiguration:
            BlockPublicPolicy: false
InvisibleKind commented 10 months ago

For me even the suggested snippet doesn't help. The basic static-website construct fails with a message:

Error:
CREATE_FAILED: buildpublicBucketHASH (AWS::S3::Bucket)
Resource handler returned message: "Access Denied (Service: S3, Status Code: 403, Request ID: -cut-, Extended Request ID: -cut-)" (RequestToken: -cut-, HandlerErrorCode: GeneralServiceException)

The serverless user is allowed to create S3 Buckets, of course. Moreover, if I change the static-website to single-page-app, no error appears and deploy works in a normal way.

sean-ac commented 8 months ago

The issue is here:

https://github.com/getlift/lift/blob/a91e293dcd889b3d0153444ed0b55afea470822f/src/constructs/aws/StaticWebsite.ts#L67-L77

This object needs to now return a BlockPublicAccess object, with every field set to false.

Docs: https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3.BlockPublicAccess.html

Example:

      blockPublicAccess: new BlockPublicAccess({
        blockPublicAcls: false,
        blockPublicPolicy: false,
        ignorePublicAcls: false,
        restrictPublicBuckets: false
      })

(You will need to import BlockPublicAccess from aws-cdk-lib/aws-s3)

I solved this by doing a local patch (via yarn patch serverless-lift), and modifying the .js files directly.

kevincerro-dvrv commented 6 months ago

I will try to fix this on a PR

richard-stafflink commented 3 months ago

The latest update of aws-cdk-lib v2.144.0 now checks this and breaks.

rj-xy commented 3 months ago

The latest update of aws-cdk-lib v2.144.0 now checks this and breaks.

An update on this: the latest aws-cdk-lib package has had an update, so now even single-page-app will not work.

@mnapoli are there plans of updating the new defaults required when creating the bucket?

I'm happy to help with the change/update to resolve this, if you provide some direction.

ATM the only workarounds are:

  1. Using the extensions example above - preferred
  2. Pin package.json resolution version for aws-cdk-lib (not desirable)
  3. Yarn patch - not convenient
  4. Use one of the forked versions of this lib - not ideal long term
mnapoli commented 3 months ago

Please confirm if https://github.com/getlift/lift/pull/384 fixes the problem.

kizza commented 2 months ago

Please confirm if https://github.com/getlift/lift/pull/384 fixes the problem.

Happy to confirm it does indeed 🎈 My static-website construct was raising the following during deployment:

Error: Cannot use 'publicReadAccess' property on a bucket without allowing bucket-level public access through 'blockPublicAceess' property.

Which while not the precise error ("Access denied" above, seems to be the same problem). It deployed perfectly using yarn link serverless-lift to @kevincerro's https://github.com/getlift/lift/pull/384 locally

I'll use this brief opportunity to say thank you @mnapoli - this repo has been awesome to discover 🙏

ktwbc commented 2 months ago

yes worked for me as well.