CloudFormation + ちょい足しでリダイレクトWebサイトを作ってみた

AWS事業本部 梶原@福岡オフィスです。

先日、Webサイトのリダイレクトを特急で作成する必要があり 次回楽をするために、CloudFormation一撃化しようとしたのですが、ちょっとACMの部分だけは複雑になりそうだったのでちょい足しすることしました。

ウェブサイトの閉鎖等の際、別のサイトに誘導したい またwww.xxxx.com からxxxx.comへのリダイレクトなどの時にも使用できるかと思います。 (パスを含まない場合は高度な条件付きリダイレクトでなくて、単純なリダイレクト設定でもいけます)

仕組みとしては、CloudFront + S3 静的ウェブサイトホスティング + 高度な条件付きリダイレクト機能 を使用します。

今回のちょい足し部分はACMの証明書のDNS認証の為の1ポチです。

前提条件

  • ドメインをRoute53で管理していること

構築

1. AWSコンソールにログイン

https://ap-northeast-1.console.aws.amazon.com/console/home?region=ap-northeast-1#

2. このボタンをポチっとする。

CloudFormationを実行した後にタイムアウト前にACMの承認をする必要があるため、心の準備だけはお願いします。 なお、CloudFormationの実行リージョンは米国東部 (バージニア北部)で実施してください
(CloudFrtont用のACMの証明を米国東部 (バージニア北部)で発行するため)

From

  • DomainName(リダイレクト元のドメイン名)
  • ValidationDomain(登録するホストゾーン)

To

  • Protocol
  • TargetHostName
  • TargetPath

をパラメータに入力

TargetPathの開始は/を含くまないようにして下さい。(S3 の高度な条件付きリダイレクト設定と同様)
下記設定は、本ブログのAWSカテゴリに飛ぶようにしています。

CludFormationの実行をしましたら、作成がタイムアウトする前(30分程度は余裕があります)にACMの認証を行います。

ちょい足し部分

ACM証明書のDNS認証を実施する

下のリンクをクリックしてCertificate Managerの画面から今回作成したドメインの認証を行います。

https://console.aws.amazon.com/acm/home?region=us-east-1#/

該当する証明書のRoute53でのレコード作成を押下します

ACM証明書の状況が発行済みになったら、あとはコトコトにこむ CloudFormationの完了をお待ちください。 CloudFrontのディストリビューションの生成が正常に完了するまで30分から1時間程度程度かかります。

動作確認

意図したリダイレクトとなっているか確認してください。

また https://docs.aws.amazon.com/ja_jp/AmazonS3/latest/dev/how-to-page-redirect.html#advanced-conditional-redirects

を参考にして、リダイレクト条件などを変更ください。

まとめ

アクセスログなどは設定してないので、必要に応じて設定していただけると幸いです。 サクッと作って、このサイトどこにいったんやーってことにならないようなるかといいかと。 今回は一発でDNS設定までつくってしまいましたが、実際のサイト移行の際はRecordSetGroupの部分はコメント等を実施して、移行してください。

参考

[ACM] CloudFormationがACMのDNSレコード検証に対応しました

https://docs.aws.amazon.com/ja_jp/AmazonS3/latest/dev/how-to-page-redirect.html#advanced-conditional-redirects

CloudFormationテンプレート

AWSTemplateFormatVersion: "2010-09-09"
Metadata: 
  AWS::CloudFormation::Interface: 
    ParameterGroups: 
      - Label: 
          default: "From"
        Parameters: 
          - DomainName
          - ValidationDomain
      - Label: 
          default: "To"
        Parameters: 
          - Protocol
          - TargetHostName
          - TargetPath

Parameters:
  Protocol:
    Type: String
    Default: "https"
  TargetHostName:
    Type: String
  TargetPath:
    Type: String
  DomainName:
    Type: String
  ValidationDomain:
    Type: String

Resources:
  # S3 bucket contains static contents
  S3Bucket:
    Type: AWS::S3::Bucket
    Properties:
      # BacketName: !Ref BacketName
      WebsiteConfiguration:
        IndexDocument: "index.html"
        RoutingRules:
          - RedirectRule:
              Protocol: !Ref Protocol
              HostName: !Ref TargetHostName
              ReplaceKeyWith: !Ref TargetPath

  # ACMCertificate
  ACMCertificate:
    Type: AWS::CertificateManager::Certificate
    Properties:
      DomainName: !Ref DomainName
      DomainValidationOptions:
        - DomainName: !Ref DomainName
          ValidationDomain: !Ref ValidationDomain
      ValidationMethod: DNS

  # CloudFront Distribution for contents delivery
  S3Distribution:
    DependsOn: S3Bucket
    DependsOn: ACMCertificate
    Type: AWS::CloudFront::Distribution
    Properties:
      DistributionConfig:
        Aliases: 
        - !Ref DomainName
        Origins:
        - Id: !Sub S3-Website-${S3Bucket.DomainName}
          DomainName: !Sub ${S3Bucket}.s3-website-${AWS::Region}.amazonaws.com
          CustomOriginConfig:
            OriginProtocolPolicy: http-only
        Enabled: true
        HttpVersion: http2
        IPV6Enabled: true
        DefaultCacheBehavior:
          TargetOriginId: !Sub S3-Website-${S3Bucket.DomainName}
          ForwardedValues:
            QueryString: false
          ViewerProtocolPolicy: redirect-to-https
          Compress: true
        PriceClass: "PriceClass_200"
        ViewerCertificate:
          AcmCertificateArn: !Ref ACMCertificate
          SslSupportMethod: sni-only
          MinimumProtocolVersion: TLSv1.1_2016
        Comment: !Sub ${AWS::StackName} distribution

  RecordSetGroup:
    Type: AWS::Route53::RecordSetGroup
    Properties:
      HostedZoneName: !Sub "${ValidationDomain}."
      RecordSets:
        - Name: !Ref DomainName
          Type: A
          AliasTarget:
            HostedZoneId: Z2FDTNDATAQYW2
            DNSName: !GetAtt S3Distribution.DomainName

Outputs:
  Url:
    Value: !Sub "https://${DomainName}"