dhach.acme_letsencrypt
acme-letsencrypt
概要
これは、次の目的を達成するための純粋なAnsibleロールです。
- ECCまたはRSAの秘密鍵を作成する
- 証明書署名要求を生成する(複数のドメイン向け)
- リクエストをLet's Encryptまたは好きなACMEプロバイダーに送信する
- すべてのファイルを決定論的な場所にインストールする
私はこのロールを、certbotやacme-tiny、acme.shなどのサードパーティツールに頼らずにLet's Encryptの証明書を取得する手段を提供するために作成しました。これにより、何が行われているかをよりコントロールできます。
現在、HTTPチャレンジタイプのみがサポートされています。
これはAnsibleロールだけなので、自動的な証明書更新は処理しません。これを達成するには、CI/CDパイプラインから定期的にこのロールを実行するか、cronタブを使用してAnsibleプルモードで動作させることができます。
Ansibleバージョン
このロールは、リリース2.0.0以降、Ansible >=2.10との互換性が保証されます。
<2.10の互換性が必要な場合(「プレコレクション」)、1.x.xタグのリリースを使用してください。
要件
ターゲットホストで:
- openssl
使用例プレイブック
SAN証明書(複数のドメイン)用のsecp384r1 ECCキーを使用します。
- name: "webserver01の証明書を取得"
hosts: webserver01
become: true
roles:
- dhach.acme_letsencrypt
vars:
le_base_directory: /etc/letsencrypt
le_certificates:
- name: ecc.example.com
domains:
- secp.example.com
- ecc.example.com
key:
curve: secp384r1
次に、secp256r1キーを使用し、強制的に再作成し、Let's Encryptの本番検証サーバーに対してリクエストを発行します:
- name: "webserver02の証明書を取得"
hosts: webserver02
become: true
roles:
- dhach.acme_letsencrypt
vars:
le_acme_directory: https://acme-v02.api.letsencrypt.org/directory
le_certificates:
- name: another-domain.example.com
domains:
- another-domain-abc.example.com
- another-domain-def.example.com
- another-domain-ghi.example.com
- another-domain-jkl.example.com
- another-domain-mno.example.com
ssl:
type: ECC
curve: secp256r1
renew: true
または、RSAキーを使用して各ドメインごとに1つの証明書を取得します:
- name: "webserver03の証明書を取得"
hosts: webserver03
become: true
roles:
- dhach.acme_letsencrypt
vars:
le_certificates:
- name: example.com
domains:
- foo.example.com
key:
type: RSA
size: 4096
- name: more.example.com
domains:
- bar.example.com
key:
type: RSA
size: 4096
ファイルの場所
すべての生成された鍵や証明書要求、その後の証明書は、{{ le_base_directory }}/{{ le_certificates['name'] }}
の値の下に見つかります。
例えば、name
を'example.com'に設定し、le_base_directory
が'/etc/letsencrypt/'に設定されている場合、結果は次のようになります:
/etc/letsencrypt/example.com/
├── domain.csr
├── domain.key
├── domain.pem
├── fullchain.pem
└── intermediate.pem
ウェブサーバーの設定方法
ACMEサーバーは、特定の名前と内容のファイルをHTTP経由で提供するプリ定義されたパスに入れることによってチャレンジに応じる必要があります。
ウェブサーバーは、* /.well-known/acme-challenge *の位置を{{ le_base_directory }}/.well-known/acme-challenge/
の内容で提供する必要があります。
le_base_directory
のデフォルト値を使用している場合の例:
Nginx:
location /.well-known/acme-challenge {
alias /etc/letsencrypt/.well-known/acme-challenge/;
}
Apache:
Alias /.well-known/acme-challenge/ "/etc/letsencrypt/.well-known/acme-challenge/"
<Directory "/etc/letsencrypt/.well-known/acme-challenge/">
AllowOverride None
Options MultiViews Indexes SymLinksIfOwnerMatch IncludesNoExec
Require method GET POST OPTIONS
</Directory>
ロール変数とデフォルト値
以下に定義されているすべての変数がリストされています。それぞれのデフォルト変数も示されています。
証明書要求
証明書を要求するドメインを制御できます。また、鍵生成に関する詳細を指定するオプションもあります。オプションはRSAとECCキーの間でわずかに異なります。
すべての証明書要求はSAN(SubjectAltName)要求として構築されます。
ECC:
le_certificates:
- name: example.com # 実質的には内部識別子で、ファイルを保存する場所
domains: # 証明書を発行してほしいドメインのリスト
- foo.example.com
- bar.example.com
key: # 秘密鍵を生成する場合の詳細
type: ECC # (必須)サポートされているタイプ: ECC, RSA
curve: secp384r1 # (オプション | デフォルト: secp384r1)ECCキーの曲線(RSAキーには影響なし)。
renew: false # (オプション | デフォルト: false)キーを強制的に再作成するかどうか。常にバックアップを保持します。
RSA:
le_certificates:
- name: example.com # 実質的には内部識別子で、ファイルを保存する場所
domains: # 証明書を発行してほしいドメインのリスト
- foo.example.com
- bar.example.com
key: # 秘密鍵を生成する場合の詳細
type: RSA # (必須)サポートされているタイプ: ECC, RSA
size: 4096 # (オプション | デフォルト: 4096)RSAキーの長さ(ECCキーには影響なし)
renew: false # (オプション | デフォルト: false)キーを強制的に再作成するかどうか。常にバックアップを保持します。
ディレクトリと権限
le_base_directory
: 生成されたすべてのファイルを置くための基本ディレクトリ(デフォルト: /etc/letsencrypt)
le_files_owner
: 生成されたファイルとフォルダーの所有者(デフォルト: root)
le_files_group
: 生成されたファイルとフォルダーが属するグループ(デフォルト: root)
Let's Encryptアカウントキー
le_account_key_path
: Let's Encryptアカウントキーを置く(または見つける)場所(デフォルト: "{{ le_base_directory }}/account.key")
le_account_key_type
: アカウントキーに使用するキータイプ(RSA, ECC)(デフォルト: RSA)
le_account_key_size
: キーのサイズ。RSAキーの場合のみ。(デフォルト: 4096)
le_account_key_curve
: 使用する曲線。ECCキーの場合のみ、RSAキーには影響なし。(デフォルト: secp384r1)
le_account_key_regenerate
: 既存のキーを再生成するかどうか。バックアップを保持します。(デフォルト: false)
残念ながら、Let's EncryptはECCアカウントキーをすぐにはサポートしていません。RSA 4096に設定しておくのがベストです。
Let's Encrypt / ACMEバージョンとディレクトリ
le_acme_version
: 使用するACMEバージョンです。他の発行者を選択した場合に必要になることがあります(デフォルト: 2)
le_acme_directory
: 証明書をリクエストするためのACMEディレクトリURL。安全上の理由から、デフォルトはLet's Encryptのステージングに設定されています(デフォルト: https://acme-staging-v02.api.letsencrypt.org/directory)
Let's Encryptの本番ディレクトリは、https://acme-v02.api.letsencrypt.org/directoryです。
le_renew_if_invalid_after
: 有効期限がこの日数未満の場合に証明書を更新しようとします(デフォルト: 30)
le_force_renew
: 証明書を強制的に更新しようとします(デフォルト: false)
le_csr_only
: プライベートキーとCSRのみ生成する場合は、これをtrueに設定します。デバッグに役立つ場合があります。(デフォルト: false)
貢献と問題
すべての貢献を歓迎します。問題を開いたり、プルリクエストを作成することをためらわないでください。
挙げられた問題について喜んで検討しますし、常にこのロールを改善しようと努めます。
テスト
すべてのテストはMoleculeで行われます。
CIパイプラインはGitHub Actionsで実現されており、マトリックス戦略を使用して、Ubuntu、Debian、CentOSでテストを行います。
ローカルテストを開始するには、ローカルPython venvを設定し、すべての依存関係をインストールしてテストを実行します。このためには、マシンにDockerがインストールされている必要があります(またはDocker-Machineを使用):
python3 -m venv venv
source venv/bin/activate
python3 -m pip install --upgrade pip
python3 -m pip install -r test-requirements.txt
molecule test
このロールは基本的にACMEサーバーに対してリクエストを発行する必要があるため、DNSレコードを動的に設定するドメインの管理が必要です。そのため、テストはリント、鍵とCSRが作成されて存在し、期待される内容が含まれているかどうかを確認することに制限されます。
すべての機能を持つ完全なロールをテストするのは、実際にインターネットに接続されたマシンでLet's Encryptのステージングサーバーに対して手動で行います。
ライセンス
GNU一般公衆ライセンスバージョン3.0
Requests certificates from Let's Encrypt (or another ACME server)
ansible-galaxy install dhach.acme_letsencrypt