systemli.letsencrypt
Let's Encrypt SSL証明書を取得するためのAnsibleロール
このロールは、Let's EncryptからSSL証明書をリクエストするためのもので、HTTPまたはDNSチャレンジを使用してACME APIと通信します。
特徴:
- certbotとDNSチャレンジ用のヘルパースクリプトのインストールと設定
- HTTPチャレンジとDNSチャレンジの両方をサポート
- HTTPチャレンジには、
apache
、nginx
、standalone
、webroot
の認証プラグインがサポートされています
- HTTPチャレンジには、
- DNSチャレンジは、ACMEチャレンジトークン専用の特定ゾーンを使用するため、動的更新によるセキュリティリスクが低減されます。このコンセプトはこちらで説明されています
- 証明書更新時のサービスの再起動を、ポストフックまたはカスタムポストフックコマンドを使用して行います
- 証明書に対する権限管理を行う専用のシステムグループを設定可能
サポートされるディストリビューション:
- Debian 11 (Bullseye)
- Debian 12 (Bookworm)
テスト済みの環境:
- Debian 11 (Bullseye)
- Debian 12 (Bookworm)
- CentOS7
- Ubuntu 2204 (Jammy Jellyfish)
以下のことを行います:
letsencrypt_setup
がTrueの場合(デフォルト設定)、このロールは:- certbotをインストール
- Let's Encryptにアカウントを登録
- DNSチャレンジ用の必要なファイル/キーをインストール
- システムグループ「letsencrypt」を作成します
変数
letsencrypt_cert
に値が入っている状態で呼び出すと:- Let's Encrypt ACME APIを介してSSL証明書をリクエストします。HTTPチャレンジまたはDNSチャレンジを使用します
- 証明書の更新時にサービスを再起動するためのポストフックをオプションで設定できます
- システムユーザーを「letsencrypt」システムグループに追加して、SSL証明書とその秘密鍵への読み取りアクセスを付与することができます
使い方(例)
- certbotのインストール
ansible-playbook site.yml -l localhost -t letsencrypt
- HTTPチャレンジと
webroot
認証者を使用して証明書を作成(更新時にサービス'apache2'を再起動):ansible-playbook site.yml -l localhost -t letsencrypt -e '{"letsencrypt_cert":{"name":"sub.example.org","domains":["sub.example.org"],"challenge":"http","http_auth":"webroot","webroot_path":"/var/www/sub.example.org","services":["apache2"]}}'
- DNSチャレンジを通じて証明書を作成(証明書への読み取りアクセスをユーザー'Debian-exim'に付与し、更新時にサービス'exim4'と'dovecot'を再起動):
ansible-playbook site.yml -l localhost -t letsencrypt -e '{"letsencrypt_cert":{"name":"sub2","domains":["sub2.example.org","sub2.another.example.org"],"challenge":"dns","services":["dovecot","exim4"],"users":["Debian-exim"]}}'
- HTTPチャレンジと
standalone
認証者を使用して証明書を作成(更新時に同じ秘密鍵を再利用し、カスタムポストフックスクリプトを実行):ansible-playbook site.yml -l localhost -t letsencrypt -e '{"letsencrypt_cert":{"name":"sub3","domains":["sub3.example.org"],"challenge":"http","http_auth":"standalone","reuse_key":True,"post_hook":"/usr/local/bin/cert-post-hook.sh"}}'
変数letsencrypt_cert
の期待される構造
変数letsencrypt_cert
は辞書形式である必要があります:
letsencrypt_opts_extra: "--register-unsafely-without-email"
letsencrypt_cert:
name: sub.example.org
domains:
- sub.example.org
challenge: http
http_auth: webroot
webroot_path: /var/www/sub.example.org
services:
- apache2
または:
letsencrypt_cert:
name: sub2
domains:
- sub2.example.org
- sub2.another.example.org
challenge: dns
services:
- dovecot
- exim4
users:
- Debian-exim
または:
letsencrypt_cert:
name: sub3
domains:
- sub3.example.org
challenge: http
http_auth: standalone
reuse_key: True
post_hook: "/usr/local/bin/cert-post-hook.sh"
辞書は以下のキーをサポートしています:
name
: 証明書の名前(オプション)domains
: 証明書のためのドメインのリスト(必須)challenge
: 'http'または'dns'(必須)- チャレンジが'http'の場合:
http_auth
: 'webroot'、'apache'、または'nginx'(オプション、デフォルトは'webroot')http_auth
が'webroot'の場合:webroot_path
(オプション、デフォルトは'/var/www')
- チャレンジが'http'の場合:
services
: ポストフックで再起動するサービスのリスト(オプション)reuse_key
: 証明書更新時に同じ秘密鍵を再利用するかどうか。'True'または'False'(デフォルトは'False')post_hook
: 証明書の取得/更新後に実行されるカスタムポストフック(オプション)deploy_hook
: 証明書の取得/更新が成功した後に実行されるカスタムデプロイフック(オプション)renew_hook
: 各更新された証明書の更新後に1回実行されるカスタム更新フック(オプション)users
: システムグループ「letsencrypt」に追加するユーザーのリスト(オプション)
一般的な前提条件
このロールは、certbotのインストールとSSL証明書の取得をHTTPまたはDNSチャレンジを使用して行います。ApacheウェブサーバーやDNSサーバーなどの必要なインフラストラクチャのインストールや設定は行いません。
このロールはAnsible 2.2でのみテストされています。以前のバージョンのAnsibleで動作する保証はありません。
HTTPチャレンジ
必要条件:
- リクエストした証明書のドメイン名は、システムを指している必要があります
http_auth
が'apache'の場合、Apache2がシステムにインストールされて設定されている必要がありますhttp_auth
が'nginx'の場合、NGINXがシステムにインストールされて設定されている必要があります
DNSチャレンジ
必要条件:
- ACME DNSチャレンジ専用の特定ゾーンを持つDNSサーバーが必要です。このゾーンはTXTレコードに対して動的DNS更新(NSUPDATE)を許可する必要があります。
- リクエストしたすべてのドメイン名のために、
_acme-challenge.sub.example.org
のCNAMEレコードはsub.example.org._le.example.org
を指す必要があります(ACME DNSチャレンジ専用の特定ゾーン内)。 - DNS更新キーと秘密のDNS更新キーの内容は、Ansibleの変数
letsencrypt_ddns_key
およびletsencrypt_ddns_privkey
に利用できる必要があります(できればボールト内に)。
このロールは、DNSチャレンジ用のヘルパースクリプトを/usr/local/bin/certbot-dns-hook.sh
にインストールします。このスクリプトは、DNSチャレンジ中にsub.example.org._le.example.org
のTXTレコードに検証トークンを追加し、その後削除します。
DNSチャレンジによるワイルドカードサポート
ワイルドカード証明書の取得は、DNSチャレンジを通じて特に問題なく機能するはずです。
DNSチャレンジのためのbind9の設定
(別のオプションとしてacme-dnsサーバーを使用することもできます)
動的更新用のキーを生成します:
cd /etc/bind/keys
dnssec-keygen -a HMAC-SHA512 -b 512 -n USER _le.example.org_ddns_update
chown -R bind:bind /etc/bind/keys
キーをbind設定に追加します(例:/etc/bind/named.conf.options
に):
key "_le.example.org_ddns_update" {
algorithm hmac-sha512;
secret "...";
};
動的更新のためのゾーンを作成します:
$ORIGIN .
$TTL 86400 ; 1日
_le.example.org IN SOA ns1.example.org. postmaster.example.org. (
2017061501 ; シリアル
86400 ; リフレッシュ (1日)
3600 ; リトライ (1時間)
2419200 ; 有効期限 (4週間)
86400 ; 最小 (1日)
)
NS ns1.example.org.
NS ns2.example.org.
TXT "v=spf1 -all"
そして、それをbind設定(例:/etc/bind/named.conf.local
)に設定します:
zone "_le.example.org" {
type master;
file "/etc/bind/zones/db._le.example.org";
update-policy { grant _le.example.org_ddns_update wildcard *._le.example.org. TXT; };
};
/etc/letsencrypt/keys/ddns_update.key
の形式(bindから):
key "<key>" {
algorithm HMAC-SHA512;
secret "<key>";
};
/etc/letsencrypt/keys/ddns_update.private
の形式:
Private-key-format: v1.3
Algorithm: 165 (HMAC_SHA512)
Key: <key>
Bits: AAA=
Created: 20181017144534
Publish: 20181017144534
Activate: 20181017144534
Ansible変数のデフォルト
# セットアップステップを実行します; 無効にするにはfalseに設定
letsencrypt_setup: True
# 既存のアカウントデータをコピーするための提供
letsencrypt_account: ""
# letsencrypt_account:
# hash: 1234567890abcdef1234567890abcdef
# id: 123456789
# creation_host: localhost
# creation_dt: 2020-12-13T13:12:00Z
# private_key:
# n: 1234
# e: 5678
# d: 90ab
# p: cdef
# q: 1234
# dp: 5678
# dq: 90ab
# qi: cdef
# kty: RSA
# Let's Encryptアカウントに関連付けるメールアドレスを設定
letsencrypt_account_email: ""
# HTTPチャレンジ用のデフォルトの認証者('webroot'または'apache')
letsencrypt_http_auth: webroot
# 認証者'webroot'のデフォルトのwebrootパス
letsencrypt_webroot_path: /var/www
# DNSチャレンジ用のヘルパースクリプトとDNS更新キーをインストール
letsencrypt_dns_challenge: yes
# 動的DNSゾーン更新に関する設定
# letsencrypt_ddns_server: ""
# letsencrypt_ddns_zone: ""
# letsencrypt_ddns_key: ""
# letsencrypt_ddns_privkey: ""
# 証明書へのアクセスのためにシステムグループ'letsencrypt'を作成
letsencrypt_group: yes
# 証明書更新時に秘密鍵を再利用しますか?
letsencrypt_reuse_key: False
# 名前のサブセットを許可しますか?
letsencrypt_subset_names: True
# certbot用のグローバルな追加コマンドラインオプションを設定
letsencrypt_opts_extra: ""
# letsencryptディレクトリのパスを設定(末尾の"/"は不要)
letsencrypt_directory: /etc/letsencrypt
テスト
テスト目的で、変数letsencrypt_test
を設定することができます。Trueに設定すると、ロールはLet's Encryptのテストサーバーを使用してアカウントを作成し、証明書を取得します。
ロールの開発とテストのために、MoleculeとVagrant/Github Actionsを使用しています。ローカル環境でロールを簡単にテストすることができます:
molecule test
ライセンス
このAnsibleロールはGNU GPLv3の下でライセンスされています。
著者
著作権 2017-2019 systemli.org (https://www.systemli.org/)