[Let's Encrypt] DNS-01 challenge はいいぞ

  • DNS-01 challenge はいいぞ
  • certbot コマンドで出来ます。今回は Google Compute Engine と Google Cloud DNS を使っているの前提
  • CentOS 7系の話

certbot コマンドで DNS-01 challenge してみる

DNS-01 challenge は TXT レコードに特定の文字列を入れて認証する方法です。最近お気に入りです。

以下のメリットがあります。

  • IP制限していても関係ない
  • ポート80や443を開けていなくていい
  • ロードバランサー挟んでいたり、DNSラウンドロビンしてる時に、どっちに来るかわからない時とか このためだけの nginx の設定書く必要もなし(ぐぐったら nginx の設定でどうにかする方法がめっちゃ出てきた)
  • Aレコードを登録している必要もない
  • 内部のアプリケーションで使うだけみたいな時もまぁ使えなくもないかも(オレオレ証明書でいい気もしますが)

デメリットは

  • DNS の設定を変更出来る必要がある(できればAPIなどで)

くらいでしょうか。あまり思い浮かびません。

とりあえず今回は Google Cloud DNS を使ったやり方を試したいと思いますが、ヘルプを見る限り、以下のものに対応しています。

  • Cloudflare for DNS
  • CloudXNS for DNS
  • DigitalOcean for DNS
  • DNSimple for DNS
  • DNS Made Easy for DNS
  • Gehirn Infrastracture Service for DNS
  • Google Cloud DNS
  • Linode for DNS
  • LuaDNS for DNS
  • NS1 for DNS
  • OVH for DNS
  • BIND for DNS
  • Route53 for DNS
  • Sakura Cloud for DNS

certbot プラグインの準備

今回は certbot コマンドでやってみます。

GCEのインスタンスにログインして、certbot をインストールします。

インストールは、epel 有効にしたらすぐ出来るだろうと思ったのですが、うまくいかず 一旦 yum remove epel-release して、入れ直したところうまくいきました。

詳細なインストール方法は certbot の公式サイト を参照してください。

$ sudo certbot --help plugins
usage:

  certbot plugins [options]

optional arguments:
  -h, --help            show this help message and exit
  -c CONFIG_FILE, --config CONFIG_FILE
                        path to config file (default: /etc/letsencrypt/cli.ini
                        and ~/.config/letsencrypt/cli.ini)

plugins:
  Options for the "plugins" subcommand

  --init                Initialize plugins. (default: False)
  --prepare             Initialize and prepare plugins. (default: False)
  --authenticators      Limit to authenticator plugins only. (default: None)
  --installers          Limit to installer plugins only. (default: None)

plugins:
  Plugin Selection: Certbot client supports an extensible plugins
  architecture. See 'certbot plugins' for a list of all installed plugins
  and their names. You can force a particular plugin by setting options
  provided below. Running --help <plugin_name> will list flags specific to
  that plugin.

  --configurator CONFIGURATOR
                        Name of the plugin that is both an authenticator and
                        an installer. Should not be used together with
                        --authenticator or --installer. (default: Ask)
  -a AUTHENTICATOR, --authenticator AUTHENTICATOR
                        Authenticator plugin name. (default: None)
  -i INSTALLER, --installer INSTALLER
                        Installer plugin name (also used to find domains).
                        (default: None)
  --apache              Obtain and install certificates using Apache (default:
                        False)
  --nginx               Obtain and install certificates using Nginx (default:
                        False)
  --standalone          Obtain certificates using a "standalone" webserver.
                        (default: False)
  --manual              Provide laborious manual instructions for obtaining a
                        certificate (default: False)
  --webroot             Obtain certificates by placing files in a webroot
                        directory. (default: False)
  --dns-cloudflare      Obtain certificates using a DNS TXT record (if you are
                        using Cloudflare for DNS). (default: False)
  --dns-cloudxns        Obtain certificates using a DNS TXT record (if you are
                        using CloudXNS for DNS). (default: False)
  --dns-digitalocean    Obtain certificates using a DNS TXT record (if you are
                        using DigitalOcean for DNS). (default: False)
  --dns-dnsimple        Obtain certificates using a DNS TXT record (if you are
                        using DNSimple for DNS). (default: False)
  --dns-dnsmadeeasy     Obtain certificates using a DNS TXT record (if you are
                        using DNS Made Easy for DNS). (default: False)
  --dns-gehirn          Obtain certificates using a DNS TXT record (if you are
                        using Gehirn Infrastracture Service for DNS).
                        (default: False)
  --dns-google          Obtain certificates using a DNS TXT record (if you are
                        using Google Cloud DNS). (default: False)
  --dns-linode          Obtain certificates using a DNS TXT record (if you are
                        using Linode for DNS). (default: False)
  --dns-luadns          Obtain certificates using a DNS TXT record (if you are
                        using LuaDNS for DNS). (default: False)
  --dns-nsone           Obtain certificates using a DNS TXT record (if you are
                        using NS1 for DNS). (default: False)
  --dns-ovh             Obtain certificates using a DNS TXT record (if you are
                        using OVH for DNS). (default: False)
  --dns-rfc2136         Obtain certificates using a DNS TXT record (if you are
                        using BIND for DNS). (default: False)
  --dns-route53         Obtain certificates using a DNS TXT record (if you are
                        using Route53 for DNS). (default: False)
  --dns-sakuracloud     Obtain certificates using a DNS TXT record (if you are
                        using Sakura Cloud for DNS). (default: False)

結構たくさんあります。

早速使ってみます。

今あるプラグインを確認。

$ certbot plugins

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* apache
Description: Apache Web Server plugin
Interfaces: IAuthenticator, IInstaller, IPlugin
Entry point: apache = certbot_apache.entrypoint:ENTRYPOINT

* nginx
Description: Nginx Web Server plugin
Interfaces: IAuthenticator, IInstaller, IPlugin
Entry point: nginx = certbot_nginx.configurator:NginxConfigurator

* standalone
Description: Spin up a temporary webserver
Interfaces: IAuthenticator, IPlugin
Entry point: standalone = certbot.plugins.standalone:Authenticator

* webroot
Description: Place files in webroot directory
Interfaces: IAuthenticator, IPlugin
Entry point: webroot = certbot.plugins.webroot:Authenticator
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
$ sudo certbot certonly --dns-google -d hoge.grasys.tech
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Could not choose appropriate plugin: The requested dns-google plugin does not appear to be installed
The requested dns-google plugin does not appear to be installed

プラグインは別途インストールが必要でした(そりゃ一覧にないからな)。入れましょう。

certbot コマンドではできないようなので、 yum で。

sudo yum install python-certbot-google-dns

yum じゃない場合は

pip install certbot-dns-google

とか。

一覧を再度確認します。

$ certbot plugins

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* dns-google
Description: Obtain certificates using a DNS TXT record (if you are using Google
Cloud DNS for DNS).
Interfaces: IAuthenticator, IPlugin
Entry point: dns-google = certbot_dns_google.dns_google:Authenticator

* standalone
Description: Spin up a temporary webserver
Interfaces: IAuthenticator, IPlugin
Entry point: standalone = certbot.plugins.standalone:Authenticator

* webroot
Description: Place files in webroot directory
Interfaces: IAuthenticator, IPlugin
Entry point: webroot = certbot.plugins.webroot:Authenticator
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

apache とか nginx のが消えたのですがががが・・・

使わないので先に進みましょう

まずはヘルプを読みます。

$ certbot --help dns-google
usage:
  certbot [SUBCOMMAND] [options] [-d DOMAIN] [-d DOMAIN] ...

Certbot can obtain and install HTTPS/TLS/SSL certificates.  By default,
it will attempt to use a webserver both for obtaining and installing the
certificate.

optional arguments:
  -h, --help            show this help message and exit
  -c CONFIG_FILE, --config CONFIG_FILE
                        path to config file (default: /etc/letsencrypt/cli.ini
                        and ~/.config/letsencrypt/cli.ini)

dns-google:
  Obtain certificates using a DNS TXT record (if you are using Google Cloud
  DNS for DNS).

  --dns-google-propagation-seconds DNS_GOOGLE_PROPAGATION_SECONDS
                        The number of seconds to wait for DNS to propagate
                        before asking the ACME server to verify the DNS
                        record. (default: 60)
  --dns-google-credentials DNS_GOOGLE_CREDENTIALS
                        Path to Google Cloud DNS service account JSON file.
                        (See https://developers.google.com/identity/protocols/
                        OAuth2ServiceAccount#creatinganaccount forinformation
                        about creating a service account and
                        https://cloud.google.com/dns/access-
                        control#permissions_and_roles for information about
                        therequired permissions.) (default: None)

GCE上などで実行するか、別途 Google Cloud DNS を操作可能なサービスアカウントの JSON ファイルを用意しておく必要があります。

今回は GCE上で実行します。 ローカルのMacからやろうとしたら、MetaDataが取れないせいか gcloud auth login していても --dns-google-credentials しないとダメでした。

やってみる

$ sudo certbot certonly --dns-google -d hoge.grasys.tech
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator dns-google, Installer None
Enter email address (used for urgent renewal and security notices) (Enter 'c' to
cancel): YOUR@MAILADDRESS
Starting new HTTPS connection (1): acme-v02.api.letsencrypt.org

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Please read the Terms of Service at
https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf. You must
agree in order to register with the ACME server at
https://acme-v02.api.letsencrypt.org/directoryß
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(A)gree/(C)ancel: A

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Would you be willing to share your email address with the Electronic Frontier
Foundation, a founding partner of the Let's Encrypt project and the non-profit
organization that develops Certbot? We'd like to send you email about our work
encrypting the web, EFF news, campaigns, and ways to support digital freedom.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(Y)es/(N)o: N
Obtaining a new certificate
Performing the following challenges:
dns-01 challenge for hoge.grasys.tech
URL being requested: GET https://www.googleapis.com/discovery/v1/apis/dns/v1/rest
URL being requested: GET https://dns.googleapis.com/dns/v1/projects/YOUR_PROJECT/managedZones?alt=json&dnsName=hoge.grasys.tech.
Attempting refresh to obtain initial access_token
URL being requested: GET https://dns.googleapis.com/dns/v1/projects/YOUR_PROJECT/managedZones?alt=json&dnsName=grasys.tech.
URL being requested: GET https://dns.googleapis.com/dns/v1/projects/YOUR_PROJECT/managedZones/XXXXXXXXXXXXXXXXXX/rrsets?alt=json
URL being requested: POST https://dns.googleapis.com/dns/v1/projects/YOUR_PROJECT/managedZones/XXXXXXXXXXXXXXXXXX/changes?alt=json
URL being requested: GET https://dns.googleapis.com/dns/v1/projects/YOUR_PROJECT/managedZones/XXXXXXXXXXXXXXXXXX/changes/255?alt=json
Waiting 60 seconds for DNS changes to propagate
Waiting for verification...
Cleaning up challenges
URL being requested: GET https://www.googleapis.com/discovery/v1/apis/dns/v1/rest
URL being requested: GET https://dns.googleapis.com/dns/v1/projects/YOUR_PROJECT/managedZones?alt=json&dnsName=hoge.grasys.tech.
Attempting refresh to obtain initial access_token
URL being requested: GET https://dns.googleapis.com/dns/v1/projects/YOUR_PROJECT/managedZones?alt=json&dnsName=grasys.tech.
URL being requested: GET https://dns.googleapis.com/dns/v1/projects/YOUR_PROJECT/managedZones/XXXXXXXXXXXXXXXXXX/rrsets?alt=json
URL being requested: POST https://dns.googleapis.com/dns/v1/projects/YOUR_PROJECT/managedZones/XXXXXXXXXXXXXXXXXX/changes?alt=json

IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at:
   /etc/letsencrypt/live/hoge.grasys.tech/fullchain.pem
   Your key file has been saved at:
   /etc/letsencrypt/live/hoge.grasys.tech/privkey.pem
   Your cert will expire on 2019-11-20. To obtain a new or tweaked
   version of this certificate in the future, simply run certbot
   again. To non-interactively renew *all* of your certificates, run
   "certbot renew"
 - Your account credentials have been saved in your Certbot
   configuration directory at /etc/letsencrypt. You should make a
   secure backup of this folder now. This configuration directory will
   also contain certificates and private keys obtained by Certbot so
   making regular backups of this folder is ideal.
 - If you like Certbot, please consider supporting our work by:

   Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate
   Donating to EFF:                    https://eff.org/donate-le

できました。 手動で TXT レコード入れたりしないといけないのか?!???!!! とかなっていましたが、全て自動でやってくれました。

更新は certbot renew するだけでよさそうですが --dns-google-credentials つけて実行したドメインの設定ファイルを覗いてみたところ

/etc/letsencrypt/renewal/DOMAIN_NAME.conf

dns_google_credentials = PROJECT_NAME-0000000000000.json

ってなってたので、cron で renew 実行したい場合は、フルパスで指定しておいたほうが安心かもしれません。

AWS で EC2+Route53 でもためそうと思ったのですが、Route53 を使っているドメインが手元になかったので、そのうち。

それでは今回はこの辺で。