AWS
S3
CloudFormation
CloudFront

CloudFormationを使ってS3とCloudFrontの構成でSorryページを表示する環境を構築する

はじめに

本記事では、AWS CloudFormation管理コンソールを使って、S3とCloudFrontでSorryページを表示する環境を構築する手順を説明しています。(初心者向け)

本記事で掲載しているテンプレートの最新版は、下記に置いてます。
https://github.com/okubo-t/aws-cloudformation

構成図

前提条件

CloudFrontに設定するSSLサーバ証明書を、リージョンがバージニア北部のAWS Certificate Manager(ACM)にインポートしていること。

ACM管理コンソールで、CloudFrontに設定する証明書の識別子をメモしておく。

構築手順

1 AWS CloudFormation管理コンソールから、スタックの作成をクリックします。

2 後述のテンプレートを選択します。

3 各パラメータを入力します。

パラメータ名 用途 備考
スタックの名前 テンプレートから作成するリソース一式の名前 例 prd-stack-vpc-20180801
BucketName Sorryページを配置するバケット名 必須
CName01 CloudFrontに設定するCNAME 任意
CName02 CloudFrontに設定するCNAME(2つ以上ある場合) 任意
CFSSLCertificateId 前提条件でメモした証明書の識別子 必須

4 後続は、デフォルトのまま次へ次へで、作成します。

5 状況が CREATE COMPLETEになれば、S3とCloudFrontの構築が完了です。

6 管理コンソールの下部の出力から、構築したS3バケットとCloudFrontの情報を確認できます。
  ここで、キーがDomainNameの値をメモしておきます。

7 S3の管理コンソールから、パラメータに設定したバケットに、Sorryページの内容を記載したindex.htmlファイルをアップロードします。

8 ブラウザから、先ほどメモしたDomainNameの値にWebアクセスして、
Sorryページの内容が表示されれば、OKです。(されない場合は、5分程度待ってから確認してみて下さい。)

テンプレート

s3-cloudfront-sorry.yml
AWSTemplateFormatVersion: "2010-09-09"
Description: 
  S3 and CloudFront for Sorry Page Create

Metadata:
  "AWS::CloudFormation::Interface":
    ParameterGroups:
      - Label: 
          default: "S3 and CloudFront Configuration"
        Parameters: 
          - BucketName
          - CName01
          - CName02
          - CFSSLCertificateId

    ParameterLabels: 
      BucketName: 
        default: "BucketName"
      CName01:
        default: "CName01"
      CName02:
        default: "CName02"
      CFSSLCertificateId: 
        default: "CFSSLCertificateId"

# ------------------------------------------------------------#
# Input Parameters
# ------------------------------------------------------------# 
Parameters:
  BucketName:
    Type: String

  CName01:
    Type: String
    Default: ""

  CName02:
    Type: String
    Default: ""

  CFSSLCertificateId:
    Type: String

Conditions:
  IsCName01: !Not [!Equals [!Ref CName01, ""]]
  IsCName02: !Not [!Equals [!Ref CName02, ""]]

Resources:
# ------------------------------------------------------------#
#  S3 Bucket
# ------------------------------------------------------------#        
# Bucket
  Bucket:
    Type: "AWS::S3::Bucket"
    Properties:
      BucketName: !Ref BucketName

  CloudFrontOriginAccessIdentity:
    Type: "AWS::CloudFront::CloudFrontOriginAccessIdentity"
    Properties:
      CloudFrontOriginAccessIdentityConfig:
        Comment: !Sub "access-identity-${Bucket}"

  BucketPolicy:
    Type: "AWS::S3::BucketPolicy"
    Properties:
      Bucket: !Ref Bucket
      PolicyDocument:
        Statement:
        - Action: "s3:GetObject"
          Effect: Allow
          Resource: !Sub "arn:aws:s3:::${Bucket}/*"
          Principal:
            CanonicalUser: !GetAtt CloudFrontOriginAccessIdentity.S3CanonicalUserId

# ------------------------------------------------------------#
#  CloudFront
# ------------------------------------------------------------#  
  CloudFrontDistribution:
    Type: "AWS::CloudFront::Distribution"
    Properties:
      DistributionConfig:
        PriceClass: PriceClass_All
        Aliases:
        - !If [IsCName01, !Ref CName01, !Ref "AWS::NoValue"]
        - !If [IsCName02, !Ref CName02, !Ref "AWS::NoValue"]
        Origins:
        - DomainName: !GetAtt Bucket.DomainName
          Id: !Sub "S3origin-${BucketName}"
          S3OriginConfig:
            OriginAccessIdentity: !Sub "origin-access-identity/cloudfront/${CloudFrontOriginAccessIdentity}"

        DefaultCacheBehavior:
          TargetOriginId: !Sub "S3origin-${BucketName}"
          ViewerProtocolPolicy: redirect-to-https
          AllowedMethods:
          - GET
          - HEAD
          CachedMethods:
          - GET
          - HEAD
          DefaultTTL: 3600
          MaxTTL: 86400
          MinTTL: 60
          Compress: true
          ForwardedValues:
            Cookies:
              Forward: none
            QueryString: false
        ViewerCertificate:
          SslSupportMethod: sni-only
          MinimumProtocolVersion: TLSv1.1_2016
          AcmCertificateArn: !Sub "arn:aws:acm:us-east-1:${AWS::AccountId}:certificate/${CFSSLCertificateId}"
        HttpVersion: http2
        Enabled: true
        CustomErrorResponses:
        - ErrorCode: 403
          ErrorCachingMinTTL: 30
          ResponsePagePath: /index.html
          ResponseCode: 503

# ------------------------------------------------------------#
# Output Parameters
# ------------------------------------------------------------#  
Outputs:
#BucketName
  BucketName:
    Value: !Ref Bucket

#DistributionID
  DistributionID:
    Value: !Ref CloudFrontDistribution

#DmainName
  DomainName:
    Value: !GetAtt CloudFrontDistribution.DomainName