Route53にCloudFront + S3構成を登録して、独自ドメインでアクセスする
以下のページで、OACを使用して、CloudFront経由でS3コンテンツを配信する方法を取り上げました。

本ページはこの続きということで、この構成をRoute53に登録し、独自ドメインでアクセスできるようにします。
構築する環境

基本的には、先述のページと同様です。
変更点は2点です。
1点目はRoute53です。
Route53にCloudFrontを登録し、独自ドメインでアクセスできるようにします。
今回はRoute53で取得した「awstut.net」を使用します。
2点目はACMです。
独自ドメインでアクセスする際の通信をSSL化します。
CloudFormationテンプレートファイル
上記の構成をCloudFormationで構築します。
以下のURLにCloudFormationテンプレートを配置しています。
https://github.com/awstut-an-r/awstut-fa/tree/main/134
テンプレートファイルのポイント解説
本構成はCloudFormation StackSetsを使用して構築します。
StackSetsに関する詳細は、以下のページをご確認ください。

Route53
Resources:
  DnsRecord:
    Type: AWS::Route53::RecordSet
    Properties:
      HostedZoneId: !Ref HostedZoneId
      Name: !Ref DomainName
      Type: A
      AliasTarget:
        DNSName: !Ref DistributionDomainName
        HostedZoneId: !Ref DistributionHostedZoneId
Code language: YAML (yaml)Route53に独自ドメインとCloudFrontに関するレコードを設定します。
詳細につきましては、以下のページをご確認ください。

ポイントはCloudFrontのHostedZoneIdです。
以下のページによりますと、CloudFrontのHostedZoneIdは「Z2FDTNDATAQYW2」とありますので、これを設定します。
https://docs.aws.amazon.com/ja_jp/general/latest/gr/cf_region.html
ACM
Resources:
  Certificate:
    Type: AWS::CertificateManager::Certificate
    Properties:
      DomainName: !Ref DomainName
      DomainValidationOptions:
        - DomainName: !Ref DomainName
          HostedZoneId: !Ref HostedZoneId
      ValidationMethod: DNS
Code language: YAML (yaml)ACMを使用して、独自ドメイン用の証明書を作成します。
詳細につきましては、以下のページをご確認ください。

ポイントはACMを作成するリージョンです。
Amazon CloudFront で ACM 証明書を使用するには、米国東部 (バージニア北部) リージョン の証明書をリクエスト (またはインポート) していることを確認します。CloudFront ディストリビューションに関連づけられたこのリージョンの ACM 証明書は、このディストリビューションに設定されたすべての地域に分配されます。
サポートされるリージョン
上記に従い、us-east-1リージョンでACMを作成します。
ACMのIDをSSM Parameter Storeに保存します。
Resources:
  CustomResource:
    Type: Custom::CustomResource
    Properties:
      ServiceToken: !GetAtt Function.Arn
  Function:
    Type: AWS::Lambda::Function
    Properties:
      Code:
        ZipFile: |
          import boto3
          import cfnresponse
          import os
          certificate = os.environ['CERTIFICATE']
          parameter_name = os.environ['PARAMETER_NAME']
          region = os.environ['REGION']
          ssm_client = boto3.client('ssm', region_name=region)
          CREATE = 'Create'
          DELETE = 'Delete'
          response_data = {}
          def lambda_handler(event, context):
            try:
              if event['RequestType'] == CREATE:
                response = ssm_client.put_parameter(
                  Name=parameter_name,
                  Value=certificate,
                  Type='String'
                )
                print(response)
              elif event['RequestType'] == DELETE:
                response = ssm_client.delete_parameter(
                  Name=parameter_name
                )
                print(response)
              cfnresponse.send(event, context, cfnresponse.SUCCESS, response_data)
            except Exception as e:
              print(e)
              cfnresponse.send(event, context, cfnresponse.FAILED, response_data)
      Environment:
        Variables:
          CERTIFICATE: !Ref Certificate
          PARAMETER_NAME: !Ref ACMParameterStoreName
          REGION: !Ref AppRegion
      FunctionName: !Sub "${Prefix}-function"
      Handler: !Ref Handler
      Runtime: !Ref Runtime
      Role: !GetAtt FunctionRole.Arn
Code language: YAML (yaml)CloudFormationカスタムリソースを使用します。
カスタムリソースに紐付くLambda関数を実行することで、パラメータを保存します。
CloudFormationカスタムリソースに関する詳細は、以下のページをご確認ください。

今回の構成はap-northeast-1リージョンに構築します。
ですからus-east-1リージョン上のACMのIDが参照できるように、ap-northeast-1リージョンのSSM Parameter Storeに登録します。
CloudFront
Resources:
  Distribution:
    Type: AWS::CloudFront::Distribution
    Properties:
      DistributionConfig:
        Aliases:
          - !Ref DomainName
        DefaultCacheBehavior:
          AllowedMethods:
            - GET
            - HEAD
          CachedMethods:
            - GET
            - HEAD
          Compress: true
          ForwardedValues:
            Cookies:
              Forward: none
            QueryString: false
          TargetOriginId: !Ref BucketName
          ViewerProtocolPolicy: redirect-to-https
        DefaultRootObject: index.html
        Enabled: true
        Origins:
          - DomainName: !Ref BucketRegionalDomainName
            Id: !Ref BucketName
            OriginAccessControlId: !GetAtt OAC.Id
            S3OriginConfig:
              OriginAccessIdentity: ""
        PriceClass: PriceClass_All
        ViewerCertificate:
          SslSupportMethod: sni-only
          AcmCertificateArn: !Sub "{{resolve:ssm:${ACMParameterStoreName}}}"
Code language: YAML (yaml)CloudFrontディストリビューションにACMを適用する上でのポイントは2つです。
1点目はAliasesプロパティです。
こちらに使用するドメイン名を登録します。
2点目はViewerCertificateプロパティです。
こちらにACMのIDを指定します。
先述のParameter Storeの値を参照して、本プロパティに設定します。
環境構築
CloudFormationを使用して、本環境を構築し、実際の挙動を確認します。
CloudFormationスタックを作成し、スタック内のリソースを確認する
CloudFormationスタックを作成します。
スタックの作成および各スタックの確認方法については、以下のページをご確認ください。

各スタックのリソースを確認した結果、今回作成された主要リソースの情報は以下の通りです。
- CloudFrontディストリビューション:E1HDHS15XEQA22
- CloudFrontディストリビューションのドメイン:d1u8d8wqcfy55l.cloudfront.net
AWS Management Consoleからも、リソースの作成状況を確認します。
ACMを確認します。

確かに「awstut.net」用のACM証明書が作成されています。
CloudFrontの作成状況を確認します。

正常にCloudFrontディストリビューションが作成されています。
先述のACM証明書がディストリビューションが関連づけられていることもわかります。
ディストリビューションのオリジンを確認します。

確かにS3バケットが関連づけられています。
S3バケットへのアクセスは、OACを使用するように設定されていることもわかります。
Route53を確認します。

確かにCloudFront用のAレコードが作成されています。
動作確認
準備が整いましたので、独自ドメインにアクセスします。
$ curl https://awstut.net/
<html>
  <head></head>
  <body>
    <h1>index.html</h1>
    <p>awstut.net</p>
  </body>
</html>
Code language: HTML, XML (xml)正常に応答がありました。
独自ドメイン、かつHTTPSで通信することができました。
まとめ
CloudFront + S3構成をRoute53に登録し、独自ドメインでアクセスできるようになりました。