AWS Certificate Manager 使えよって話なんですが、例えばドメイン認証に使用するためのメールアドレスは使えないけど、Web サーバ上に認証ファイルはおけるっていう限定的な環境で Let's Encrypt で更新した SSL 証明書を ELB にアップロードしたいとかって状況があるかもしれませんね。
実際あったんです。
そんな時は letsencrypt renew
の後に aws-cli でアップロードするようにしてあげればいいんでないかなーと。
ELB 配下には複数のインスタンスがぶら下がってることが多いと思いますが、前提条件としては letsencrypt renew
を実施するインスタンスは固定しておいて、ELB (application) のターゲットグループでパス /.well-known/*
をそのインスタンスに流すように設定しておく必要があります。
あとは、そのインスタンスに以下のようなシェルスクリプトを作ります。
ELB v2(Application) の場合
# !/bin/bash
set -eux
_domain='example.com'
_listener_arn='{ELB_LISTNER_ARN_HERE}'
_cert_path="/${_domain}/"
_date=$(date +%Y%m%d-%H%M%S)
_cert_name="${_domain}-${_date}"
# 新しいSSL証明書をアップロード
cd /etc/letsencrypt/live/${_domain}/
aws iam upload-server-certificate \
--server-certificate-name ${_cert_name} \
--certificate-body file://cert.pem \
--private-key file://privkey.pem \
--certificate-chain file://chain.pem \
--path ${_cert_path}
# 新しいSSL証明書を ELB(Application) のターゲットグループにセット
sleep 60
_cert_arn=$(aws iam get-server-certificate --server-certificate-name ${_cert_name} | jq -r '.ServerCertificate.ServerCertificateMetadata.Arn')
aws elbv2 modify-listener \
--listener-arn ${_listener_arn} \
--certificates "CertificateArn=${_cert_arn}"
# 古いSSL証明書を削除
_certs=$(aws iam list-server-certificates --path-prefix ${_cert_path} | jq -r '.ServerCertificateMetadataList[].ServerCertificateName')
for _cert in ${_certs}; do
if [ "${_cert_name}" != "${_cert}" ]; then
aws iam delete-server-certificate --server-certificate-name ${_cert}
fi
done
ELB v1(classic) の場合
# !/bin/bash
set -eux
_domain='example.com'
_elb_name='{ELB_NAME_HERE}'
_elb_port='443'
_cert_path="/${_domain}/"
_date=$(date +%Y%m%d-%H%M%S)
_cert_name="${_domain}-${_date}"
# 新しいSSL証明書をアップロード
cd /etc/letsencrypt/live/${_domain}/
aws iam upload-server-certificate \
--server-certificate-name ${_cert_name} \
--certificate-body file://cert.pem \
--private-key file://privkey.pem \
--certificate-chain file://chain.pem \
--path ${_cert_path}
# 新しいSSL証明書を ELB(classic) のリスナーにセット
sleep 60
_cert_arn=$(aws iam get-server-certificate --server-certificate-name ${_cert_name} | jq -r '.ServerCertificate.ServerCertificateMetadata.Arn')
aws elb set-load-balancer-listener-ssl-certificate \
--load-balancer-name ${_elb_name} \
--load-balancer-port ${_elb_port} \
--ssl-certificate-id ${_cert_arn}
# 古いSSL証明書を削除
_certs=$(aws iam list-server-certificates --path-prefix ${_cert_path} | jq -r '.ServerCertificateMetadataList[].ServerCertificateName')
for _cert in ${_certs}; do
if [ "${_cert_name}" != "${_cert}" ]; then
aws iam delete-server-certificate --server-certificate-name ${_cert}
fi
done
_domain
と _listener_arn
(_elb_name
, _elb_port
) は、環境によって変更してあげてくださいね。
あと、jq 使ってるんで yum install jq
とかでインストールしてあげてください。
そんで letsencrypt renew
の --renew-hook
オプションで、証明書が更新された時に実行するコマンドとして登録するわけです。
letsencrypt renew --renew-hook '/root/bin/upload-cert.sh'
あとは、上のコマンドを crontab で定期的(週一回とか)に実行してあげれば、Let's Encrypt の SSL証明書が更新された時に自動的に ELB のターゲットグループに設定されてる証明書も更新されて古い証明書が削除されるってわけです。