AWSでの静的サイトのterraform構築例の紹介(と、CertificateManagerでのSSL証明書取得がラクになった件🎅)
🎄「Amazon Web Services Advent Calendar 2017」1日目の記事です 🎄
tl;dr
● AWSで静的サイト(https + 独自ドメイン)を構築するための手順説明を行います。.tfファイル例も公開(smarby/terraform-aws-static-site-sample)します 🎅
● 実は11月から、ACMでのSSL証明書の発行が簡単になりました! そのあたりにも対応しています。
今年構築した、あるサイトの構成
今年、とあるキャンペーンサイトをhttps+独自ドメインで構築する、という機会がありました。
以下のような構成です。originにS3の「静的ウェブサイト配信」を利用し、全てCloudFront経由で配信します。
SSL証明書の取得方法について
メールでの検証
AWS CertificateManager(以下、ACM)を利用してのSSL証明書取得するためには、AWS側に私がそのドメインの管理者であることを検証(Validate)してもらう必要があります。
「1. 証明書発行をリクエスト」=> 「2. 自動送付される確認メール(Subject = Certificate approval)の中身にあるリンクをクリックし承認」という流れです。
そこで、キャンペーンサイトの構築にあたっては、以下のように、S3バケット経由でメールの確認ができるようにして対応していました(ここもterraformでがんばっていました!!)。
【NEW!!】DNS検証
しかし最近(2017年11月)、上記のメールでの検証フローとは別に、DNS検証というオプションが増えました。
DNS検証は、以下のように、AWSの指定するCNAMEレコードを追加することにより、ドメインの管理者であることの確認を行うという形です。
つまり、上記のような「メールを受信できる状態を作り、ACMからのメールを受信し、クリックする」という面倒なことが不要になりました!!
このほうがラクそうなので、今回公開する構築方法は、こちらの方法で行ってみたいと思います。
インフラセットアップ手順
ここから先は、雛形となる.tfファイルを利用しながら、手順を説明します。
なお、このサンプルは、「所有しているドメインを、サブドメイン無しでキャンペーンサイトに利用する」という前提で書かれています。terraform の使い方(terraform initやbackendなど)については説明しません。
1.証明書リクエストし、必要なCNAMEレコードを確認する 👀
以下のコマンドを実行します。"my-static-site.com"のところは、今回配信に利用するドメイン名を指定してください。--validation-method="DNS"としているところがポイントです。2017年11月以降のaws-cliを利用してください。(手元ではaws-cli/1.12.1を利用しています)
$ aws --region=us-east-1 acm request-certificate \
--domain-name="my-static-site.com" \
--validation-method="DNS"
以下のように、証明書のARNが返ります。
{
"CertificateArn": "arn:aws:acm:us-east-1:111122223333:certificate/aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee"
}
次に、このARNを利用して、登録が必要なレコードの値を問い合わせます。すぐ問い合わせると失敗することがあるので、その場合は数秒待ち、もう一度問い合わせてみてください。
$ aws --region=us-east-1 acm describe-certificate \
--certificate-arn="arn:aws:acm:us-east-1:111122223333:certificate/aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee" \
| jq ".Certificate.DomainValidationOptions[0].ResourceRecord"
成功すると、以下のように、CNAMEレコードに必要な名前と値を取得できます。
{
"Type": "CNAME",
"Name": "_xxxxxxxxxxxxxxxxxxxxxx.my-static-site.com",
"Value": "_yyyyyyyyyyyyyyyyyyyyyyyyy.acm-validations.aws"
}
2. .tfファイルのダウンロード、一部編集 ✏️
次に、git cloneで.tfファイルをダウンロードします。
$ git clone https://github.com/smarby/terraform-aws-static-site-sample
environments/production/variables.tf を編集し、独自ドメイン名、コンテンツを配置するバケット名等を設定します。
# ACMのリージョン。CloudFront連携するにはバージニア(us-east-1)を選択する必要がある。
acm_region = "us-east-1"
# 先程のrequest-certificateの結果(Name)を貼る。最初の.までの値。
acm_verification_record_name = "_xxxxxxxxxxxxxxxxxxxxxx"
# 先程のrequest-certificateの結果(Value)を貼る。
acm_verification_record_value = "_yyyyyyyyyyyyyyyyyyyyyyyyy.acm-validations.aws"
# cloudfrontが認識するoriginの識別子。他と重複せず、管理しやすい名前であれば良い。
cloudfront_origin_id = "production_my_static_site_s3_origin"
# 所持している独自ドメイン
domain = "my-static-site.com"
# コンテンツを配置するバケットのリージョン
region = "ap-northeast-1"
3. terraform apply (1回目) 🚀
ディレクトリenvironments/production に移動したのち、terraform init と terraform apply を実行します。
$ cd environments/production
$ terraform init # backend等の設定
$ terraform apply
ここイケてないのですが、この1度目のterraform applyでは、証明書の発行がまだ終わっていないので、CloudFrontのディストリビューション作成のところで失敗します。null_resourceやlocal-execを駆使するとイケるかもしれませんが、特にここでは頑張りません。
4. レジストラ側にNSレコードを設定 ✏️
次に、
$ terraform output -module=static_site
と実行すると出力結果としてNSレコードが4個出てきますので、これをレジストラ側にネームサーバーとして設定します。NSレコードの反映を、しばし待ちます。
5. 証明書が発行されたことを確認 👀
先程と同様に、describe-certificateで証明書の状態をチェックします。
$ aws --region=us-east-1 acm describe-certificate \
--certificate-arn="arn:aws:acm:us-east-1:111122223333:certificate/aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee"
AWS側でCNAMEレコードが検証できていれば、ISSUED(証明書発行済み)が返ってきます。NSレコードの反映と、AWSのCNAMEレコードのチェックのタイミング次第ですが、場合によっては時間がかかるかもしれません。
ISSUEDになっていれば、次のステップに進みます。
6. terraform apply(2回目) 🚀
先程と同様に、terraform applyを実行します。
今度は、CloudFrontのディストリビューションが作成されるはずです。
7. コンテンツの配信を確認 👀
ディストリビューション作成が終わった後、S3にコンテンツをアップロードし、オブジェクトの公開設定を行うと、httpsで配信できることを確認できると思います。
説明は以上です。
まとめ 🎄
● ACMにDNS認証が登場し、SSL証明書の取得がラクになりました。
● 静的サイトの構築方法を説明しました。