acmesmithでSSL証明書を管理する
開発環境などのテンポラリな環境でSSL証明書を利用したい場合はLet's Encryptが便利です。Let's Encryptの証明書を管理するツールにはcertbotやlegoなどがありますが、それらは鍵や証明書をローカルディスクに格納するため、他のサーバで証明書を利用したい場合に鍵や証明書を安全に配布する仕組みが必要になります。また、発行済みの証明書が複数のサーバに分散してしまうと、有効期限やSAN(Subject Alternative Name)の更新に多大な手間がかかります。
そこで、acmesmithというツールを利用すると、S3などのストレージで鍵や証明書を一元管理できます。これにより、複数のサーバで証明書を利用する場合の運用がとても楽になります。
本稿では、acmesmithを利用して証明書を運用する方法を説明します。ここでは、Route53でドメインを管理しており、S3が利用できる前提とします。
準備
以下のIAMロールを持つIAMユーザを作成します。YOUR_BUCKET
はS3のバケット名、YOUR_HOSTED_ZONE
はRoute53のゾーンIDに置き換えてください。
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": ["s3:GetObject", "s3:PutObject", "s3:ListBucket"], "Resource": ["arn:aws:s3:::YOUR_BUCKET", "arn:aws:s3:::YOUR_BUCKET/cert"] }, { "Effect": "Allow", "Action": ["route53:ListHostedZones", "route53:GetChange"], "Resource": "*" }, { "Effect": "Allow", "Action": "route53:ChangeResourceRecordSets", "Resource": ["arn:aws:route53:::hostedzone/YOUR_HOSTED_ZONE"] } ] }
IAMキーを取得したら、以下の内容でacmesmith.ymlを作成します。YOUR_PASSPHRASE
は鍵のパスフレーズなので適当なものに置き換えてください。
endpoint: https://acme-v01.api.letsencrypt.org/ storage: type: s3 region: ap-northeast-1 bucket: YOUR_BUCKET prefix: cert aws_access_key: access_key_id: IAM_KEY secret_access_key: IAM_SECRET challenge_responders: - route53: aws_access_key: access_key_id: IAM_KEY secret_access_key: IAM_SECRET account_key_passphrase: YOUR_PASSPHRASE1 certificate_key_passphrase: YOUR_PASSPHRASE2
acmesmithはRubyGemsで提供されています。
gem install acmesmith
初期登録と更新
まずは、Let's Encryptのアカウント登録と証明書発行を行います。ドメインの所有者であることの確認(ACME Challenge)はRoute53で行われます。
acmesmith register mailto:[email protected] acmesmith authorize example.com acmesmith request example.com acmesmith list
証明書のリストが表示されれば成功です。S3にはLet's Encryptのアカウント鍵、SSL証明書とその秘密鍵が格納されます。
期限切れが近い証明書を更新するには以下を実行します。デフォルトでは期限切れ7日前を過ぎたら更新されます。そうでない場合は何もしないので、何回実行しても大丈夫です。
acmesmith autorenew
鍵や証明書はS3にあるので、IAMキーさえ設定すれば他のサーバでも証明書を取得できます。これもACMEサーバには問い合わせないので、何回実行しても大丈夫です。
acmesmith show-certificate example.com acmesmith show-private-key example.com
Dockerで実行する
すでにWebサーバをDockerで運用している場合、acmesmithもDockerで実行するとよいでしょう。ここではRubyのイメージにacmesmithとacmesmith.ymlを追加します。
# acmesmith/Dockerfile FROM ruby:2 RUN gem install acmesmith ADD acmesmith.yml / ENTRYPOINT ["acmesmith"]
# /docker-compose.yml version: "2" services: acmesmith: build: acmesmith
以下のコマンド群で証明書を生成できます。
docker-compose build acmesmith docker-compose run --rm acmesmith autorenew docker-compose run --rm acmesmith show-certificate example.com > cert.pem docker-compose run --rm acmesmith show-private-key example.com > key.pem
生成された証明書をWebサーバに追加するとHTTPSが利用できるようになります。
証明書を更新する際にはイメージのリビルドとコンテナの再起動が必要になるため、およそ90日ごとに数秒のダウンタイムが発生します*1。
最後に、acmesmithで生成した証明書をnginxで利用する例を公開します。
*1:Let's Encryptの用途を考えると、数秒のダウンタイムを許容できないケースは少ないかと思います。ダウンタイムを許容できない場合はボリューム経由で証明書を渡してシグナルを投げるといった工夫が必要です。