Route53 + CloudFront + S3 で ZoneApexのリダイレクト

# やりたいこと
- example.com のようなZoneApex を www.example.com などへリダイレクトする
- もちろんHTTPSも対応


# 手順
1. S3のバケットを作る
    - バケット名はなんでも良い (が、ZoneApexをそのまま使えば良いだろう)
    - Static website hostingで、リクエストをリダイレクトする、をチェック
    - ターゲットバケットまたはドメイン の箇所に、リダイレクト先（ここではwww.example.com） を入力する
    - プロトコルはリダイレクト先がssl対応していればHTTPS
2. AWS Certificate Manager(ACM)で example.com のSSL証明書を発行する
    - SSL証明書は **us-east-1** リージョンで作成しておく
    - さもないと、CloudFrontのDistributionを作る時に ```The specified SSL certificate doesn't exist, isn't in us-east-1 region, isn't valid, or doesn't include a valid certificate chain.``` とか言って、怒られる
3. CloudFrontのDistributionを作る
    - CNAMEを example.com とする
    - SSL Certificateは 2. で作成した証明書を使う
4. Route53でARecordを設定
    - AliasTargetとして 3. で作成したDistributionのDomain Nameを指定


# CloudFormationで構築
AWSマネジメントコンソールからの設定方法については至る所で説明されているので、ここではCloudFromationのテンプレートを示す。

```yaml

AWSTemplateFormatVersion: 2010-09-09
Parameters:
  ZoneApexSSLCertArn:
    Default: >-
      arn:aws:acm:[REGION]:[ACCOUNT_ID]:certificate/hogehoge-fugafuga
    Description: Certificate for SSL
    Type: String
  ZoneApex:
    Default: example.com
    Description: Domain name
    Type: String
  CloudFrontHostedZoneId:
    Default: Z2FDTNDATAQYW2
    Description: CloudFront hosted zone id from AWS Documantation
    Type: String
Resources:
  HostedZode:
    Type: 'AWS::Route53::HostedZone'
    Properties:
      Name: !Ref ZoneApex
  ARecordZoneApex:
    Type: 'AWS::Route53::RecordSet'
    Properties:
      HostedZoneId: !Ref HostedZode
      Name:
        'Fn::Join':
          - ''
          - - !Ref ZoneApex
            - .
      Type: A
      AliasTarget:
        HostedZoneId: !Ref CloudFrontHostedZoneId
        DNSName: !GetAtt ZoneApexRedirectBucketCloudFront.DomainName
    DependsOn:
      - ZoneApexRedirectBucketCloudFront
  ZoneApexRedirectBucket:
    Type: 'AWS::S3::Bucket'
    Properties:
      BucketName: !Ref ZoneApex
      WebsiteConfiguration:
        RedirectAllRequestsTo:
          HostName:
            'Fn::Join':
              - ''
              - - www.
                - !Ref ZoneApex
          Protocol: https
  ZoneApexRedirectBucketCloudFront:
    Type: 'AWS::CloudFront::Distribution'
    DependsOn:
      - ZoneApexRedirectBucket
    Properties:
      DistributionConfig:
        Aliases:
          - !Ref ZoneApex
        HttpVersion: http2
        Enabled: true
        DefaultCacheBehavior:
          ForwardedValues:
            QueryString: false
            Cookies:
              Forward: none
          TargetOriginId:
            'Fn::Join':
              - ''
              - - Custom-
                - !Ref ZoneApex
                - .s3-website-
                - !Ref 'AWS::Region'
                - .amazonaws.com/
          ViewerProtocolPolicy: allow-all
        ViewerCertificate:
          AcmCertificateArn: !Ref ZoneApexSSLCertArn
          SslSupportMethod: sni-only
        Origins:
          - CustomOriginConfig:
              OriginProtocolPolicy: http-only
            DomainName:
              'Fn::Join':
                - ''
                - - !Ref ZoneApex
                  - .s3-website-
                  - !Ref 'AWS::Region'
                  - .amazonaws.com
            Id:
              'Fn::Join':
                - ''
                - - Custom-
                  - !Ref ZoneApex
                  - .s3-website-
                  - !Ref 'AWS::Region'
                  - .amazonaws.com/

```

Parametersにある ```ZoneApexSSLCertArn``` に、貴方が取得したSSL証明書のARNを指定してね。
必然的に、[REGION]の部分は us-east-1 になると思います。



# 注意点
- 現在、S3の静的ウェブホスティングではHTTPSをサポートしていない。
従って、S3のリダイレクト設定では、HTTPSのZoneApexからHTTPSのサブドメインへリダイレクトをすることができない。要CloudFront。
- SSL証明書は **us-east-1** リージョンで作成しないとCloudFrontのDistributionで使用することができない。
- Alias TargetのHostedZoneId設定に注意
    - CloudFrontの場合は ``` Z2FDTNDATAQYW2 ``` を使う
    - http://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-properties-route53-aliastarget.html