Let’s Encrypt でワイルドカードな SSL 証明書取得 (DNS-01 方式、Route 53)

ワイルドカード証明書は DNS-01 方式によるドメイン認証 (対象ドメインの DNS サーバーへ指定された認証用 TXT レコードを追加して検証する方式) 限定らしいです。

・ Does Let’s Encrypt issue wildcard certificates?

Yes. Wildcard issuance must be done via ACMEv2 using the DNS-01 challenge. See this post for more technical information.
FAQ – Let’s Encrypt – Free SSL/TLS Certificates

前提

以下、Route 53 のレコードセットをいじるため、少なくとも下記のようなポリシーがアタッチされた IAM ユーザーのアクセスキー、もしくは IAM ロールがアタッチされた EC2 インスタンスなどが必要になります。

{
    "Version": "2012-10-17",
    "Id": "certbot-dns-route53 sample policy",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "route53:ListHostedZones",
                "route53:GetChange"
            ],
            "Resource": [
                "*"
            ]
        },
        {
            "Effect" : "Allow",
            "Action" : [
                "route53:ChangeResourceRecordSets"
            ],
            "Resource" : [
                "arn:aws:route53:::hostedzone/${Route 53 の Hosted Zone ID}"
            ]
        }
    ]
}

参考: certbot/sample-aws-policy.json at master · certbot/certbot

Certbot を使う場合

こちらの記事を参考に Docker 化しました > hiraro/letsencrypt_with_certbot_dns_route53_docker

証明書の発行方法

Git でクローン。

git clone https://github.com/hiraro/letsencrypt_with_certbot_dns_route53_docker.git
cd letsencrypt_with_certbot_dns_route53_docker

Docker イメージをビルド。

docker build -t local/certbot_r53 .

ステージング CA サーバーで動作確認。 EMAIL は Let’s Encrypt の規約に同意する際、必要なメールアドレスです。

$(pwd)/letsencrypt に証明書が発行されますが、ここで発行される証明書はテスト用のため、実際に有効なものではありません。

docker run --rm \
    -v $(pwd)/letsencrypt:/etc/letsencrypt \
    -e AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID} \
    -e AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY} \
    -e EMAIL=${EMAIL} \
    -e DOMAINS="example.com,*.example.com" \
    -e USE_STAGING_SERVER=1 \
    local/certbot_r53

本番 CA サーバーで本物の証明書を発行。

docker run --rm \
    -v $(pwd)/letsencrypt:/etc/letsencrypt \
    -e AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID} \
    -e AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY} \
    -e EMAIL=${EMAIL} \
    -e DOMAINS="example.com,*.example.com" \
    local/certbot_r53doc

注意点

Docker 化した理由は、Certbot がいろんな 依存パッケージ を勝手にインストールし始めるためです。

政治的な事情で、勝手に Docker や任意のパッケージをインストールすることが難しい場合、Certbot は残念ながら使えません。

lego を使う場合

lego とは

Go 製の Let’s Encrypt クライアント。

Let’s Encrypt client and ACME library written in Go
xenolf/lego: Let’s Encrypt client and ACME library written in Go

Let’s Encrypt の公式サイト でも紹介されているし、 GitHub のスター数も 2800 以上あるので、まぁ信頼できるのでは。

証明書の発行

Go 製なので、ひとつのバイナリファイルを GitHub のリリースページから wget 等でダウンロードしてくるだけでインストール完了。 コマンドオプション等は Certbot とほぼ同様かと。

ステージング CA で動作確認。 $(pwd)/letsencrypt に証明書が発行されます。

export AWS_ACCESS_KEY_ID="xxxxxxxxxxxxxxxxx"
export AWS_SECRET_ACCESS_KEY="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"

lego \
    --path ./letsencrypt \
    --server "https://acme-staging-v02.api.letsencrypt.org/directory" \
    --accept-tos \
    --email "${EMAIL}" \
    --dns="route53" \
    --domains "example.com" \
    --domains "*.example.com" \
    run

本番 CA で発行。

lego \
    --path ./letsencrypt \
    --accept-tos \
    --email "${EMAIL}" \
    --dns="route53" \
    --domains "example.com" \
    --domains "*.example.com" \
    run

Docker 化するまでも無いが、一応 Docker でも簡単にできる。

docker pull xenolf/lego
# ステージング CA
docker run --rm \
    -v $(pwd)/letsencrypt:/etc/letsencrypt \
    -e AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID} \
    -e AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY} \
    xenolf/lego \
        --path /etc/letsencrypt \
        --server "https://acme-staging-v02.api.letsencrypt.org/directory" \
        --accept-tos \
        --email ${EMAIL}\
        --dns="route53" \
        --domains "example.com" \
        --domains "*.example.com" \
        run

# 本番 CA
docker run --rm \
    -v $(pwd)/letsencrypt:/etc/letsencrypt \
    -e AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID} \
    -e AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY} \
    xenolf/lego \
        --path /etc/letsencrypt \
        --accept-tos \
        --email ${EMAIL}\
        --dns="route53" \
        --domains "example.com" \
        --domains "*.example.com" \
        run