Let’s Encryptの証明書自動更新をAWS CLIで実現した話

Tech

連日寒い日が続いていますね。
二十四節気では一年で一番寒いとされる時期のようです。

こんにちは。WYRDの豊田です。

2022年が始まってもう一ヵ月が経とうとしています。遅ればせながら明けましておめでとうございます。
2021年もあっという間に過ぎ去った感じですが、2022年はどんな一年になるでしょうか。

今回のブログでは、この年末年始の余暇を使ってメールサーバーのSSL証明書更新処理を自動化した話を書こうと思います。

なお、今回の記事ではLet’s EncryptやAWSに関する基礎的な解説はしていません。

背景

私が運用しているメールサーバーの証明書はLet’s Encryptを利用しています。そのため、3ヶ月おきに証明書の更新作業を行う必要があります。

Let’s Encryptの証明書更新にある程度詳しい方からの「cronで自動化すればいいのでは?」というツッコミが聞こえてきそうですね。
しかし、このサーバーは通常時80番ポートを開いておらず、HTTP-01チャレンジを行うには、事前に80番ポートを解放してあげる必要があるのです。

※認証の仕組みについては公式サイトの解説を参照ください

つまりSSL証明書を更新するときの手順は以下になります。

  1. AWSコンソールにログイン
  2. EC2セキュリティグループで80番ポートを開く
  3. EC2インスタンスにログイン
  4. 証明書更新コマンド(certbot renew)実行
  5. 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チャレンジを推奨しているようですが)

タイトルとURLをコピーしました