Certbot で発行した証明書を Heroku SSL で利用する

#Dev
#Heroku
#Certbot

調査目的で Heroku SSL を利用しなければならない状況に直面したので、Certbot で証明書を用意した。通常は Heroku の提供する Automated Certificate Management を利用するのが良い。

ACME Challenge

デフォルトは HTTP-01 Challenge で /.well-known/acme-challenge/<token> でリクエストを受け付ける必要がある。このためにコードを書き換えたくなかった。ので、 DNS-01 Challenge を利用した。Certbot の Manual プラグインには --preferred-challenges オプションがあり dns を指定できる。

https://certbot.eff.org/docs/using.html#manual

DNS-01 Challenge

コマンドを実行すると TXT レコードに追加する文字列が生成される。

$ sudo certbot certonly --manual --preferred-challenges dns
...

Please deploy a DNS TXT record under the name
_acme-challenge.playground.tetsuya.dev with the following value:

jO0IGpJ0...aJJ3UoYc

DNS に追加後 ENTER を押すと Verification が始まる。Congratulations! が表示されたら成功。

Heroku に証明書をアップロード

Manually uploading certificates and intermediaries の手順に沿ってアップロードする。

$ sudo heroku certs:add /etc/letsencrypt/live/playground.tetsuya.dev/fullchain.pem /etc/letsencrypt/live/playground.tetsuya.dev/privkey.pem
Resolving trust chain... done
Adding SSL certificate to ⬢ tetsuya-playground... done
Certificate details:
Common Name(s): playground.tetsuya.dev
Expires At:     2021-06-24 02:08 UTC
Issuer:         /C=US/O=Let's Encrypt/CN=R3
Starts At:      2021-03-26 02:08 UTC
Subject:        /CN=playground.tetsuya.dev
SSL certificate is verified by a root authority.

アップロードした証明書は certs:info で確認できる。

$ heroku certs
Name               Common Name(s)          Expires               Trusted  Type  Domains
─────────────────  ──────────────────────  ────────────────────  ───────  ────  ───────
carnotaurus-37360  playground.tetsuya.dev  2021-06-24 02:08 UTC  True     SNI   0

$ heroku certs:info --name carnotaurus-37360
Fetching SSL certificate carnotaurus-37360 info for ⬢ tetsuya-playground... done
Certificate details:
Common Name(s): playground.tetsuya.dev
Expires At:     2021-06-24 02:08 UTC
Issuer:         /C=US/O=Let's Encrypt/CN=R3
Starts At:      2021-03-26 02:08 UTC
Subject:        /CN=playground.tetsuya.dev
SSL certificate is verified by a root authority.

Heroku へカスタムドメインの追加

Add a custom domain with a subdomain の手順に沿ってカスタムドメインを登録する。

$ heroku domains:add playground.tetsuya.dev
Configure your app's DNS provider to point to the DNS Target thawing-mountain-5762.desolate-river-9090.herokuspace.com.
    For help, see https://devcenter.heroku.com/articles/custom-domains

The domain playground.tetsuya.dev has been enqueued for addition
Run heroku domains:wait 'playground.tetsuya.dev' to wait for completion
Adding playground.tetsuya.dev to ⬢ tetsuya-playground... done

追加後に表示される DNS Target を CNAME レコードに追加してしばらく待つと、カスタムドメインでのアクセスが可能になる。CNAME を忘れた場合 heroku domains で確認ができる。

$ heroku domains
=== tetsuya-playground Heroku Domain
tetsuya-playground.herokuapp.com

=== tetsuya-playground Custom Domains
Domain Name            DNS Record Type DNS Target                                                SNI Endpoint
playground.tetsuya.dev CNAME           thawing-mountain-5762.desolate-river-9090.herokuspace.com carnotaurus-37360

接続確認

アップロードした証明証が利用されているか確認。Issuer が Let's Encrypt になっていることがわかる。

$ curl -v https://playground.tetsuya.dev
...
* SSL connection using TLSv1.2 / ECDHE-RSA-CHACHA20-POLY1305
* ALPN, server accepted to use http/1.1
* Server certificate:
*  subject: CN=playground.tetsuya.dev
*  start date: Mar 26 02:08:42 2021 GMT
*  expire date: Jun 24 02:08:42 2021 GMT
*  subjectAltName: host "playground.tetsuya.dev" matched cert's "playground.tetsuya.dev"
*  issuer: C=US; O=Let's Encrypt; CN=R3
*  SSL certificate verify ok.