ShellScript
docker
route53
letsencrypt

Let's Encryptの証明書をroute53とDockerで自動取得

DNS-01方式

Let's Encryptにはいくつか認証方式があり、TXTレコードにvlidation codeを書いて認証するのがDNS-01方式になります。

certbotを実行すると以下のように表示されます

Please deploy a DNS TXT record under the name
_acme-challenge.sample.domain.com with the following value:

j7cahB2LuYhD0nu13_AqDut5R6W5GzLjqaQYrhJ6pew

Before continuing, verify the record is deployed.
-------------------------------------------------------------------------------
Press Enter to Continue

  
Route53などのDNS as a serviceを使っていればCLIやGUIからさくっとレコード作成すればよいのでとても便利です。

今回はさらに利便性を高めるためにコマンド一発で証明書の取得ができるようにしたいと思います。

hook

https://certbot.eff.org/docs/using.html#pre-and-post-validation-hooks
↑によると--manual-auth-hook--manual-cleanup-hookというロングオプションでvalidationの前後にスクリプト実行ができる模様です。
そこで--manual-auth-hookでroute53にtxtレコードを追加し、--manual-cleanup-hookでそのtxtレコードを削除したいと思います。

(参考)route53

レコード追加

aws route53 change-resource-record-sets --hosted-zone-id <zoneid>--change-batch file://upsert.json
upsert.json
{'Comment': 'upsert for update of lets ecnrypt',
  'Changes': [
    {
      'Action': 'UPSERT',
      'ResourceRecordSet': {
        'ResourceRecords': [
          {
            'Value': '\"j7cahB2LuYhD0nu13_AqDut5R6W5GzLjqaQYrhJ6pew\"'
          }
        ],
        'Type': 'TXT',
        'Name': 'sample.domain.com',
        'TTL': 300
      }
    }
  ]
}

レコード削除

aws route53 change-resource-record-sets --hosted-zone-id <zoneid>--change-batch file://delete.json
upsert.json
{'Comment': 'upsert for update of lets ecnrypt',
  'Changes': [
    {
      'Action': 'DELETE',
      'ResourceRecordSet': {
        'ResourceRecords': [
          {
            'Value': '\"j7cahB2LuYhD0nu13_AqDut5R6W5GzLjqaQYrhJ6pew\"'
          }
        ],
        'Type': 'TXT',
        'Name': 'sample.domain.com',
        'TTL': 300
      }
    }
  ]
}

自動取得

これらを行うdockerを作りました。
https://github.com/tkykm/docker-certbot-route53
https://hub.docker.com/r/tkykm/certbot-route53/

$ yes | docker run -i -e AWS_ACCESS_KEY_ID=xxx \
-e AWS_SECRET_ACCESS_KEY=yyy \
-e AWS_ROUTE53_HOSTED_ZONE_ID=zzz \
--rm tkykm/certbot-route53 \
-m address@gmail.com \
-d sample.domain.com
-d hoge.sample.domain.com
-d api.sample.domain.com 
-----BEGIN CERTIFICATE-----
MIIFLTCCBBWgAwIBAgISAwiBfVYm3OfhF8+UNVpZEs6zMA0GCSqGSIb3DQEBCwUA
MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQD
ExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMzAeFw0xNzEyMjYwNTM2MzFaFw0x
ODAzMjYwNTM2MzFaMDAxLjAsBgNVBAMTJWFvZ2VyYWRvbWFpbi50YW1hLmFzLmNs
2ghDmtXsl2YlmyUhEkKQjHOCDvcHx3FsqY9RzmUJ97JI3/w3eq/+jz2FV49aWaqW
Cx8j2wM9vR+AmGfs8NTebM/ck7FCG7LVaTco0Yi/x9/gE2sQQ2CCCy5j1dYbHPej
0pe6pmgOoSJUp1oyNQBdCCf+QpkyfagVAoieBrSjeKPXoS41Q9e+VDxXsUwTtgZ4
xLv97wV+qWKkB8W6LZojHDr47ytu79dbRo1k7F7ZXm66ws3wxyni6LN5ivrXqI8p
RYyaJyn9Cheuu3rGZ/JfSWDnmCqlVSYZ0wvoxGHN7d5q1+gFup22ySBHqyvzkbj/
vjMKN7/SG6avwv6SROvNCWh7V6cEOFxjD+LwZmn7wS4L+mRI/ptHzRKUCwle34MY
H1boNQGUZg1/53tZw0V/WTkJaRNTQO/WKygx+xfF0nl1EMJIbHQBtzJp5UVtg04C
kHiyp+yNPmSO23qII8gFcQs9b9Snu1dFkjQ8DhGV4wtU8uSaq0uBuf9gG44dUbCa
gIO7qIX55TMIZWw7sAFdTNwMg7yFtczcOT2QiEORkzsF3lctY2Vj6GCy/1E9rVQ+
zTZR6BtthhXcLe66YVfEARbb8ufVozzZByd0beEAQKI5XEUKClrNWbrOBftG4FjB
bM/oOPgD5/HzWqMcVTMv5CQBrSagMBZgXRq1FS37n66l5bLD+qrYaQu7Gzq3UcD4
dlDFwLsXtOk7qmbBmH8DlG++A6Ew9WVd3Frae0yJgsvmaDX5qDpQcxflWFPFpnBy
9qojVOPMvS/qYy/bFQp0KsMFTgtlPy+U0Mi5HrpTx4cLwEnOd1CWXNucLlEcHExu
KEBRiqBWxkfPlXBiSblmehUUSiPwO8q2kzsNOHNbpc4LDwxMcVoXw9d6J/5HLWhN
S1vZ/Ie0zco8b9pb8A46PaC7QEL3e/E6hh2bdCf6m4HtNzHogkzCp3vCL3gvzF/6
ean3XYbaxgHxjJ+WV3Q6xvmeAvRgAOh0Zv14u635/t9V8JeAieIoZ7QYdv6uOrKY
+Lmb2SrorpaXkZgQfhQGtKiaItONXHH2nbClR9nKZNa5nANhbv78TQPkdiMrqCPA
2f6ZsjI9JnD9B3+QMLITjVpNvU4cxxm8DqlALBtdT1IEno+WreTmzOVWgi46MKOT
TgrbDhhBdWLyIETkwcyIbDm9fVdTuOhmajuKTIwVVKQng4Yf5EBuIKWYMBoTg37I
YjGXGmL3YSj0OVgcTxsdQIafifIMWRk4eC5zVFi+D9sayEyNRk/4qMVC+6gTZeOJ
0E5Kf2bdmqhgre061+cfnsG3o039d6wamH63S7iVArfKoArPW68SOA+3KChmAZ+g
OJ/0/iuNoYffrlO+zk57NfRE2fvPXrD8g4uh7Kolahl5tN/uT0siPkL7vThiVB+x
6mui8eqxOuCKv7Ne5NY6But3TpeJHIYSX/U95NXcpVKB
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIEkjCCA3qgAwIBAgIQCgFBQgAAAVOFc2oLheynCDANBgkqhkiG9w0BAQsFADA/
2ghDmtXsl2YlmyUhEkKQjHOCDvcHx3FsqY9RzmUJ97JI3/w3eq/+jz2FV49aWaqW
Cx8j2wM9vR+AmGfs8NTebM/ck7FCG7LVaTco0Yi/x9/gE2sQQ2CCCy5j1dYbHPej
0pe6pmgOoSJUp1oyNQBdCCf+QpkyfagVAoieBrSjeKPXoS41Q9e+VDxXsUwTtgZ4
xLv97wV+qWKkB8W6LZojHDr47ytu79dbRo1k7F7ZXm66ws3wxyni6LN5ivrXqI8p
RYyaJyn9Cheuu3rGZ/JfSWDnmCqlVSYZ0wvoxGHN7d5q1+gFup22ySBHqyvzkbj/
vjMKN7/SG6avwv6SROvNCWh7V6cEOFxjD+LwZmn7wS4L+mRI/ptHzRKUCwle34MY
H1boNQGUZg1/53tZw0V/WTkJaRNTQO/WKygx+xfF0nl1EMJIbHQBtzJp5UVtg04C
kHiyp+yNPmSO23qII8gFcQs9b9Snu1dFkjQ8DhGV4wtU8uSaq0uBuf9gG44dUbCa
gIO7qIX55TMIZWw7sAFdTNwMg7yFtczcOT2QiEORkzsF3lctY2Vj6GCy/1E9rVQ+
zTZR6BtthhXcLe66YVfEARbb8ufVozzZByd0beEAQKI5XEUKClrNWbrOBftG4FjB
bM/oOPgD5/HzWqMcVTMv5CQBrSagMBZgXRq1FS37n66l5bLD+qrYaQu7Gzq3UcD4
dlDFwLsXtOk7qmbBmH8DlG++A6Ew9WVd3Frae0yJgsvmaDX5qDpQcxflWFPFpnBy
9qojVOPMvS/qYy/bFQp0KsMFTgtlPy+U0Mi5HrpTx4cLwEnOd1CWXNucLlEcHExu
KEBRiqBWxkfPlXBiSblmehUUSiPwO8q2kzsNOHNbpc4LDwxMcVoXw9d6J/5HLWhN
S1vZ/Ie0zco8b9pb8A46PaC7QEL3e/E6hh2bdCf6m4HtNzHogkzCp3vCL3gvzF/6
ean3XYbaxgHxjJ+WV3Q6xvmeAvRgAOh0Zv14u635/t9V8JeAieIoZ7QYdv6uOrKY
+Lmb2SrorpaXkZgQfhQGtKiaItONXHH2nbClR9nKZNa5nANhbv78TQPkdiMrqCPA
2f6ZsjI9JnD9B3+QMLITjVpNvU4cxxm8DqlALBtdT1IEno+WreTmzOVWgi46MKOT
TgrbDhhBdWLyIETkwcyIbDm9fVdTuOhmajuKTIwVVKQng4Yf5EBuIKWYMBoTg37I
YjGXGmL3YSj0OVgcTxsdQIafifIMWRk4eC5zVFi+D9sayEyNRk/4qMVC+6gTZeOJ
0E5Kf2bdmqhgre061+cfnsG3o039d6wamH63S7iVArfKoArPW68SOA+3KChmAZ+g
X4Po1QYz+3dszkDqMp4fklxBwXRsW10KXzPMTZ+sOPAveyxindmjkW8lGy+QsRlG
PfZ+G6Z6h7mjem0Y+iWlkYcV4PIWL1iwBi8saCbGS5jN2p8M+X+Q7UNKEkROb3N6
KOqkqm57TH2H3eDJAkSnh6/DNFu0Qg==
-----END CERTIFICATE-----
-----BEGIN PRIVATE KEY-----
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCyQYbX37giBjqG
kBb9yQQjjorY8uGDMIrQoFgb8SpAi3htWHYdqWOmG2UbN5vSn3vFQuJdsbNDGJkF
2ghDmtXsl2YlmyUhEkKQjHOCDvcHx3FsqY9RzmUJ97JI3/w3eq/+jz2FV49aWaqW
Cx8j2wM9vR+AmGfs8NTebM/ck7FCG7LVaTco0Yi/x9/gE2sQQ2CCCy5j1dYbHPej
0pe6pmgOoSJUp1oyNQBdCCf+QpkyfagVAoieBrSjeKPXoS41Q9e+VDxXsUwTtgZ4
xLv97wV+qWKkB8W6LZojHDr47ytu79dbRo1k7F7ZXm66ws3wxyni6LN5ivrXqI8p
RYyaJyn9Cheuu3rGZ/JfSWDnmCqlVSYZ0wvoxGHN7d5q1+gFup22ySBHqyvzkbj/
vjMKN7/SG6avwv6SROvNCWh7V6cEOFxjD+LwZmn7wS4L+mRI/ptHzRKUCwle34MY
H1boNQGUZg1/53tZw0V/WTkJaRNTQO/WKygx+xfF0nl1EMJIbHQBtzJp5UVtg04C
kHiyp+yNPmSO23qII8gFcQs9b9Snu1dFkjQ8DhGV4wtU8uSaq0uBuf9gG44dUbCa
gIO7qIX55TMIZWw7sAFdTNwMg7yFtczcOT2QiEORkzsF3lctY2Vj6GCy/1E9rVQ+
zTZR6BtthhXcLe66YVfEARbb8ufVozzZByd0beEAQKI5XEUKClrNWbrOBftG4FjB
bM/oOPgD5/HzWqMcVTMv5CQBrSagMBZgXRq1FS37n66l5bLD+qrYaQu7Gzq3UcD4
dlDFwLsXtOk7qmbBmH8DlG++A6Ew9WVd3Frae0yJgsvmaDX5qDpQcxflWFPFpnBy
9qojVOPMvS/qYy/bFQp0KsMFTgtlPy+U0Mi5HrpTx4cLwEnOd1CWXNucLlEcHExu
KEBRiqBWxkfPlXBiSblmehUUSiPwO8q2kzsNOHNbpc4LDwxMcVoXw9d6J/5HLWhN
S1vZ/Ie0zco8b9pb8A46PaC7QEL3e/E6hh2bdCf6m4HtNzHogkzCp3vCL3gvzF/6
ean3XYbaxgHxjJ+WV3Q6xvmeAvRgAOh0Zv14u635/t9V8JeAieIoZ7QYdv6uOrKY
+Lmb2SrorpaXkZgQfhQGtKiaItONXHH2nbClR9nKZNa5nANhbv78TQPkdiMrqCPA
2f6ZsjI9JnD9B3+QMLITjVpNvU4cxxm8DqlALBtdT1IEno+WreTmzOVWgi46MKOT
TgrbDhhBdWLyIETkwcyIbDm9fVdTuOhmajuKTIwVVKQng4Yf5EBuIKWYMBoTg37I
YjGXGmL3YSj0OVgcTxsdQIafifIMWRk4eC5zVFi+D9sayEyNRk/4qMVC+6gTZeOJ
0E5Kf2bdmqhgre061+cfnsG3o039d6wamH63S7iVArfKoArPW68SOA+3KChmAZ+g
ZoSfjyW/TQ9U/tg2MSfISg+dtk14EubDVcrJZBv0nKqdpzNpxayIieewqfZmNQYG
LqOhR9dE90kTb9ui+NtoTdZE3YykNOQfvtk6KHx+dG8GBUGcAhgJzEaJQfA5lgDe
dzoVoC4ixhS6Fl2SUHwTDDlw
-----END PRIVATE KEY-----

実行でエラーがあった場合は証明書の代わりにエラー文が表示されます

参考資料

- https://certbot.eff.org/docs/using.html#pre-and-post-validation-hooks