連日寒い日が続いていますね。
二十四節気では一年で一番寒いとされる時期のようです。
こんにちは。WYRDの豊田です。
2022年が始まってもう一ヵ月が経とうとしています。遅ればせながら明けましておめでとうございます。
2021年もあっという間に過ぎ去った感じですが、2022年はどんな一年になるでしょうか。
今回のブログでは、この年末年始の余暇を使ってメールサーバーのSSL証明書更新処理を自動化した話を書こうと思います。
なお、今回の記事ではLet’s EncryptやAWSに関する基礎的な解説はしていません。
背景
私が運用しているメールサーバーの証明書はLet’s Encryptを利用しています。そのため、3ヶ月おきに証明書の更新作業を行う必要があります。
Let’s Encryptの証明書更新にある程度詳しい方からの「cronで自動化すればいいのでは?」というツッコミが聞こえてきそうですね。
しかし、このサーバーは通常時80番ポートを開いておらず、HTTP-01チャレンジを行うには、事前に80番ポートを解放してあげる必要があるのです。
※認証の仕組みについては公式サイトの解説を参照ください
つまりSSL証明書を更新するときの手順は以下になります。
- AWSコンソールにログイン
- EC2セキュリティグループで80番ポートを開く
- EC2インスタンスにログイン
- 証明書更新コマンド(
certbot renew
)実行 - EC2セキュリティグループで80番ポートを閉じる
手順としてはそれほど複雑ではないですが、3ヶ月おきに手動で実施するとなると結構面倒なので、前々から自動化したいと思っていました。
(DNS-01チャレンジなどの方法も検討しましたが、当時DNSの設定を動的に書き換える方法を思いつかず、断念した覚えがあります)
AWS CLIを使えるようにする
SSL証明書更新を自動化するには、「AWSコンソールから80番ポートを開かなければならない」点がネックになります。
これを自動化することができれば、自動化できたも同然です。
そこでAWS CLIを使って、コンソールにログインせずに80番ポートを開け閉めできるようにします。
AWSコンソールでの作業
AWS CLIからセキュリティグループの設定を変更するためには、まず専用のユーザー(IAM)を用意します。(名前は適当なものをつけます)
今回は自動化バッチから利用するだけなので、AWS認証情報タイプは「アクセスキー」だけでOKです。
次に作成したユーザーに適用するポリシーを用意します。
あらかじめAWS側が用意しているプリセットポリシーがありますが、余計な権限まで付与してしまう可能性があるので、必要最低限の権限に限定したポリシーを独自に用意した方が良いでしょう。
ということで、今回のユーザーには以下の権限を付与します。
ec2:AuthorizeSecurityGroupIngress # inboundの設定を追加できる権限 ec2:RevokeSecurityGroupIngress # inboundの設定を削除できる権限 ec2:DescribeSecurityGroups # セキュリティグループの設定一覧を取得できる権限
※この辺りの権限設定は、親子関係(ある権限を付与する時に、自動的に一緒に付与される権限)があったりするので、コンソールからGUIで設定すると楽です
これでAWS側での事前準備は終わりです。
クライアント側での作業
次はサーバー側の準備です。
AWS CLIを使ってリクエストするために、名前付きプロファイルを作成します。
$ aws configure --profile ec2-sg-update
4項目ほど入力を求められますが、AWSコンソールでユーザー作成時に発行されたアクセスキーIDやシークレットアクセスキーなどを入力します。
動作確認
ここまで作業が終われば、あとは実際にリクエストを送るだけです。
以下のコマンドで80番ポートを開いたり閉じたりできるはずです。
80番ポートを開く
$ aws ec2 authorize-security-group-ingress --group-id <セキュリティグループID> --protocol tcp --port 80 --cidr 0.0.0.0/0 --profile ec2-sg-update
80番ポートを閉じる
$ aws ec2 revoke-security-group-ingress --group-id <セキュリティグループID> --protocol tcp --port 80 --cidr 0.0.0.0/0 --profile ec2-sg-update
更新スクリプトを用意する
これでCLIベースでポートの解放が行えるようになりました。
あとはスクリプトを用意してcronで定期実行すればOKです。
スクリプトによる更新結果をSlackに通知するなど、もう少しカスタマイズすることで一層便利になりますが、その辺りについても今回は割愛します。
まとめ
長い間、手動で行っていた証明書更新作業を自動化できました。
AWSコンソールにログインしてポチポチせずに、コマンド一発で済むのはやはり楽ですね。
そういえば冒頭で断念したと書いたDNS-01チャレンジもAWS CLIと連携すればいけそうです。
DNS-01チャレンジなら80番ポートを解放することなく証明書の更新ができるので、状況によっては選択肢となるかも?(Let’s EncryptはHTTP-01チャレンジを推奨しているようですが)