Open5

CloudFront + S3 で静的ページをホストするための Serverless Framework 設定

雪猫雪猫

S3 Bucket 作成

serverless.yml
resources:
  Resources:
    S3Bucket:
      Type: AWS::S3::Bucket
      Properties:
        BucketName: ${self:service}-${sls:stage}-example
雪猫雪猫

S3 へデプロイ

Serverless S3 Sync プラグインを使う。

https://www.serverless.com/plugins/serverless-s3-sync

インストール

CLI
serverless plugin install --name serverless-s3-sync

or

CLI
npm install --save-dev serverless-s3-sync

コード

serverless.yml
plugins:
  - serverless-s3-sync

custom:
  s3Sync:
    - bucketName: ${self:service}-${sls:stage}-example
      localDir: public
public/index.html
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Example</title>
  </head>
  <body>
    <h1>Example</h1>
  </body>
</html>

デプロイ

CLI
serverless deploy

public/index.html が S3 へアップロードされる。
この時点ではオブジェクト URL にアクセスしても Access Denied になる。
CloudFront を通した公開設定は後述。

雪猫雪猫

CloudFront からのアクセスのみ許可

2 種類ある。

  • Origin Access Control (OAC) 推奨
  • Origin Access Identity (OAI) レガシー

https://docs.aws.amazon.com/ja_jp/AmazonCloudFront/latest/DeveloperGuide/private-content-restricting-access-to-s3.html
https://aws.amazon.com/jp/blogs/news/amazon-cloudfront-introduces-origin-access-control-oac/
https://dev.classmethod.jp/articles/amazon-cloudfront-origin-access-control/

Origin Access Control

https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-cloudfront-originaccesscontrol.html
https://dev.classmethod.jp/articles/cloudfront_s3_oac_setup_with_cloudformation/

オリジンアクセス

serverless.yml
resources:
  Resources:
    CloudFrontOriginAccessControl:
      Type: AWS::CloudFront::OriginAccessControl
      Properties:
        OriginAccessControlConfig:
          Name: OriginAccessControl
          OriginAccessControlOriginType: s3
          SigningBehavior: always
          SigningProtocol: sigv4

ディストリビューション

serverless.yml
resources:
  Resources:
    CloudFrontDistribution:
      Type: AWS::CloudFront::Distribution
      Properties:
        DistributionConfig:
          Enabled: true
          Origins:
            - Id: S3Origin
              DomainName:
                Fn::Join:
                  - '.'
                  - - Ref: S3Bucket
                    - s3
                    - Ref: AWS::Region
                    - Ref: AWS::URLSuffix
              OriginAccessControlId:
                Ref: CloudFrontOriginAccessControl
              S3OriginConfig: # required
                OriginAccessIdentity: ''
          DefaultCacheBehavior:
            TargetOriginId: S3Origin
            ViewerProtocolPolicy: https-only
            ForwardedValues:
              QueryString: false
          DefaultRootObject: index.html

バケットポリシー

serverless.yml
resources:
  Resources:
    S3BucketPolicy:
      Type: AWS::S3::BucketPolicy
      Properties:
        Bucket:
          Ref: S3Bucket
        PolicyDocument:
          Version: '2012-10-17'
          Statement:
            - Action:
                - s3:GetObject
              Effect: Allow
              Resource:
                Fn::Sub: ${S3Bucket.Arn}/*
              Principal:
                Service:
                  - cloudfront.amazonaws.com
              Condition:
                StringEquals:
                  AWS:SourceArn:
                    Fn::Sub: arn:aws:cloudfront::${AWS::AccountId}:distribution/${CloudFrontDistribution}

Origin Access Identity

非推奨
serverless.yml
resources:
  Resources:
    CloudFrontOriginAccessIdentity:
      Type: AWS::CloudFront::CloudFrontOriginAccessIdentity
      Properties:
        CloudFrontOriginAccessIdentityConfig:
          Comment: OriginAccessIdentity