k1LoW / serverless-static-hosting-with-basic-auth

Serverless boilerplate for Static website hosting with Basic authentication
21 stars 8 forks source link

Does this still work? #4

Closed timoaudi closed 1 year ago

timoaudi commented 1 year ago

Last commit is 4 years ago but I wanted to give this a shot anyway. Got pretty far but when trying to deploy, I get this:

Serverless: Packaging service...
Serverless: Excluding development dependencies...
Serverless: Updated Lambda assume role policy to allow Lambda@Edge to assume the role
Serverless: Removing 1 environment variables from function "BasicAuthLambdaFunction" because Lambda@Edge does not support environment variables
Serverless: Creating Stack...
Serverless: Checking Stack create progress...
CloudFormation - CREATE_IN_PROGRESS - AWS::CloudFormation::Stack - my-bucket
CloudFormation - CREATE_IN_PROGRESS - AWS::S3::Bucket - ServerlessDeploymentBucket
CloudFormation - CREATE_IN_PROGRESS - AWS::S3::Bucket - ServerlessDeploymentBucket
CloudFormation - CREATE_COMPLETE - AWS::S3::Bucket - ServerlessDeploymentBucket
CloudFormation - CREATE_IN_PROGRESS - AWS::S3::BucketPolicy - ServerlessDeploymentBucketPolicy
CloudFormation - CREATE_IN_PROGRESS - AWS::S3::BucketPolicy - ServerlessDeploymentBucketPolicy
CloudFormation - CREATE_COMPLETE - AWS::S3::BucketPolicy - ServerlessDeploymentBucketPolicy
CloudFormation - CREATE_COMPLETE - AWS::CloudFormation::Stack - my-bucket
Serverless: Stack create finished...
Serverless: Uploading CloudFormation file to S3...
Serverless: Uploading artifacts...
Serverless: Uploading service my-bucket.zip file to S3 (56.13 MB)...
Serverless: Validating template...
Serverless: Updating Stack...
Serverless: Checking Stack update progress...
CloudFormation - UPDATE_IN_PROGRESS - AWS::CloudFormation::Stack - my-bucket
CloudFormation - CREATE_IN_PROGRESS - AWS::IAM::Role - IamRoleLambdaExecution
CloudFormation - CREATE_IN_PROGRESS - AWS::S3::Bucket - WebsiteBucket
CloudFormation - CREATE_IN_PROGRESS - AWS::CloudFront::CloudFrontOriginAccessIdentity - WebsiteOriginAccessIdentity
CloudFormation - CREATE_IN_PROGRESS - AWS::Logs::LogGroup - BasicAuthLogGroup
CloudFormation - CREATE_IN_PROGRESS - AWS::IAM::Role - IamRoleLambdaExecution
CloudFormation - CREATE_FAILED - AWS::S3::Bucket - WebsiteBucket
CloudFormation - CREATE_FAILED - AWS::IAM::Role - IamRoleLambdaExecution
CloudFormation - CREATE_FAILED - AWS::Logs::LogGroup - BasicAuthLogGroup
CloudFormation - CREATE_FAILED - AWS::CloudFront::CloudFrontOriginAccessIdentity - WebsiteOriginAccessIdentity
CloudFormation - UPDATE_ROLLBACK_IN_PROGRESS - AWS::CloudFormation::Stack - my-bucket
CloudFormation - UPDATE_ROLLBACK_COMPLETE_CLEANUP_IN_PROGRESS - AWS::CloudFormation::Stack - my-bucket
CloudFormation - DELETE_IN_PROGRESS - AWS::Logs::LogGroup - BasicAuthLogGroup
CloudFormation - DELETE_IN_PROGRESS - AWS::CloudFront::CloudFrontOriginAccessIdentity - WebsiteOriginAccessIdentity
CloudFormation - DELETE_IN_PROGRESS - AWS::IAM::Role - IamRoleLambdaExecution
CloudFormation - DELETE_COMPLETE - AWS::S3::Bucket - WebsiteBucket
CloudFormation - DELETE_COMPLETE - AWS::Logs::LogGroup - BasicAuthLogGroup
CloudFormation - DELETE_COMPLETE - AWS::CloudFront::CloudFrontOriginAccessIdentity - WebsiteOriginAccessIdentity
CloudFormation - DELETE_COMPLETE - AWS::IAM::Role - IamRoleLambdaExecution
CloudFormation - UPDATE_ROLLBACK_COMPLETE - AWS::CloudFormation::Stack - my-bucket

Serverless: Operation failed!
An error occurred: WebsiteBucket - Bad Request (Service: Amazon S3; Status Code: 400; Error Code: 400 Bad Request).

This is what my configuration looks like:

service: ${self:provider.environment.WEBSITE_S3_BUCKET_NAME}

provider:
  name: aws
  runtime: nodejs6.10

  stage: dist
  region: us-east-1 # Lambda@Edge function must be us-east-1

  environment:
    WEBSITE_S3_BUCKET_NAME: ${env:WEBSITE_S3_BUCKET_NAME, 'my-bucket'}

plugins:
  - serverless-plugin-cloudfront-lambda-edge
  - serverless-s3-sync

custom:
  s3Sync:
    - bucketName: ${self:provider.environment.WEBSITE_S3_BUCKET_NAME}
      localDir: files

package:
  exclude:
    - src/*
    - package.json

functions:
  basicAuth:
    name: "${self:provider.environment.WEBSITE_S3_BUCKET_NAME}-viewer-request"
    handler: handler.basicAuth
    memorySize: 128
    timeout: 1
    lambdaAtEdge:
      distribution: WebsiteDistribution
      eventType: "viewer-request"

resources:
  Resources:
    WebsiteBucket:
      Type: AWS::S3::Bucket
      Properties:
        BucketName: ${self:provider.environment.WEBSITE_S3_BUCKET_NAME}
        AccessControl: Private
        WebsiteConfiguration:
          IndexDocument: index.html
          ErrorDocument: error.html
    WebsiteBucketPolicy:
      Type: AWS::S3::BucketPolicy
      Properties:
        Bucket: { Ref: WebsiteBucket }
        PolicyDocument:
          Statement:
            - Action:
                - "s3:GetObject"
              Effect: Allow
              Resource:
                {
                  "Fn::Join":
                    ["", ["arn:aws:s3:::", { Ref: WebsiteBucket }, "/*"]],
                }
              Principal:
                AWS:
                  {
                    "Fn::Join":
                      [
                        " ",
                        [
                          "arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity",
                          { Ref: WebsiteOriginAccessIdentity },
                        ],
                      ],
                  }
    WebsiteOriginAccessIdentity:
      Type: AWS::CloudFront::CloudFrontOriginAccessIdentity
      Properties:
        CloudFrontOriginAccessIdentityConfig:
          Comment: "CloudFrontOriginAccessIdentity for ${self:service}-${self:provider.stage}"
    WebsiteDistribution:
      Type: AWS::CloudFront::Distribution
      Properties:
        DistributionConfig:
          DefaultCacheBehavior:
            AllowedMethods:
              ["DELETE", "GET", "HEAD", "OPTIONS", "PATCH", "POST", "PUT"]
            CachedMethods: ["GET", "HEAD", "OPTIONS"]
            TargetOriginId: WebsiteBucketOrigin
            ViewerProtocolPolicy: redirect-to-https
            DefaultTTL: 0
            MaxTTL: 0
            MinTTL: 0
            Compress: true
            ForwardedValues:
              QueryString: true
              Cookies:
                Forward: "all"
          CustomErrorResponses:
            - ErrorCode: "403"
              ErrorCachingMinTTL: 1
            - ErrorCode: "404"
              ErrorCachingMinTTL: 1
            - ErrorCode: "500"
              ErrorCachingMinTTL: 1
            - ErrorCode: "502"
              ErrorCachingMinTTL: 1
            - ErrorCode: "503"
              ErrorCachingMinTTL: 1
            - ErrorCode: "504"
              ErrorCachingMinTTL: 1
          DefaultRootObject: "index.html"
          Enabled: true
          PriceClass: "PriceClass_100"
          HttpVersion: "http2"
          ViewerCertificate:
            CloudFrontDefaultCertificate: true
          Origins:
            - Id: "WebsiteBucketOrigin"
              DomainName: { "Fn::GetAtt": [WebsiteBucket, DomainName] }
              S3OriginConfig:
                OriginAccessIdentity:
                  {
                    "Fn::Join":
                      [
                        "",
                        [
                          "origin-access-identity/cloudfront/",
                          { Ref: WebsiteOriginAccessIdentity },
                        ],
                      ],
                  }
  Outputs:
    WebsiteURL:
      Value:
        {
          "Fn::Join":
            [
              "",
              ["https://", { "Fn::GetAtt": [WebsiteDistribution, DomainName] }],
            ],
        }
      Description: "URL for website via CloudFront"

Any advice how to get this to work or any suggestions for alternatives how to easily setup basic authentication for an S3 bucket without it being too much rocket science? Thanks 🙂

k1LoW commented 1 year ago

Hmmm, I think it may not work now. The essence is to run basicAuth() with Lambda@Edge, so you may as well try that.

timoaudi commented 1 year ago

Thanks @k1LoW will give that a shot. I also found this which looks like a bit of manual clicking work but definitely doable: https://www.golinuxcloud.com/protect-s3-bucket-with-basic-authentication/#Step_1_Create_S3_bucket