ACMのリクエストとDNS検証をシェルで自動化するには途中でウェイトが必要
こんにちは。深緑です。
先日、AWSにてWEBサイトのアカウント発行を自動化したのですが、
httpsの部分・・・即ちACMのリクエストとDNS検証に非常に苦労したので共有させていただきます。
なお、本記事のスクリプトはこちらのサイトを参考にさせていただいています。
ACM での SSL 証明書発行を AWS CLI でスクリプト化する - michimani.net
こちらの記事でもACMのリクエスト後にウェイトを入れていますが、
私が組んでみたところACMのリクエスト時に別名ドメインを増やすとより多くのウェイトが必要かつバラツキが発生することがわかったので、それに対応するためアレンジを入れたのが本記事のスクリプトになります。
上記記事の執筆者の方に感謝いたします。
ACMのリクエストとDNS検証を行うシェル
最終的に出来上がったシェルはこの通りです。
#!/bin/bash
domain="admin.example.net"
alternative_names=("subdomain1.example.net" "subdomain2.example.net")
hosted_zone_id="Route53のホストゾーンID"
# ACMをリクエスト
acm_arn=$( \
aws acm request-certificate \
--region ap-northeast-1 \
--domain-name ${domain} \
--validation-method DNS \
--subject-alternative-names $(IFS=" "; echo "${alternative_names[*]}") \
--output text)
# ACMのDNS検証レコードを作成
len=$((${#alternative_names[@]} + 1)) # ドメイン+代替ドメインの数
for i in $( seq 0 $(($len - 1)) )
do
# ACMの検証用レコードのNameとValueの取得
# ACMのリクエスト直後は検証用レコードが取れないので何回かリトライする
validation_record_name=""
validation_record_value=""
for j in $(seq 180)
do
sleep 3
validation_record_name=$( \
aws acm describe-certificate \
--region ap-northeast-1 \
--certificate-arn ${acm_arn} \
--query "Certificate.DomainValidationOptions[${i}].ResourceRecord.Name" \
--output text)
# NameとValueがまだできてない場合「None」が返ってくるので、返却値が4文字を超えていることをループを抜ける条件にする
if [ 4 -ge "${#validation_record_name}" ]; then
continue
fi
validation_record_value=$( \
aws acm describe-certificate \
--region ap-northeast-1 \
--certificate-arn ${acm_arn} \
--query "Certificate.DomainValidationOptions[${i}].ResourceRecord.Value" \
--output text)
if [ 4 -lt "${#validation_record_name}" ] && [ 4 -lt "${#validation_record_value}" ]; then
break
fi
done
if [ 4 -ge "${#validation_record_name}" ] || [ 4 -ge "${#validation_record_value}" ]; then
echo "ACMの検証用レコードが取得できませんでした"
exit 1
fi
aws route53 change-resource-record-sets \
--region ap-northeast-1 \
--hosted-zone-id ${hosted_zone_id} \
--change-batch \
"{
\"Comment\": \"ACMのDNS検証レコードを作成\",
\"Changes\": [
{
\"Action\": \"UPSERT\",
\"ResourceRecordSet\": {
\"Name\": \"${validation_record_name}\",
\"Type\": \"CNAME\",
\"TTL\": 300,
\"ResourceRecords\": [
{
\"Value\": \"${validation_record_value}\"
}
]
}
}
]
}"
done
exit 0
解説
本スクリプトは、ACMの検証も自動化するためにDNS検証を使用しています。
DNSにはRoute53を使用する想定で書いています。
DNS検証は、作成したACMをaws acm describe-certificate
してCertificate.DomainValidationOptions[].ResourceRecord
のNameとValueを用いて、
Route53にCNAMEを作ることで実現できます。
ACMの画面における「Route53でレコードを作成」のボタンの動きです。
Certificate.DomainValidationOptions[].ResourceRecord
の中身は、
aws acm request-certificate
が正常終了しても一定時間(バラツキあり)は空っぽです。
従って、aws acm request-certificate
の直後に aws acm describe-certificate
してRoute53のCNAME作成しようとしても空振りします。
これを回避するためにループとsleepを用いてウェイトをかけている次第です。
Certificate.DomainValidationOptions[].ResourceRecord.Name
Certificate.DomainValidationOptions[].ResourceRecord .Value
は、まだできてない場合は「None」が返ってくるので、返却値が4文字を超えているかどうかをウェイトの終了条件としています。
if [ 4 -ge "${#validation_record_name}" ]; then
continue
fi
この部分は「None」との文字列比較でもいいような気はしているのですが、
なんか空白値が返ってくることがあるんじゃないかと心配になり文字数の比較としました。
本来取れる値は4文字はあり得ないですからね。
参考にしたサイト
ACM での SSL 証明書発行を AWS CLI でスクリプト化する - michimani.net
本記事がお役に立てれば幸いです。
Discussion