systemli.letsencrypt

Rola Ansible do uzyskiwania certyfikatów SSL Let's Encrypt

Integracja Ansible Galaxy

Ta rola ma na celu żądanie certyfikatów SSL od Let's Encrypt, używając wyzwania HTTP lub DNS dla ich interfejsu API ACME.

Funkcje:

  • Instaluje i konfiguruje certbot oraz skrypt pomocniczy do wyzwania DNS
  • Obsługuje zarówno wyzwanie HTTP, jak i DNS
    • Dla wyzwania HTTP, obsługiwane są wtyczki uwierzytelniające apache, nginx, standalone oraz webroot
  • Wyzwanie DNS używa dedykowanej strefy tylko dla tokenów wyzwania AMCE, co zmniejsza ryzyko związane z dynamicznymi aktualizacjami. Koncept jest wyjaśniony tutaj
  • Restart usług przy odnawianiu certyfikatu z użyciem post-hooków lub własnego polecenia post-hook
  • Kontrola dostępu do certyfikatów z użyciem dedykowanej grupy systemowej

Obsługiwane dystrybucje:

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

Testowane na:

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

Co robi:

  • Gdy letsencrypt_setup jest True (domyślnie), ta rola wykonuje:

    • Instaluje certbot
    • Rejestruje konto w Let's Encrypt
    • Instaluje wymagane pliki/klucze do wyzwania DNS
    • Tworzy grupę systemową 'letsencrypt'
  • Gdy wywołana jest z wypełnioną zmienną 'letsencrypt_cert':

    • Żąda certyfikatu SSL za pośrednictwem interfejsu API ACME Let's Encrypt, używając wyzwania HTTP lub DNS
    • Opcjonalnie ustawia post-hook dla odnawiania certyfikatów (aby uruchomić wymagane usługi po tym)
    • Opcjonalnie dodaje użytkowników systemowych do grupy 'letsencrypt', aby przyznać im dostęp do certyfikatów SSL i ich kluczy prywatnych

Jak to działa (przykłady)

  • Instalacja certbota ansible-playbook site.yml -l localhost -t letsencrypt
  • Tworzenie certyfikatu za pomocą wyzwania HTTP i uwierzytelniającego webroot (restartowanie usługi 'apache2' przy odnawianiu): 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"]}}'
  • Tworzenie certyfikatu za pomocą wyzwania DNS (przyznawanie dostępu do certyfikatów dla użytkownika 'Debian-exim', restartowanie usług 'exim4' i 'dovecot` przy odnawianiu): 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"]}}'
  • Tworzenie certyfikatu za pomocą wyzwania HTTP i uwierzytelniającego standalone (ponowne użycie tego samego klucza prywatnego przy odnawianiu i uruchomienie własnego skryptu post-hook przy odnawianiu): 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"}}'

Oczekiwana struktura zmiennej letsencrypt_cert

Zmienna letsencrypt_cert powinna być słownikiem:

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

lub:

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

lub:

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"

Słownik obsługuje następujące klucze:

  • name: nazwa certyfikatu [opcjonalnie]
  • domains: lista domen dla certyfikatu [wymagane]
  • challenge: 'http' lub 'dns' [wymagane]
    • dla wyzwania 'http': http_auth: 'webroot', 'apache' lub 'nginx' [opcjonalnie, domyślnie 'webroot']
      • dla http_auth 'webroot': webroot_path [opcjonalnie, domyślnie '/var/www']
  • services: lista usług do zrestartowania w post-hook [opcjonalnie]
  • reuse_key: Ponowne użycie tego samego klucza prywatnego przy odnawianiu certyfikatu. 'True' lub 'False' (domyślnie 'False')
  • post_hook: Własny post-hook do wykonania po próbie uzyskania/odnowienia certyfikatu [opcjonalnie]
  • deploy_hook: Własny deploy-hook do wykonania po udanej próbie uzyskania/odnowienia certyfikatu [opcjonalnie]
  • renew_hook: Własny renew-hook do wykonania raz dla każdego odnowionego certyfikatu po odnawianiu certyfikatu [opcjonalnie]
  • users: lista użytkowników do dodania do grupy systemowej 'letsencrypt' [opcjonalnie]

Ogólne wstępne informacje

Rola zajmuje się instalacją certbota i żądaniem certyfikatów SSL używając wyzwania HTTP lub DNS. Nie instaluje ani nie konfiguruje wymaganej infrastruktury (tj. serwera Apache czy serwera DNS).

Rola jest testowana tylko z Ansible 2.2. Brak gwarancji, że działa z wcześniejszymi wersjami Ansible.

Wyzwanie HTTP

Wymagania:

  • Nazwa domeny (domen), dla której żądany jest certyfikat, musi wskazywać na system
  • Dla http_auth 'apache', Apache2 musi być zainstalowany (i skonfigurowany) na systemie
  • Dla http_auth 'nginx', NGINX musi być zainstalowany (i skonfigurowany) na systemie

Wyzwanie DNS

Wymagania:

  • Serwer DNS z dedykowaną strefą, używaną tylko dla wyzwania DNS ACME. Ta strefa musi pozwalać na dynamiczne aktualizacje DNS (NSUPDATE).
  • Rekordy CNAME dla _acme-challenge.sub.example.org dla wszystkich nazw domen żądanych certyfikatów muszą wskazywać na sub.example.org._le.example.org (w dedykowanej strefie dla wyzwania DNS ACME).
  • Zawartość klucza aktualizacji DNS i prywatnych kluczy aktualizacji DNS musi być dostępna w zmiennych Ansible letsencrypt_ddns_key i letsencrypt_ddns_privkey (najlepiej wewnątrz skarbca).

Ta rola instaluje skrypt pomocniczy do wyzwania DNS w /usr/local/bin/certbot-dns-hook.sh. Skrypt ten doda token weryfikacyjny do rekordu TXT w sub.example.org._le.example.org podczas wyzwania DNS i usunie go później.

Obsługa wildcard dla wyzwania DNS

Uzyskiwanie certyfikatów wildcard powinno działać od razu przez wyzwanie DNS.

Konfiguracja bind9 dla wyzwania DNS

(Inną opcją byłoby użycie serwera acme-dns dla tego)

Wygeneruj klucz do dynamicznych aktualizacji:

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

Dodaj klucz do konfiguracji bind (np. w /etc/bind/named.conf.options):

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

Utwórz strefę dla dynamicznych aktualizacji:

$ORIGIN .
$TTL 86400 ; 1 dzień
_le.example.org IN SOA ns1.example.org. postmaster.example.org. (
                2017061501 ; serial
                86400      ; odświeżanie (1 dzień)
                3600       ; ponowna próba (1 godzina)
                2419200    ; wygaszenie (4 tygodnie)
                86400      ; minimum (1 dzień)
                )
            NS ns1.example.org.
            NS ns2.example.org.
            TXT "v=spf1 -all"

i skonfiguruj ją w swoim pliku konfiguracyjnym bind (np. w /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 dla /etc/letsencrypt/keys/ddns_update.key (z bind)

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

Format dla /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

Domyślne zmienne Ansible

# Wykonaj krok instalacji; ustaw na false, aby wyłączyć
letsencrypt_setup: True

# Podaj istniejące dane konta do skopiowania
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

# Ustaw adres e-mail związany z kontem Let's Encrypt
letsencrypt_account_email: ""

# Domyślny uwierzytelniacz dla wyzwania HTTP ('webroot' lub 'apache')
letsencrypt_http_auth: webroot

# Domyślna ścieżka do webroot dla uwierzytelniającego 'webroot'
letsencrypt_webroot_path: /var/www

# Zainstaluj skrypt pomocniczy do wyzwania DNS i klucz aktualizacji DNS
letsencrypt_dns_challenge: yes

# Ustawienia dla dynamicznych aktualizacji strefy DNS
# letsencrypt_ddns_server: ""
# letsencrypt_ddns_zone: ""
# letsencrypt_ddns_key: ""
# letsencrypt_ddns_privkey: ""

# Utwórz grupę systemową 'letsencrypt' dla dostępu do certyfikatów
letsencrypt_group: yes

# Ponownie używać klucza prywatnego przy odnawianiu certyfikatu?
letsencrypt_reuse_key: False

# Zezwolić na podzbiór nazw?
letsencrypt_subset_names: True

# Ustaw globalne dodatkowe opcje wiersza poleceń dla certbota
letsencrypt_opts_extra: ""

# Ustaw ścieżkę do katalogu letsencrypt (bez ukośnika na końcu !!)
letsencrypt_directory: /etc/letsencrypt

Testowanie

Do celów testowych, zmienna letsencrypt_test może być ustawiona. Jeśli ustawiona na True, rola użyje testowych serwerów Let's Encrypt do tworzenia konta i uzyskiwania certyfikatu.

Do rozwijania i testowania roli używamy Molecule i Vagrant/Github Actions. W lokalnym środowisku można łatwo przetestować rolę za pomocą

molecule test

Licencja

Ta rola Ansible jest licencjonowana na mocy GNU GPLv3.

Autor

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

O projekcie

Role to obtain Let's Encrypt SSL certificates

Zainstaluj
ansible-galaxy install systemli.letsencrypt
Licencja
gpl-3.0
Pobrania
25.7k
Właściciel
Your friendly tech collective