さくらウェブアクセラレータで使うドメインのSSL証明書更新
弊社ではサイトのCDNとして「さくらウェブアクセラレータ」を利用していて、そのドメインの証明書はLet's Encryptで発行しています。 Let's Encryptの証明書は有効期限が90日なので、3ヶ月に一度くらい証明書の入れ替えが必要です。
運用を始めた頃は、実体のサーバーがCDNの背後にあるので、証明書発行を毎回DNS認証で行なっていたのですが、良く考えたらACMEでも認証tokenは毎回発行されるので、オリジンサーバー上でcertbotを実行することで発行することができるなあと思いました。
ネットで色々と調べて、結果、証明書の入れ替えまでを自動化できたので、その方法を記事にしたいと思います。
Let's Encryptの証明書発行
ACMEのためのwebサーバー設定
弊社のサイトのフロントエンドはnginxを使用しているのですが、ACMEのために.well-knownフォルダにアクセスできるようにオリジンサーバーのnginxのconfに以下の設定を追加します。
location /.well-known { root /var/www/nginx/certbot; }
証明書発行
オリジンサーバー上で、以下のコマンドを実行します。
certbot-auto certonly --webroot -w /var/www/nginx/certbot -d ドメイン名 -m root@eatsmart.co.jp --agree-tos -n
これで、オリジンサーバーの/etc/letsencrypt/live/ドメイン名
配下に証明書と鍵が生成されます。
証明書更新
さくらウェブアクセラレータのAPIを使用することで、証明書の更新を自動化することができます。
まずは、以下のURLからAPIキー(アクセストークン、トークンシークレット)を発行する必要があります。
サイトID取得
初回は、まず操作対象のサイトIDを取得する必要があります。 サイトIDは、以下のコマンドで確認できます。
$ curl -X GET --user "アクセストークン":"トークンシークレット" \ https://secure.sakura.ad.jp/cloud/zone/is1a/api/webaccel/1.0/site { "Total": 3, "From": 0, "Count": 3, "Sites": [ { "Index": 0, "ID": "XXXXXXXXXXXXXX", "Name": "cdn1.esimg.jp", "Domain": "cdn1.esimg.jp", "DomainType": "own_domain", ・・・ ], "is_ok": true } (JSONを整形しています)
このIDの値を使用します。
証明書更新
更新は以下のコマンドでできます。
curl -X PUT --user "アクセストークン":"トークンシークレット" \ https://secure.sakura.ad.jp/cloud/zone/is1a/api/webaccel/1.0/site/113000168864/certificate \ -d "{\"Certificate\": { \"CertificateChain\": \"$(perl -pe 's/\n/\\n/' /etc/letsencrypt/live/ドメイン名/fullchain.pem | perl -pe 's/\\n$//')\", \"Key\": \"$(perl -pe 's/\n/\\n/' /etc/letsencrypt/live/ドメイン名/privkey.pem | perl -pe 's/\\n$//')\" }}"
まとめ
上のふたつをまとめ、以下のようなシェルを作って更新するようにしました。
$ cat replace_cdn_cert.sh #!/bin/sh TARGET=$1 SITE_ID=$2 echo 'target:'$TARGET echo 'siteId:'$SITE_ID certbot-auto certonly --webroot -w /var/www/nginx/certbot -d $TARGET -m root@eatsmart.co.jp --agree-tos -n curl -X PUT --user "アクセストークン":"トークンシークレット" \ https://secure.sakura.ad.jp/cloud/zone/is1a/api/webaccel/1.0/site/$SITE_ID/certificate \ -d "{\"Certificate\": { \"CertificateChain\": \"$(perl -pe 's/\n/\\n/' /etc/letsencrypt/live/$TARGET/fullchain.pem | perl -pe 's/\\n$//')\", \"Key\": \"$(perl -pe 's/\n/\\n/' /etc/letsencrypt/live/$TARGET/privkey.pem | perl -pe 's/\\n$//')\" }}" $ ./replace_cdn_cert.sh cdn1.esimg.jp XXXXXXXXXXXXXX
これで、証明書更新の通知が憂鬱ではなくなりました!