SSLのkeystoreを自動更新

SSLのkeystoreを自動更新

Let's EncryptのSSL証明書の自動更新と共にkeystore.jksも自動作成する方法。

関連ページ 参考URL
Let's Encryptは SSL証明書 を自動更新してくれるが、Tomcatでは、その証明書からkeystoreを作らないと結局サイトが動かなくなる。
いろいろ調べて、renewal-hooksディレクトリ以下に シェルスクリプト を置くと、証明書の自動更新直後にそれを実行してくれる事が分かった。

しかし何故かエラーが出てこのシェルスクリプトを実行してくれなかったので、結局自前の cron で自動実行することにした。
これらの顛末のメモ。

renewal-hooksを使ったkeystoreの更新

Ubuntu環境であれば、etc/letsencrypt/renewal-hooks/deployの下にシェルスクリプトを置くと、SSL更新と連動してそれが実行される。
このシェルの中にkeystoreを作成する処理すれば、理論上ユーザーは一切SSLを気にせずにサイトを運用できる。

自分の場合はサイトの運営にTomcatを使っているので、シェルの中身は下のような内容になる。
#!/bin/bash

#

LIVE_PATH=
[letsencrypt/live下のサイトフォルダ]

TOMCAT_PATH=
[tomcatのconfフォルダ]

PASS=
[パスワードの文字列]


CHAIN_PATH="${LIVE_PATH}"
[fullchainのファイル名]

PEM_PATH="${LIVE_PATH}"
[privkeyのファイル名]

P12_PATH="${LIVE_PATH}"
[pkcs12のファイル名]

JKS_FROM_PATH="${LIVE_PATH}"
[keystoreのファイル名]

JKS_TO_PATH="${TOMCAT_PATH}"
[keystoreのファイル名]


sudo rm -r "${P12_PATH}"

#pkcs12ファイルを作成

sudo openssl pkcs12 -export -in "${CHAIN_PATH}" -inkey "${PEM_PATH}" -out "${P12_PATH}" -password pass:"${PASS}"
#keystoreを作成

sudo keytool -importkeystore -destkeystore "${JKS_FROM_PATH}" -srckeystore "${P12_PATH}" -srcstoretype PKCS12 -srcstorepass "${PASS}" -deststorepass "${PASS}"
#keystoreをtomcatへコピー

sudo mv -f "${JKS_FROM_PATH}"  "${JKS_TO_PATH}"
#tomcatを再起動

sudo service tomcat restart

# EOF
keystoreの作成と、その前のpkcs12ファイルの作成には本来サーバ管理者によるパスワードの入力が必要。
ただパスワードを入力する必要があるならそれは自動更新と言わないので、コードの中にパスワードも押し込んでる。

bashの中にパスワードを直書きしてるのはセキュリティ的に少しヤバいもしれない。
自分はこれが限界だが知識がある人はもっとセキュアの方法に変えていいかも。

陥りやすい注意点として、このシェルファイルに適切な実行権限がない場合がある。
ls -lのコマンドを打ち込み、所有者の権限のxが有効になっているか確認する。

renewal-hooksのエラー

これで一見落着かと思いきや、3か月後にサイトを見に行ったら503になっていた。
503エラー

renewal-hooksが正しく動いてるかどうかは、--force-renewオプションを付けてrenewを実行する事で簡単にテストできる。
sudo certbot renew --force-renew
結果は下の通り。
renewal-hooksのエラー
赤文字でError output from deploy-hook commandという表記があり、おそらくこれが原因で正しく更新されなかったのだと思う。

自前のcronを使ったkeystoreの更新

そもそもcertbot renewの自動更新処理も、Linuxのcronを使って定期実行してるに過ぎないので、keystoreの作成も自前のcronで実行することにした。
Linux標準のcron設定のファイルを下のコードで開く。
sudo crontab -e
ファイルの一番下に、作成したシェルスクリプトを定期的に実行するスクリプトを追記。
下のコードでは、毎週日曜日の0時0分0秒にシェルを実行するように指定。
0 0 * * 0 sh 
[作成したシェルのパス]
0
0