Τι μένει ίδιο όπως στο Let’s Encrypt

Αν έχεις ποτέ λάβει πιστοποιητικό Let’s Encrypt, μπορείς ήδη να χρησιμοποιήσεις την εσωτερική CA. Το πρωτόκολλο είναι ίδιο — ACME RFC 8555. Οι clients που ήδη γνωρίζεις λειτουργούν χωρίς τροποποίηση.

Ίδια:

  • HTTP-01 και DNS-01 challenges.
  • Εγγραφή λογαριασμού και διαχείριση κλειδιού.
  • Προεπιλεγμένη διάρκεια 90 ημερών.
  • Αυτόματη ανανέωση στις 60 ημέρες.
  • Wildcard πιστοποιητικά μέσω DNS-01.

Τι διαφέρει

Δύο μικρές διαφορές, και οι δύο εφάπαξ βήματα setup:

  1. Το ACME directory URL δείχνει στην εσωτερική CA, όχι στο https://acme-v02.api.letsencrypt.org/directory.
  2. Το root πιστοποιητικό της εσωτερικής CA πρέπει να είναι αξιόπιστο για τον client που κάνει το αίτημα. Αυτό κανονίζεται μέσω configuration management (Ansible, Puppet, MDM) στο provisioning των hosts.

Αυτή είναι όλη η διαφορά. Όλα τα άλλα είναι το ίδιο workflow Let’s Encrypt που ήδη γνωρίζεις.

Στρέφοντας τον client σου στην εσωτερική CA

Το εσωτερικό ACME endpoint δημοσιεύεται σε μια σταθερή εσωτερική URL (τυπικά https://acme.example.internal/acme/acme/directory, αλλά η ακριβής διαδρομή εξαρτάται από το deployment σου). Παρακάτω είναι συνταγές για κοινούς clients.

certbot

certbot --server https://acme.example.internal/acme/acme/directory \
        --email ops@example.internal \
        --no-eff-email \
        --agree-tos \
        certonly --standalone -d service.example.internal

Για ανανέωση, το flag --server διατηρείται στο renewal/*.conf, οπότε το περιοδικό certbot renew cron το παίρνει αυτόματα.

acme.sh

acme.sh --register-account \
        --server https://acme.example.internal/acme/acme/directory \
        -m ops@example.internal

acme.sh --issue \
        --server https://acme.example.internal/acme/acme/directory \
        --standalone \
        -d service.example.internal

lego

lego --server=https://acme.example.internal/acme/acme/directory \
     --email=ops@example.internal \
     --domains=service.example.internal \
     --http run

Caddy

Στο Caddyfile σου:

{
  acme_ca https://acme.example.internal/acme/acme/directory
  email ops@example.internal
}

service.example.internal {
  reverse_proxy localhost:8080
}

Το Caddy θα λάβει και θα ανανεώσει το πιστοποιητικό αυτόματα.

Traefik

Στη δυναμική σου διαμόρφωση:

certificatesResolvers:
  internal:
    acme:
      caServer: "https://acme.example.internal/acme/acme/directory"
      email: ops@example.internal
      storage: /etc/traefik/acme.json
      httpChallenge:
        entryPoint: web

Αναφορά certResolver: internal από τους ορισμούς router.

Εγκατάσταση του root πιστοποιητικού στους clients

Για να γίνονται αποδεκτά τα πιστοποιητικά που εκδίδει η CA χωρίς προειδοποιήσεις, το root της CA πρέπει να βρίσκεται στο trust store συστήματος κάθε host που θα δει τα πιστοποιητικά.

Linux (οικογένεια Debian/Devuan)

sudo cp internal-ca-root.crt /usr/local/share/ca-certificates/internal-ca-root.crt
sudo update-ca-certificates

Linux (οικογένεια RHEL)

sudo cp internal-ca-root.crt /etc/pki/ca-trust/source/anchors/
sudo update-ca-trust extract

OpenBSD / FreeBSD

# OpenBSD
sudo install -m 0644 internal-ca-root.crt /etc/ssl/internal-ca-root.crt
sudo cat /etc/ssl/cert.pem internal-ca-root.crt > /etc/ssl/cert.pem.new
sudo mv /etc/ssl/cert.pem.new /etc/ssl/cert.pem

macOS

sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain internal-ca-root.crt

Windows

certutil.exe -addstore -f "ROOT" internal-ca-root.crt

Για browsers που διατηρούν τα δικά τους trust stores (Firefox), το root πρέπει επιπλέον να εισαχθεί μέσω Ρυθμίσεις → Απόρρητο → Πιστοποιητικά → Αρχές.

Αυτή η εγκατάσταση κανονικά γίνεται μέσω configuration management. Με το χέρι είναι ok για μια εφάπαξ περίπτωση, αλλά δεν κλιμακώνεται σε στόλο.

Wildcard πιστοποιητικά

Τα wildcards εκδίδονται μέσω challenge DNS-01 — ο client αποδεικνύει τον έλεγχο ενός domain δημιουργώντας μια εγγραφή TXT. Αυτό λειτουργεί για εσωτερικά μόνο domains επειδή η εσωτερική CA μπορεί να επικυρώσει εγγραφές TXT σε οποιοδήποτε DNS server ελέγχεις.

Παράδειγμα με acme.sh χρησιμοποιώντας τον BIND nsupdate provider:

acme.sh --issue \
        --server https://acme.example.internal/acme/acme/directory \
        --dns dns_nsupdate \
        -d '*.example.internal' \
        -d 'example.internal'

Θα χρειαστείς τον nsupdate provider διαμορφωμένο ενάντια στο εσωτερικό σου DNS — δες την τεκμηρίωση acme.sh για τις συγκεκριμένες μεταβλητές περιβάλλοντος.

Ανανέωση

Η ανανέωση δουλεύει όπως με το Let’s Encrypt: ο client ελέγχει την υπολειπόμενη εγκυρότητα και ανανεώνει όταν είναι κάτω από το κατώφλι (60 ημέρες για cert 90 ημερών).

Για τα περισσότερα deployments, ο υπάρχων renewal cron (certbot renew, acme.sh --cron, αυτόματη ανανέωση Caddy) λειτουργεί απλά.

Αν δεις αποτυχίες ανανέωσης:

  1. Είναι το directory URL ακόμη προσβάσιμο; Μια αλλαγή δικτύου μπορεί να έσπασε τη διαδρομή από τον client στη CA.
  2. Έληξε ή περιστράφηκε το root πιστοποιητικό; Τα roots είναι τυπικά έγκυρα για 10 χρόνια· τα intermediates για μικρότερες περιόδους. Μια rotation που δεν διαδόθηκε σε όλους τους clients θα εκδηλωθεί ως αποτυχίες ανανέωσης.
  3. Είναι ο τύπος challenge ακόμη κατάλληλος; Μια υπηρεσία που ήταν προσβάσιμη για HTTP-01 μπορεί τώρα να βρίσκεται πίσω από load balancer που σπάει την απάντηση challenge.

Όρια και πολιτικές

Η εσωτερική CA επιβάλλει πολιτικές ανά λογαριασμό — ποια domains κάθε λογαριασμός μπορεί να αιτηθεί πιστοποιητικά, ποια μέγιστη διάρκεια επιτρέπεται, ποιοι τύποι challenge γίνονται αποδεκτοί.

Αν ένα αίτημα που λειτουργούσε χθες αποτύχει ξαφνικά με σφάλμα policy denied, η πολιτική έχει αλλάξει (ή το account binding σου). Επικοινώνησε με τον CA operator σου. Η υπηρεσία Λειτουργία είναι η διαδρομή κλιμάκωσης αν ο CA operator σου είμαστε εμείς.