systemli.letsencrypt

Ansible角色以获取Let's Encrypt SSL证书

集成 Ansible Galaxy

该角色旨在使用HTTP或DNS挑战来请求Let's Encrypt的SSL证书,采用其ACME API。

功能:

  • 安装并配置certbot及DNS挑战辅助脚本
  • 支持HTTP和DNS挑战
    • 对于HTTP挑战,支持身份验证插件apachenginxstandalonewebroot
  • 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"
letsencrypt_cert:
  name: sub3
  domains:
    - sub3.example.org
  challenge: http
  http_auth: standalone
  reuse_key: True
  deploy_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']
  • services:后钩子中需要重启的服务列表 [可选]
  • reuse_key:在证书续订时重用相同的私钥。'True'或'False'(默认'False')
  • post_hook:获取/续订证书后要执行的自定义后钩子 [可选]
  • deploy_hook:获取/续订证书成功后要执行的自定义部署钩子 [可选]
  • renew_hook:在每次续订证书后执行一次的自定义续订钩子 [可选]
  • users:要添加到'sletsencrypt'系统组的用户列表 [可选]

一般前提条件

该角色负责安装certbot并使用HTTP或DNS挑战请求SSL证书。它不会安装或配置所需的基础设施(即Apache网络服务器或DNS服务器)。

该角色仅与Ansible 2.2进行测试。不保证在Ansible早期版本上正常运行。

HTTP挑战

要求:

  • 请求证书的域名必须指向系统
  • 对于http_auth 'apache',系统上必须安装(并配置)Apache2
  • 对于http_auth 'nginx',系统上必须安装(并配置)NGINX

DNS挑战

要求:

  • 一台带有专用区域的DNS服务器,仅用于ACME DNS挑战。该区域必须允许对TXT记录进行动态DNS更新(NSUPDATE)。
  • 所有请求证书的域名的CNAME记录必须指向sub.example.org._le.example.org(位于ACME DNS挑战的专用区域内)。
  • DNS更新密钥及私有DNS更新密钥的内容需要在Ansible变量letsencrypt_ddns_keyletsencrypt_ddns_privkey中提供(最好放在一个保险箱里)。

该角色安装了一个用于DNS挑战的辅助脚本到/usr/local/bin/certbot-dns-hook.sh。该脚本将在DNS挑战期间将验证令牌添加到sub.example.org._le.example.org的TXT记录,并在之后将其删除。

DNS挑战的通配符支持

通过DNS挑战获得通配符证书应该可以开箱即用。

配置bind9以进行DNS挑战

(另一个选项是使用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 ; serial
                86400      ; refresh (1天)
                3600       ; retry (1小时)
                2419200    ; expire (4周)
                86400      ; minimum (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/)

关于项目

Role to obtain Let's Encrypt SSL certificates

安装
ansible-galaxy install systemli.letsencrypt
许可证
gpl-3.0
下载
25.7k
拥有者
Your friendly tech collective