Let's Encrypt 証明書の自動更新システムを作る
Let's Encrypt 証明書の自動更新システムを作る:
この記事は はてなエンジニア Advent Calendar 2018 11日目の記事です.
こんにちは,システムプラットフォーム部でSREをしているid:cohalzです.
はてなでは証明書を自動更新してくれる仕組みを作っており,今回はその紹介をします.
はてなの証明書自動更新といえば,はてなブログの独自ドメインにおける証明書自動更新システムのことを思い浮かべる人もいるかも知れません.
今回紹介するのは,そのシステムとは違う,開発チーム用に向けて作成したシステムとなります.
ここではブログの方のシステムについて紹介は行いませんが,少し前にGeekOut様にてはてなブログのHTTPS化に関する記事が公開されましたのでそちらをご覧ください.
geek-out.jp
大きな違いはシステムで使う認証方式および保存場所が違うことです.
Let's Encrypt における認証方式には以下の2つが存在します.
DNS-01を選んだ理由としては,証明書を取得するためのwebサーバが不要なのと,Route 53のレコードを書き換えるだけで済むことから選びました.
Route 53のレコードを書き換えるのもcliやAPIが揃っているため自動化しやすいというのもありました.
保存場所については今回S3を選択しました.
S3を選択した理由としては,可用性が高いのは勿論のこと,暗号化やバケットポリシーなど機密性も保証しやすかったためです.
ブログのシステムでは認証方式にHTTP-01,保存場所にDynamoDBを用いており,利用用途によってサービスを使い分けています.
はてなでは以前からLet's Encrypt証明書を利用しており,3ヶ月ごとに証明書を更新していました.
Let's Encrypt証明書をクライアントから取得し,ACMもしくは証明書ストアサーバにアップロードするという手順を行っていました.
これにはいくつか問題がありました.
AWS Certificate Manager: DNS を使用した、証明書のより簡単な検証
これにより,Route 53 を利用してドメインを管理している場合には,コンソールから数回操作するだけで,ACM上において証明書の取得・更新が行われるようになりました.
ただし,ACMの証明書はALBやELBに対して使うことが前提です.
はてなでは,ALBやELBを用いていないサービスおよび環境もあるため,利用場所を問わないLet's Encryptの証明書は変わらず必要になってきます.
また,Let's Encryptにてワイルドカード証明書のサポートが始まるタイミングでもあり,Let's Encrypt証明書の自動更新システムを作成することにしました.
2018年1月にワイルドカード証明書の発行を開始 - Let's Encrypt 総合ポータル
理由はいくつかありますが,はてなでは主に2つの理由によりワイルドカード証明書を利用しています.
ワイルドカード証明書では,その1枚の証明書を管理すれば良いため管理が楽になります.
crt.sh
そのため,特に開発環境やステージング環境では,開発用のドメインの存在が外部に漏れないように,ワイルドカード証明書でカバーされるドメインで環境構築を行う事が望ましいです.
最初に試したのはcertbotとhookを使ったものでした.
certbotとはcliでLet's Encrypt証明書の取得できるクライアントのことです.
certbot.eff.org
この,certbotにはドメイン認証の際にhookとしてスクリプトを渡すことができます.
User Guide — Certbot 0.29.0.dev0 documentation
そのhookとしてDNSのレコードセットを変更するスクリプトを指定してあげることで動作します.
certbotとhookのスクリプトをバッチ用サーバに配布*1し,実行することで実現しました.
cron等で定期実行後,バッチ用サーバに保存された証明書をサーバに配布という流れになります.
しかし,いくつかの課題点が見えてきました.
Lambdaで実装を始める前に問題点を洗い出し,設計思想をあらかじめ構築しました.
例えば以下の通りです.
流れは大きく3つに別れています.
cronなどを用いて,S3からのダウンロードとnginxをreloadする等のシェルスクリプトを実行すれば完全に自動化が可能になります.
以上のシステムを開発チームに使ってもらい,フィードバックからさらなる改善を行いました.
今回作成したシステムのうち,黒い枠線で囲った範囲をGitHubにて公開しました.
github.com
内部で使っているシステムですが,チーム内にOSS化をしたいと言ったところ快諾をいただきました.
はてなでは,過去にLet's Encryptへの寄付を行ったこともあります.
developer.hatenastaff.com
寄付や今回のOSS化のように,利用しているOSSやコミュニティへ様々な形で支援をしていきたいと考えています.
はてなでは,運用上の課題をシステム開発により解決していく/OSSやコミュニティへ支援をしていくSREを募集しています.
hatenacorp.jp
この記事は はてなエンジニア Advent Calendar 2018 11日目の記事です.
こんにちは,システムプラットフォーム部でSREをしているid:cohalzです.
はてなでは証明書を自動更新してくれる仕組みを作っており,今回はその紹介をします.
はてなの証明書自動更新といえば,はてなブログの独自ドメインにおける証明書自動更新システムのことを思い浮かべる人もいるかも知れません.
今回紹介するのは,そのシステムとは違う,開発チーム用に向けて作成したシステムとなります.
ここではブログの方のシステムについて紹介は行いませんが,少し前にGeekOut様にてはてなブログのHTTPS化に関する記事が公開されましたのでそちらをご覧ください.
geek-out.jp
ブログのシステムと何が違うのか
まずはじめに,何故ブログと別のシステムを作成したかについて説明します.大きな違いはシステムで使う認証方式および保存場所が違うことです.
Let's Encrypt における認証方式には以下の2つが存在します.
- HTTPによる認証(HTTP-01)
- DNSによる認証(DNS-01)
DNS-01を選んだ理由としては,証明書を取得するためのwebサーバが不要なのと,Route 53のレコードを書き換えるだけで済むことから選びました.
Route 53のレコードを書き換えるのもcliやAPIが揃っているため自動化しやすいというのもありました.
保存場所については今回S3を選択しました.
S3を選択した理由としては,可用性が高いのは勿論のこと,暗号化やバケットポリシーなど機密性も保証しやすかったためです.
ブログのシステムでは認証方式にHTTP-01,保存場所にDynamoDBを用いており,利用用途によってサービスを使い分けています.
システムを作成した経緯
次に,システムを作成した経緯について説明します.はてなでは以前からLet's Encrypt証明書を利用しており,3ヶ月ごとに証明書を更新していました.
Let's Encrypt証明書をクライアントから取得し,ACMもしくは証明書ストアサーバにアップロードするという手順を行っていました.
これにはいくつか問題がありました.
- 入れ替えの作業が煩雑で間違えやすい
- 管理する証明書が増えるだけ,作業量も増える
AWS Certificate Manager: DNS を使用した、証明書のより簡単な検証
これにより,Route 53 を利用してドメインを管理している場合には,コンソールから数回操作するだけで,ACM上において証明書の取得・更新が行われるようになりました.
ただし,ACMの証明書はALBやELBに対して使うことが前提です.
はてなでは,ALBやELBを用いていないサービスおよび環境もあるため,利用場所を問わないLet's Encryptの証明書は変わらず必要になってきます.
また,Let's Encryptにてワイルドカード証明書のサポートが始まるタイミングでもあり,Let's Encrypt証明書の自動更新システムを作成することにしました.
2018年1月にワイルドカード証明書の発行を開始 - Let's Encrypt 総合ポータル
なぜワイルドカード証明書が必要なのか
ここまでLet's Encryptの話をしてきましたが,なぜワイルドカード証明書が必要なのかという話をします.理由はいくつかありますが,はてなでは主に2つの理由によりワイルドカード証明書を利用しています.
証明書管理の手間を削減
ドメインにつき一つの証明書を取得する場合では,管理するドメインが多くなった際にコストがその分増加します.ワイルドカード証明書では,その1枚の証明書を管理すれば良いため管理が楽になります.
ドメイン情報の隠蔽
現在,証明書を取得するとCertificate Transparencyによりcrt.shのようなサイトでログが残り,証明書を取得したドメインが検索可能になります.crt.sh
そのため,特に開発環境やステージング環境では,開発用のドメインの存在が外部に漏れないように,ワイルドカード証明書でカバーされるドメインで環境構築を行う事が望ましいです.
certbotとhookを使う方式
以上の課題から,ワイルドカード証明書を自動取得・更新するシステムの構築を始めました.最初に試したのはcertbotとhookを使ったものでした.
certbotとはcliでLet's Encrypt証明書の取得できるクライアントのことです.
certbot.eff.org
この,certbotにはドメイン認証の際にhookとしてスクリプトを渡すことができます.
User Guide — Certbot 0.29.0.dev0 documentation
そのhookとしてDNSのレコードセットを変更するスクリプトを指定してあげることで動作します.
certbotとhookのスクリプトをバッチ用サーバに配布*1し,実行することで実現しました.
cron等で定期実行後,バッチ用サーバに保存された証明書をサーバに配布という流れになります.
しかし,いくつかの課題点が見えてきました.
- スクリプトを動かすサーバの保守・可用性
- エラーや通知のハンドリング
AWS Lambdaで動作する証明書更新システム
上で挙げた課題を解決するために,AWS Lambdaを採用しました.(以下Lambdaと表記します)Lambdaで実装を始める前に問題点を洗い出し,設計思想をあらかじめ構築しました.
例えば以下の通りです.
- 手作業を可能な限り減らし,自動化を目指す
- システムから最新の証明書を証明書ストアに保存する
- 可用性の高い証明書ストアを利用する
- 成功・失敗ともにSlack通知を行う
今回作成したシステムの構成図
流れは大きく3つに別れています.
- CloudWatch Logsから証明書を取得したいドメインをLambdaに送信
- Lambdaからcertbotを通してLet's EncryptサーバとRoute 53にAPIを叩き,証明書を取得
- 取得した証明書をS3バケットに保存
- 保存完了後,Slackに通知を行う(エラー時も通知を行う)
cronなどを用いて,S3からのダウンロードとnginxをreloadする等のシェルスクリプトを実行すれば完全に自動化が可能になります.
以上のシステムを開発チームに使ってもらい,フィードバックからさらなる改善を行いました.
- CloudWatch Logsに入力するJSONの入力チェックを行う
- 証明書保存先バケットへの書き込みが可能か事前にチェックする
- 無制限に書き込みが出来ないよう,LambdaからアクセスできるバケットをIAMで制限する
- 証明書をSSE-KMSで暗号化し,ストアにアクセスできるユーザをKMSによって制限する
実行開始と終了時に通知されます
今回作成したシステムのうち,黒い枠線で囲った範囲をGitHubにて公開しました.
github.com
内部で使っているシステムですが,チーム内にOSS化をしたいと言ったところ快諾をいただきました.
はてなでは,過去にLet's Encryptへの寄付を行ったこともあります.
developer.hatenastaff.com
寄付や今回のOSS化のように,利用しているOSSやコミュニティへ様々な形で支援をしていきたいと考えています.
はてなでは,運用上の課題をシステム開発により解決していく/OSSやコミュニティへ支援をしていくSREを募集しています.
hatenacorp.jp
*1:配布はdroot https://blog.yuuk.io/entry/droot を用いています
オリジナルのエンクロージャ: |
20181210164438.png |
コメント
コメントを投稿