追記 2017/7/4 githubにうp
github.com
先週は会社の社長賞研修でサンフランシスコ、シリコンバレーに行ってきて書きたいことは山ほどあるけど、忘れてしまいそうな作業メモ。
研修中に証明書の期限が切れてしまい、リモートで更新するのが非常にストレスだったので、SSL証明書を自動化したい。
以前も考えたけど、GAEの証明書はまだgcloudコマンドからは変更できなかったので諦めた。
調べなおしてみると、2017/6/14のgcloudのアップデートで、コマンドラインからGAE用のSSL証明書をアップできるようになって、実現できるようになったので早速つくってみる。
とりあえずコマンド一発で
TOKENの作成
DNSの変更
AppEngineの証明書をアップデート
まで動いた。
あとcronで回して、念のため有効期限の監視も付ければ完璧?
監視は、デフォルトでは期限まで30日以上あったら更新されないので、期限が30日を切ったタイミングでアラート出せば何らかの原因で止まっているのが確認できるはず。
証明書にはLet's Encrypt
letsencrypt.org
やり取りは、おなじみの↓DNS認証ができるdehydratedを使う。
GitHub - lukas2511/dehydrated: letsencrypt/acme client implemented as a shell-script – just add water
前提として使うドメインはCloud DNSに入れておく必要がある。また、実行ユーザーはGoogle Cloud SDKをインストールして、最新のgcloudコマンドを使えるようにしておく。GAE使ってる環境と同じであれば大丈夫だとは思うけど。
元になるドメイン(bizocean.jp)は、AWS Route53で管理していたけど、今回使うサブドメイン(s.bizocean.jp)のNSレコードだけCloud DNSのものに向けておけば、問題なく動いた。
オリジナルのhook.shをベースに作る。とりあえず変更が必要そうなのは頭にまとめた。
gae_hook.sh
#!/usr/bin/env bash DNS_PROJECT="oceanus-dev" GAE_PROJECT="oceanus-gae" CERT_ID=`gcloud beta app --project $GAE_PROJECT ssl-certificates list | awk 'NR==2 {print $1}'` CERT_NAME="letsencrypt-auto`date "+%Y%m%d"`" TARGET_DOMAIN="s.bizocean.jp" ZONE_NAME="s-bizocean-jp" ACME_TTL=60 SLEEP_SECOND=60 function deploy_challenge { local DOMAIN="${1}" TOKEN_FILENAME="${2}" TOKEN_VALUE="${3}" if [ $DOMAIN = $TARGET_DOMAIN ];then echo "Set TXT record of _acme-challenge.$DOMAIN to $TOKEN_VALUE" echo "dns update start" gcloud dns --project=$DNS_PROJECT record-sets transaction start -z=${ZONE_NAME} gcloud dns --project=$DNS_PROJECT record-sets transaction remove \ `gcloud --project=$DNS_PROJECT dns record-sets list -z=${ZONE_NAME} --name="_acme-challenge.${DOMAIN}." | awk 'NR==2 {print $4}'` \ -z=${ZONE_NAME} --name="_acme-challenge.${DOMAIN}." --type=TXT --ttl=${ACME_TTL} gcloud dns --project=$DNS_PROJECT record-sets transaction add $TOKEN_VALUE -z=${ZONE_NAME} --name="_acme-challenge.${DOMAIN}." --type=TXT --ttl=${ACME_TTL} gcloud dns --project=$DNS_PROJECT record-sets transaction execute -z=${ZONE_NAME} echo "dns update end sleep ${SLEEP_SECOND}" sleep $SLEEP_SECOND else echo "Don't match $TARGET_DOMAIN and $DOMAIN" echo "Set TXT record of _acme-challenge.$DOMAIN to $TOKEN_VALUE manually" read fi } function clean_challenge { local DOMAIN="${1}" TOKEN_FILENAME="${2}" TOKEN_VALUE="${3}" } function deploy_cert { local DOMAIN="${1}" KEYFILE="${2}" CERTFILE="${3}" FULLCHAINFILE="${4}" CHAINFILE="${5}" TIMESTAMP="${6}" if [ $DOMAIN = $TARGET_DOMAIN ];then echo "update ssl cert start" gcloud beta app --project ${GAE_PROJECT} ssl-certificates update $CERT_ID \ --display-name=$CERT_NAME \ --certificate=$FULLCHAINFILE \ --private-key=$KEYFILE else echo "Don't match $TARGET_DOMAIN and $DOMAIN" fi } function unchanged_cert { local DOMAIN="${1}" KEYFILE="${2}" CERTFILE="${3}" FULLCHAINFILE="${4}" CHAINFILE="${5}" } HANDLER=$1; shift; $HANDLER $@
全体的にひたすらgcloudコマンドを並べただけで汚い。
更新後のsleepは10秒程度だと安定しなかったので、長めに60秒とした。TTLと合わせてもっと短くできるかもしれない。もしくはステータスを確認してからやるか。
ドメインチェック以外、例外処理もやってないが、それは死活監視の方に任せるつもり。
次に必要な設定。
鍵の長さはデフォが4096、GAEは2048以下しか対応していないのでアップ時に怒られる。
実行するディレクトリにconfigというそのままの名前のファイルを作成して変更する。
config
KEYSIZE="2048"
実行コマンド。-xを追加すれば残り期限にかかわらず強制定期にアップデートする。
./dehydrated -c -d s.bizocean.jp --challenge dns-01 -k ./gae_hook.sh
こんな感じで実行されればおk。
途中でこけるとトランザクションが残っちゃうので実行前にabortした方がいいかもしれない。
# INFO: Using main config file /home/yu_yamazaki/letsencrypt/dehydrated/config Processing s.bizocean.jp + Checking domain name(s) of existing cert... unchanged. + Checking expire date of existing cert... + Valid till Oct 2 00:26:00 2017 GMT (Longer than 30 days). Ignoring because renew was forced! + Signing domains... + Generating private key... + Generating signing request... + Requesting challenge for s.bizocean.jp... Set TXT record of _acme-challenge.s.bizocean.jp to RsMwB34gCgdfmks-2LGpsH0MVpBZVYkdveANiAcTXlk dns update start ERROR: (gcloud.dns.record-sets.transaction.start) transaction already exists at [transaction.yaml] Record removal appended to transaction at [transaction.yaml]. Record addition appended to transaction at [transaction.yaml]. Executed transaction [transaction.yaml] for managed-zone [s-bizocean-jp]. Created [https://www.googleapis.com/dns/v1/projects/oceanus-dev/managedZones/s-bizocean-jp/changes/21]. ID START_TIME STATUS 21 2017-07-04T01:44:46.816Z pending dns update end sleep 60 + Responding to challenge for s.bizocean.jp... + Challenge is valid! + Requesting certificate... + Checking certificate... + Done! + Creating fullchain.pem... + Done!
期限内だったら何もせずに終了する
% ./dehydrated -c -d s.bizocean.jp --challenge dns-01 -k ./gae_hook.sh # INFO: Using main config file /home/BIZOCEAN/yu_yamazaki/letsencrypt/dehydrated/config Processing s.bizocean.jp + Checking domain name(s) of existing cert... unchanged. + Checking expire date of existing cert... + Valid till Oct 2 00:46:00 2017 GMT (Longer than 30 days). Skipping renew!
- 作者: Dan Sanderson,玉川竜司
- 出版社/メーカー: オライリージャパン
- 発売日: 2011/01/24
- メディア: 大型本
- 購入: 5人 クリック: 414回
- この商品を含むブログ (27件) を見る
仕事で使える!Google Cloud Platform 最新クラウドインフラ導入マニュアル (仕事で使える!シリーズ(NextPublishing))
- 作者: 吉積礼敏,福田潔
- 出版社/メーカー: インプレスR&D
- 発売日: 2016/03/25
- メディア: Kindle版
- この商品を含むブログを見る