AWS CloudFormationで独自ドメインホスティング環境構築を自動化してみた

![img](https://day-journal.com/memo/images/try-084_00.png)

### AWS CloudFormationで独自ドメインホスティング環境構築を自動化してみました :tada:  

<br>

以前の記事内容をAWS CloudFormationで実現する方法をためしてみました！

https://qiita.com/dayjournal/items/945613577b3056ec4f71

<br>

今回の作成したテンプレートをGitHubで公開したのでぜひご利用ください！

https://github.com/dayjournal/aws-cloudformation-templates-showcase

#### certificate-create.yml

```yaml
AWSTemplateFormatVersion: 2010-09-09
# テンプレート概要
Description: Certificate creation
# パラメータ
Parameters:
  # ドメイン名入力
  DomainName:
    Description: Domain Name
    Type: String
  # ホストゾーンID入力
  HostedZoneId:
    Description: Host Zone ID
    Type: String
# リソース
Resources:
  # Certificate Manager設定
  CertificateManagerCertificate:
    # リソースタイプ
    Type: AWS::CertificateManager::Certificate
    # プロパティ
    Properties:
      # ドメイン指定
      DomainName: !Sub ${DomainName}
      # 検証ドメイン設定
      DomainValidationOptions:
        -
          # ドメイン指定
          DomainName: !Sub ${DomainName}
          # ホストゾーンID指定
          HostedZoneId: !Sub ${HostedZoneId}
      # 検証方法指定
      ValidationMethod: DNS
```

#### hosting.yml

```yaml
AWSTemplateFormatVersion: 2010-09-09
# テンプレート概要
Description: Build a Unique Domain Hosting Environment with Amazon Route 53, Amazon CloudFront, and Amazon S3
# パラメータ
Parameters:
  # ドメイン名入力
  DomainName:
    Description: Domain Name
    Type: String
  # ホストゾーンID入力
  HostedZoneId:
    Description: Host Zone ID
    Type: String
  # 証明書ID入力
  CertificateId:
    Description: Certificate ID
    Type: String
# リソース
Resources:
  # S3バケット設定
  S3Bucket:
    # リソースタイプ
    Type: AWS::S3::Bucket
      # プロパティ
    Properties:
      # バケット名指定
      BucketName: !Sub ${AWS::StackName}-${AWS::Region}-${AWS::AccountId}
  # S3バケットポリシー設定
  S3BucketPolicy:
    # リソースタイプ
    Type: AWS::S3::BucketPolicy
    # 処理順設定
    DependsOn:
      - CloudFrontOriginAccessIdentity
    # プロパティ
    Properties:
      # S3バケット指定
      Bucket: !Sub ${S3Bucket}
      # CloudFront用バケットポリシー指定
      PolicyDocument:
        Statement:
          -
            Sid: PolicyForCloudFrontPrivateContent
            Effect: Allow
            Principal:
              AWS: !Sub arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity ${CloudFrontOriginAccessIdentity}
            Action: s3:GetObject
            Resource: !Sub arn:aws:s3:::${S3Bucket}/*
  # CloudFrontOAI設定
  CloudFrontOriginAccessIdentity:
    # リソースタイプ
    Type: AWS::CloudFront::CloudFrontOriginAccessIdentity
    # プロパティ
    Properties:
      CloudFrontOriginAccessIdentityConfig:
        Comment: Unique Domain Hosting Environment
  # CloudFront設定
  CloudFrontDistribution:
    # リソースタイプ
    Type: AWS::CloudFront::Distribution
    # 処理順設定
    DependsOn:
      - S3Bucket
      - CloudFrontOriginAccessIdentity
    # プロパティ
    Properties:
      DistributionConfig:
        # ドメイン指定
        Aliases:
          - !Sub ${DomainName}
        Origins:
          -
            # S3ドメイン名指定
            DomainName: !Sub ${S3Bucket}.s3.${AWS::Region}.amazonaws.com
            # オリジン名指定
            Id: !Sub ${S3Bucket}.s3.${AWS::Region}.amazonaws.com
            # オリジンアクセスアイデンティティ指定
            S3OriginConfig:
              OriginAccessIdentity: !Sub origin-access-identity/cloudfront/${CloudFrontOriginAccessIdentity}
        # キャッシュビヘイビア設定
        DefaultCacheBehavior:
          # オリジンID指定
          TargetOriginId: !Sub ${S3Bucket}.s3.${AWS::Region}.amazonaws.com
          # 自動圧縮有無指定
          Compress: true
          # HTTPメソッド指定
          AllowedMethods:
            - HEAD
            - GET
          CachedMethods:
            - HEAD
            - GET
          # ビューアプロトコルポリシー指定
          ViewerProtocolPolicy: redirect-to-https
          # キャッシュポリシー指定 (CachingOptimized)
          CachePolicyId: 658327ea-f89d-4fab-a63d-7e88639e58f6
        # SPA対応設定
        CustomErrorResponses:
          -
            ErrorCode: 403
            ResponsePagePath: /index.html
            ResponseCode: 200
            ErrorCachingMinTTL: 0
          -
            ErrorCode: 404
            ResponsePagePath: /index.html
            ResponseCode: 200
            ErrorCachingMinTTL: 0
        # 料金クラス指定
        PriceClass: PriceClass_All
        # ディストリビューション有効無効指定
        Enabled: true
        # SSL証明書設定
        ViewerCertificate:
          # 証明書ID指定
          AcmCertificateArn: !Sub arn:aws:acm:us-east-1:${AWS::AccountId}:certificate/${CertificateId}
          # セキュリティポリシー指定
          MinimumProtocolVersion: TLSv1.2_2021
          SslSupportMethod: sni-only
        # 配信制限設定
        Restrictions:
          GeoRestriction:
            # 地理的制限指定
            RestrictionType: none
        # HTTPバージョン指定
        HttpVersion: http2
        # ルートURL指定
        DefaultRootObject: index.html
        # IPv6有無指定
        IPV6Enabled: true
  # Route53レコード設定
  Route53RecordSet:
    # リソースタイプ
    Type: AWS::Route53::RecordSet
    # 処理順設定
    DependsOn:
      - CloudFrontDistribution
    # プロパティ
    Properties:
      # ドメイン指定
      Name: !Sub ${DomainName}
      # ホストゾーンID指定
      HostedZoneId: !Sub ${HostedZoneId}
      # レコードタイプ指定
      Type: A
      # エイリアスターゲット設定
      AliasTarget:
        # CloudFrontドメイン指定
        DNSName: !GetAtt CloudFrontDistribution.DomainName
        # ホストゾーンID指定 (固定)
        HostedZoneId: Z2FDTNDATAQYW2
```

<br>

## 事前準備

- Amazon Route 53による独自ドメインの取得  
- 対象の「ドメイン名」と「ホストゾーンID」をメモしておく  

![img](https://day-journal.com/memo/images/try-084_01.png)

<br>

## 構築の流れ

1. [指定リージョンでSSL証明書を自動デプロイ](https://qiita.com/dayjournal/items/314f3de3805f6962f0e9#%E6%8C%87%E5%AE%9A%E3%83%AA%E3%83%BC%E3%82%B8%E3%83%A7%E3%83%B3%E3%81%A7ssl%E8%A8%BC%E6%98%8E%E6%9B%B8%E3%82%92%E8%87%AA%E5%8B%95%E3%83%87%E3%83%97%E3%83%AD%E3%82%A4)
2. [任意リージョンで独自ドメインホスティング環境を自動デプロイ](https://qiita.com/dayjournal/items/314f3de3805f6962f0e9#%E4%BB%BB%E6%84%8F%E3%83%AA%E3%83%BC%E3%82%B8%E3%83%A7%E3%83%B3%E3%81%A7%E7%8B%AC%E8%87%AA%E3%83%89%E3%83%A1%E3%82%A4%E3%83%B3%E3%83%9B%E3%82%B9%E3%83%86%E3%82%A3%E3%83%B3%E3%82%B0%E7%92%B0%E5%A2%83%E3%82%92%E8%87%AA%E5%8B%95%E3%83%87%E3%83%97%E3%83%AD%E3%82%A4)

<br>

## 指定リージョンでSSL証明書を自動デプロイ

はじめに、指定リージョンでSSL証明書を自動デプロイします。SSL証明書をCloudFrontで利用するためには、リージョンを「us-east-1」で作成する必要があります。  

リージョン「us-east-1」でCloudFormationにアクセス。スタック → スタックの作成 → 「新しいリソースを使用」をクリック。
![img](https://day-journal.com/memo/images/try-084_02.png)

前提条件は「テンプレートの準備完了」を選択。テンプレートの指定は「テンプレートファイルのアップロード」を選択しファイルをアップロード → 「次へ」をクリック。
CloudFormationテンプレートは「certificate-create.yml」を利用。
![img](https://day-journal.com/memo/images/try-084_03.png)

任意のスタック名・ドメイン名・ホストゾーンIDを設定 → 「次へ」をクリック。
![img](https://day-journal.com/memo/images/try-084_04.png)

スタックオプションは今回デフォルトで設定 → 「次へ」をクリック。
![img](https://day-journal.com/memo/images/try-084_05.png)

設定を確認 → 「スタックの作成」をクリック。
![img](https://day-journal.com/memo/images/try-084_06.png)

スタックが作成されたのを確認。
![img](https://day-journal.com/memo/images/try-084_07.png)

「us-east-1」リージョンのAWS Certificate Managerを確認すると、SSL証明書が自動作成されているのを確認できる。次のテンプレートで利用するため対象の「証明書ID」をメモ。
![img](https://day-journal.com/memo/images/try-084_08.png)

<br>

## 任意リージョンで独自ドメインホスティング環境を自動デプロイ

最後に、任意リージョンで独自ドメインホスティング環境を自動デプロイします。

デプロイしたいリージョンでCloudFormationにアクセス。
スタック → スタックの作成 → 「新しいリソースを使用」をクリック。
![img](https://day-journal.com/memo/images/try-084_09.png)

前提条件は「テンプレートの準備完了」を選択。テンプレートの指定は「テンプレートファイルのアップロード」を選択しファイルをアップロード → 「次へ」をクリック。
CloudFormationテンプレートは「hosting.yml」を利用。
![img](https://day-journal.com/memo/images/try-084_10.png)

任意のスタック名・証明書ID・ドメイン名・ホストゾーンIDを設定 → 「次へ」をクリック。
![img](https://day-journal.com/memo/images/try-084_11.png)

スタックオプションは今回デフォルトで設定 → 「次へ」をクリック。
![img](https://day-journal.com/memo/images/try-084_12.png)

設定を確認 → 「スタックの作成」をクリック。
![img](https://day-journal.com/memo/images/try-084_13.png)

スタックが作成されたのを確認。
![img](https://day-journal.com/memo/images/try-084_14.png)

Amazon CloudFrontに自動でデプロイされているのを確認します。
![img](https://day-journal.com/memo/images/try-084_15.png)

Amazon S3に自動でデプロイされているのを確認します。
![img](https://day-journal.com/memo/images/try-084_16.png)

デプロイされたS3バケットに公開したいファイル一式をアップロードします。
![img](https://day-journal.com/memo/images/try-084_17.png)

独自ドメインにアクセスするとアップロードしたWebSiteが表示されます。
![img](https://day-journal.com/memo/images/try-084_18.png)

<br>

AWS CloudFormationを利用することで、独自ドメインホスティング等のさまざまなリソース構築を自動化することが可能です :bulb: 

今後は、AWS CDK等で各サービス構成をどの範囲まで定義できるかも試していければと思います。

<br>

AWS CloudFormationについて、他にも記事を書いています。よろしければぜひ :bow:
<a href="https://day-journal.com/memo/tags/AWS-CloudFormation" target="_blank">tags - AWS CloudFormation</a>

やってみたシリーズ :grinning:
<a href="https://day-journal.com/memo/tags/Try" target="_blank">tags - Try</a>

https://qiita.com/dayjournal/items/57cb0a8232d11c6c99af

https://qiita.com/dayjournal/items/945613577b3056ec4f71

<br>
<br>

<a href="https://dayjournal.booth.pm" target="_blank"><img src="https://day-journal.com/memo/images/etc/book.png" alt="book"></a>