systemli.letsencrypt

Ansible-Rolle zur Beschaffung von Let's Encrypt SSL-Zertifikaten

Integration
Ansible Galaxy

Diese Rolle ist dazu gedacht, SSL-Zertifikate von Let's Encrypt anzufordern, indem entweder die HTTP- oder die DNS-Herausforderung für die ACME-API verwendet wird.

Funktionen:

  • Installiert und konfiguriert certbot und das Hilfsskript für die DNS-Herausforderung
  • Unterstützt sowohl die HTTP- als auch die DNS-Herausforderung
    • Für die HTTP-Herausforderung werden die Authentifikator-Plugins apache, nginx, standalone und webroot unterstützt
  • Die DNS-Herausforderung nutzt eine dedizierte Zone nur für AMCE-Herausforderungstokens, was die Sicherheitsrisiken dynamischer Updates senkt. Das Konzept wird hier erklärt
  • Neustart von Diensten bei der Zertifikatsverlängerung mit Post-Hooks oder benutzerdefinierten Post-Hook-Befehlen
  • Berechtigungssteuerung zu Zertifikaten durch eine dedizierte Systemgruppe

Unterstützte Distributionen:

  • Debian 11 (Bullseye)
  • Debian 12 (Bookworm)

Getestet auf:

  • Debian 11 (Bullseye)
  • Debian 12 (Bookworm)
  • CentOS7
  • Ubuntu 2204 (Jammy Jellyfish)

Funktionsweise:

  • Wenn letsencrypt_setup auf True (Standard) gesetzt ist, wird diese Rolle:

    • certbot installieren
    • Ein Konto bei Let's Encrypt registrieren
    • Die erforderlichen Dateien/Schlüssel für die DNS-Herausforderung installieren
    • Die Systemgruppe 'letsencrypt' erstellen
  • Wenn mit einer ausgefüllten Variable letsencrypt_cert aufgerufen:

    • Ein SSL-Zertifikat über die Let’s Encrypt ACME API anfordern, entweder mit der HTTP- oder DNS-Herausforderung
    • Optional den Post-Hook für Zertifikatsverlängerungen festlegen (um erforderliche Dienste danach neu zu starten)
    • Optional Systembenutzer zur Gruppe 'letsencrypt' hinzufügen, um ihnen Lesezugriff auf die SSL-Zertifikate und deren private Schlüssel zu gewähren

Beispielhafte Verwendung

  • Installation von certbot: ansible-playbook site.yml -l localhost -t letsencrypt
  • Erstellung eines Zertifikats über die HTTP-Herausforderung mit webroot-Authentifikator (Neustart des Dienstes 'apache2' bei Verlängerung): 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"]}}'
  • Erstellung eines Zertifikats über die DNS-Herausforderung (Gewährung von Lesezugriff auf Zertifikate für den Benutzer 'Debian-exim', Neustart der Dienste 'exim4' und 'dovecot' bei Verlängerung): 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"]}}'
  • Erstellung eines Zertifikats über die HTTP-Herausforderung mit standalone-Authentifikator (Wiederverwendung des gleichen privaten Schlüssels bei Verlängerung oder Ausführung eines benutzerdefinierten Post-Hook-Skripts bei Verlängerung): 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"}}'

Erwartete Struktur der Variable letsencrypt_cert

Die Variable letsencrypt_cert wird als Wörterbuch erwartet:

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

oder:

letsencrypt_cert:
  name: sub2
  domains:
    - sub2.example.org
    - sub2.another.example.org
  challenge: dns
  services:
    - dovecot
    - exim4
  users:
    - Debian-exim

oder:

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"

Das Wörterbuch unterstützt folgende Schlüssel:

  • name: Name des Zertifikats [optional]
  • domains: Liste der Domains für das Zertifikat [erforderlich]
  • challenge: 'http' oder 'dns' [erforderlich]
    • für die Herausforderung 'http': http_auth: 'webroot', 'apache' oder 'nginx' [optional, Standard 'webroot']
      • für http_auth: 'webroot': webroot_path [optional, Standard '/var/www']
  • services: Liste der Dienste, die im Post-Hook neu gestartet werden sollen [optional]
  • reuse_key: Den gleichen privaten Schlüssel bei der Zertifikatsverlängerung wiederverwenden. 'True' oder 'False' (Standard 'False')
  • post_hook: Benutzerdefinierter Post-Hook, der nach dem Versuch, ein Zertifikat zu erhalten/verlängern, ausgeführt wird [optional]
  • deploy_hook: Benutzerdefinierter Deploy-Hook, der nach einem erfolgreichen Versuch, ein Zertifikat zu erhalten/verlängern, ausgeführt wird [optional]
  • renew_hook: Benutzerdefinierter Renew-Hook, der einmal für jedes erneuerte Zertifikat nach der Zertifikatsverlängerung ausgeführt wird [optional]
  • users: Liste der Benutzer, die zur Systemgruppe 'letsencrypt' hinzugefügt werden sollen [optional]

Allgemeine Vorbedingungen

Die Rolle kümmert sich um die Installation von certbot und die Anforderung von SSL-Zertifikaten mithilfe der HTTP- oder DNS-Herausforderung. Es installiert oder konfiguriert nicht die erforderliche Infrastruktur (z. B. den Apache-Webserver oder einen DNS-Server).

Die Rolle wurde nur mit Ansible 2.2 getestet. Es gibt keine Garantien, dass sie mit älteren Versionen von Ansible funktioniert.

Die HTTP-Herausforderung

Anforderungen:

  • Die Domainnamen des angeforderten Zertifikats müssen auf das System zeigen
  • Für http_auth 'apache' muss Apache2 auf dem System installiert (und konfiguriert) sein
  • Für http_auth 'nginx' muss NGINX auf dem System installiert (und konfiguriert) sein

Die DNS-Herausforderung

Anforderungen:

  • Ein DNS-Server mit einer dedizierten Zone, die nur für die ACME-DNS-Herausforderung verwendet wird. Diese Zone muss dynamische DNS-Updates (NSUPDATE) für TXT-Datensätze erlauben.
  • CNAME-Einträge für _acme-challenge.sub.example.org müssen für alle Domainnamen des angeforderten Zertifikats auf sub.example.org._le.example.org zeigen (innerhalb der speziellen Zone für die ACME-DNS-Herausforderung).
  • Der Inhalt des DNS-Update-Schlüssels und der privaten DNS-Update-Schlüssel müssen in den Ansible-Variablen letsencrypt_ddns_key und letsencrypt_ddns_privkey verfügbar sein (vorzugsweise innerhalb eines Vaults).

Diese Rolle installiert ein Hilfsskript für die DNS-Herausforderung in /usr/local/bin/certbot-dns-hook.sh. Dieses Skript fügt während der DNS-Herausforderung das Validierungstoken zum TXT-Datensatz bei sub.example.org._le.example.org hinzu und entfernt es anschließend.

Wildcard-Unterstützung mit der DNS-Herausforderung

Die Beschaffung von Wildcard-Zertifikaten sollte ohne Probleme über die DNS-Herausforderung funktionieren.

Konfiguration von bind9 für die DNS-Herausforderung

(Eine andere Option wäre die Verwendung des acme-dns-Servers dafür)

Generieren Sie einen Schlüssel für dynamische Updates:

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

Fügen Sie den Schlüssel in Ihre bind-Konfiguration ein (z. B. in /etc/bind/named.conf.options):

key "_le.example.org_ddns_update" {
    algorithm hmac-sha512;
    secret "...";
};

Erstellen Sie die Zone für dynamische Updates:

$ORIGIN .
$TTL 86400	; 1 Tag
_le.example.org		IN SOA	ns1.example.org. postmaster.example.org. (
                2017061501 ; Seriennummer
                86400      ; Aktualisierungsintervall (1 Tag)
                3600       ; Wiederholungsintervall (1 Stunde)
                2419200    ; Ablauffrist (4 Wochen)
                86400      ; Minimalzeit (1 Tag)
                )
            NS	ns1.example.org.
            NS	ns2.example.org.
            TXT	"v=spf1 -all"

und konfigurieren Sie es in Ihrer bind-Konfiguration (z. B. in /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; };
};

Format für /etc/letsencrypt/keys/ddns_update.key (von bind):

key "<key>" {
    algorithm HMAC-SHA512;
    secret "<key>";
};

Format für /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-Standardvariablen

# Einrichtungsprozess durchführen; auf false setzen, um zu deaktivieren
letsencrypt_setup: True

# Vorhandene Kontodaten bereitstellen, die kopiert werden sollen
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

# Die E-Mail-Adresse festlegen, die mit dem Let's Encrypt-Konto verknüpft ist
letsencrypt_account_email: ""

# Standardauthentifikator für die HTTP-Herausforderung ('webroot' oder 'apache')
letsencrypt_http_auth: webroot

# Standard-Webroot-Pfad für den Authentifikator 'webroot'
letsencrypt_webroot_path: /var/www

# Das Hilfsskript für die DNS-Herausforderung und den DNS-Update-Schlüssel installieren
letsencrypt_dns_challenge: ja

# Einstellungen für die dynamischen DNS-Zonenupdates
# letsencrypt_ddns_server: ""
# letsencrypt_ddns_zone: ""
# letsencrypt_ddns_key: ""
# letsencrypt_ddns_privkey: ""

# Erstellen Sie die Systemgruppe 'letsencrypt' für den Zugriff auf Zertifikate
letsencrypt_group: ja

# Den privaten Schlüssel bei der Zertifikatsverlängerung wiederverwenden?
letsencrypt_reuse_key: False

# Erlaubt eine Untermenge von Namen?
letsencrypt_subset_names: True

# Globale zusätzliche Befehlszeilenoptionen für certbot festlegen
letsencrypt_opts_extra: ""

# Pfad für das letsencrypt-Verzeichnis festlegen (kein abschließender "/" !!)
letsencrypt_directory: /etc/letsencrypt

Testen

Zu Testzwecken kann die Variable letsencrypt_test gesetzt werden. Wenn sie auf True gesetzt ist, verwendet die Rolle die Testserver von Let's Encrypt zur Kontoerstellung und zur Beschaffung des Zertifikats.

Für die Entwicklung und das Testen der Rolle verwenden wir Molecule und Vagrant/Github Actions. In der lokalen Umgebung können Sie die Rolle ganz einfach mit

molecule test

testen.

Lizenz

Diese Ansible-Rolle ist unter der GNU GPLv3 lizenziert.

Autor

Copyright 2017-2019 systemli.org (https://www.systemli.org/)

Über das Projekt

Role to obtain Let's Encrypt SSL certificates

Installieren
ansible-galaxy install systemli.letsencrypt
Lizenz
gpl-3.0
Downloads
25.7k
Besitzer
Your friendly tech collective