CloudFormationを使ってS3とCloudFrontの構成で静的Webサイトを構築する（Origin Access Identityは使わない）

#はじめに
本記事では、AWS CloudFormation管理コンソールを使って、S3とCloudFrontで、静的Webサイトの環境を構築する手順を説明しています。（初心者向け）

また、CloudFrontのOriginの設定においては、<font color="Red">OAI（Origin Access Identity）を使わず、S3の静的Webサイトには、直接アクセスできる</font> 構成としています。
直接アクセスできない構成にしたい場合は、下記の記事を参考にしてください。
[CloudFormationを使ってS3とCloudFrontの構成で静的Webサイトを構築する（Origin Access Identityは使う）]
(https://qiita.com/okubot55/items/8d059a48bb5f22d3278b)

本記事で掲載しているテンプレートの最新版は、下記に置いてます。
https://github.com/okubo-t/aws-cloudformation
#構成図
<img src="https://qiita-image-store.s3.amazonaws.com/0/283246/93cef883-15b7-c640-69dc-a398161f5849.png"　 width=70%>

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

ACM管理コンソールで、CloudFrontに設定する証明書の識別子をメモしておく。
<img src="https://qiita-image-store.s3.amazonaws.com/0/283246/a704d076-8de1-9049-404f-9a756a3a939a.png"　 width=70%>

インデックスドキュメントは、index.html とする。
#構築手順
１ AWS CloudFormation管理コンソールから、スタックの作成をクリックします。
<img src="https://qiita-image-store.s3.amazonaws.com/0/283246/e0c3e7c3-f478-18c7-2dc2-7e669d1b399d.png"　 width=50%>

２ 後述のテンプレートを選択します。
<img src="https://qiita-image-store.s3.amazonaws.com/0/283246/060a4709-622a-2394-de5f-ac2103045137.png"　 width=50%>

３ 各パラメータを入力します。
<img src="https://qiita-image-store.s3.amazonaws.com/0/283246/a58b4953-5256-7a0e-24b6-77a54d43a3e8.png"　 width=50%>

|パラメータ名|用途|備考|
|:---|:---|:---|
|スタックの名前|テンプレートから作成するリソース一式の名前|例　s3-cf-web-20190226|
|WebsiteDomainName|静的Webサイトのドメイン名|必須 S3のバケット名となります|
|CFSSLCertificateId|前提条件でメモした証明書の識別子|必須|

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

５ 状況が CREATE COMPLETEになれば、S3とCloudFrontの構築が完了です。
<img src="https://qiita-image-store.s3.amazonaws.com/0/283246/f919b748-e62b-9f47-0eed-a3ab499405f0.png"　 width=50%>

6 管理コンソールの下部の出力から、構築した静的WebサイトのエンドポイントとCloudFrontの情報を確認できます。
  ここで、キーが、DomainNameとWebsiteURLの値をメモしておきます。
<img src="https://qiita-image-store.s3.amazonaws.com/0/283246/2c7a3845-96ca-6d52-d7ab-e932e2d20262.png"　 width=８0%>

7 確認のために、S3の管理コンソールから、バケット（バケット名はWebsiteDomainNameに設定した値）に、index.htmlファイルをアップロードします。
<img src="https://qiita-image-store.s3.amazonaws.com/0/283246/1c4d085f-ed59-3b3d-36c8-19d58b2f2c1e.png"　 width=80%>

８ ブラウザから、先ほどメモしたDomainNameの値にWebアクセス（CloudFrontにWebアクセス）して、index.htmlの内容が表示されれば、OKです。

また、WebsiteURLの値にWebアクセス（S3にWebアクセス）して、index.htmlの内容が表示されれば、OKです。

9 最後に、適宜、WebsiteDomainNameのCNAMEレコード（Route53の場合は、ALIASレコード）として、CloudFrontのドメイン名をDNSサーバ（Route53）に登録してください。

#テンプレート
```s3-cloudfront-web-hosting-01.yml
AWSTemplateFormatVersion: "2010-09-09"
Description: 
  S3 and CloudFront for Static website hosting (OAI Not available)

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

    ParameterLabels: 
      WebsiteDomainName: 
        default: "WebsiteDomainName"
      CFSSLCertificateId: 
        default: "CFSSLCertificateId"

# ------------------------------------------------------------#
# Input Parameters
# ------------------------------------------------------------# 
Parameters:
  WebsiteDomainName:
    Type: String

  CFSSLCertificateId:
    Type: String

Resources:
# ------------------------------------------------------------#
#  S3 Bucket
# ------------------------------------------------------------#        
# Bucket
  Bucket:
    Type: "AWS::S3::Bucket"
    Properties:
      BucketName: !Ref WebsiteDomainName
      AccessControl: PublicRead
      WebsiteConfiguration:
        IndexDocument: index.html

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

# ------------------------------------------------------------#
#  CloudFront
# ------------------------------------------------------------#  
  CloudFrontDistribution:
    Type: "AWS::CloudFront::Distribution"
    Properties:
      DistributionConfig:
        PriceClass: PriceClass_All
        Aliases:
        - !Ref WebsiteDomainName
        Origins:
        - CustomOriginConfig:
            OriginProtocolPolicy: http-only
          DomainName: !Sub "${WebsiteDomainName}.s3-website-${AWS::Region}.amazonaws.com"
          Id: !Sub "S3-Website-${WebsiteDomainName}.s3-website-ap-northeast-1.amazonaws.com"
        DefaultCacheBehavior:
          TargetOriginId: !Sub "S3-Website-${WebsiteDomainName}.s3-website-ap-northeast-1.amazonaws.com"
          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

# ------------------------------------------------------------#
# Output Parameters
# ------------------------------------------------------------#  
Outputs:
#WebsiteURL:
  WebsiteURL:
    Value: !GetAtt Bucket.WebsiteURL

#DistributionID
  DistributionID:
    Value: !Ref CloudFrontDistribution

#DmainName
  DomainName:
    Value: !GetAtt CloudFrontDistribution.DomainName
```