dhach.acme_letsencrypt

acme-letsencrypt

CI release Ansible Galaxy

概述

这是一个纯Ansible角色,用于实现以下功能:

  • 创建ECC或RSA私钥
  • 生成证书签名请求(针对多个域名)
  • 将请求发送到Let's Encrypt或您选择的其他ACME提供商
  • 在确定的位置安装所有文件

我编写这个角色的目的是为了能够获取Let's Encrypt证书,而不必依赖任何第三方工具(如certbot、acme-tiny、acme.sh等),并对过程有更多控制。

目前,仅支持HTTP挑战类型。

由于这只是一个Ansible角色,它不处理自动证书续订。要实现这一点,您可以从CI/CD管道定期运行此角色,或让它在Ansible拉模式下运行,并使用cron定时任务。

Ansible版本

从版本2.0.0开始,此角色仅保证与Ansible >=2.10兼容。

如果需要与<2.10兼容(即“预收集”),请使用任何1.x.x版本的发布。

要求

在目标主机上:

  • openssl

示例剧本

使用secp384r1 ECC密钥为SAN证书(多个域名)获取证书。

- 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密钥为每个域获取一个证书:

- 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

如何配置您的Web服务器

ACME服务器要求您通过在Web服务器的HTTP服务预定义路径中放置具有特定名称和内容的文件来响应挑战。

您的Web服务器必须服务于位置*/ .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版本。如果您选择使用其他发行者而不是Let's Encrypt,可能是必要的(默认: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虚拟环境,安装所有依赖项,并运行测试。这需要在您的计算机上安装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通用公共许可证v3.0

关于项目

Requests certificates from Let's Encrypt (or another ACME server)

安装
ansible-galaxy install dhach.acme_letsencrypt
许可证
gpl-3.0
下载
103
拥有者