aethercert
Dokumentation

Skript zum sicheren Austausch von TLS-Zertifikaten

So skripten Sie einen TLS-Zertifikatstausch unter Windows oder Linux, der wiederholbar ist: vor der Installation prüfen, sichern, aktivieren, ausgeliefertes Zertifikat prüfen, bei Fehlern zurückrollen.

Ein Skript ist das richtige Werkzeug, wenn es für ein Produkt keinen fertigen Ablauf gibt. Das Skript ist dann der Ablauf: Es prüft das neue Material, installiert es sicher, aktiviert es, prüft, ob es wirklich ausgeliefert wird, und lässt sich erneut ausführen, ohne Schaden anzurichten.

Voraussetzungen

  • Legen Sie fest, wie das Skript seine Eingaben bekommt:
    • Zertifikat und privater Schlüssel als Dateien an einem geschützten Ort (nur für das ausführende Konto lesbar). Übergeben Sie Schlüsselmaterial nicht als Kommandozeilenargument - andere Prozesse können es sehen - und vermeiden Sie Umgebungsvariablen für private Schlüssel, die Kindprozesse erben und Diagnosewerkzeuge anzeigen können.
    • Einstellungen wie Hostname, Port oder Dienstname als Argumente oder Umgebungsvariablen.
  • Legen Sie das Skript so ab, dass nur die Administration es ändern kann.
  • Wissen Sie, was im Fehlerfall wiederherzustellen ist: die vorherigen Dateien und die vorherige Bindung - die Einstellung, die dem Produkt sagt, welches Zertifikat es nutzt, etwa ein Fingerabdruck, ein Objektname oder ein Pfad.

Was das Skript tun sollte, in dieser Reihenfolge

  1. Prüfen Sie die Eingaben und brechen Sie bei jedem Problem mit Fehler ab: fehlende Dateien, falsche Namen im SAN, falsche Daten, ein Schlüssel, der nicht zum Zertifikat passt, eine unvollständige Kette.
  2. Sichern Sie die aktuellen Dateien und die Bindung.
  3. Installieren Sie das neue Material an einem geschützten, versionierten Ort. Schalten Sie wo möglich mit einem atomaren Schritt um - ein Rename oder Symlink-Wechsel im selben Dateisystem. Behalten Sie die Rechte bei (Unix-Besitzer, -Rechte und SELinux-Label; Windows-ACLs auf den Schlüssel).
  4. Testen Sie die Konfiguration des Produkts, falls es einen Testbefehl gibt; brechen Sie bei einem Ergebnis ungleich null ab.
  5. Aktivieren Sie mit dem kleinsten Schritt, der funktioniert - lieber Reload als Neustart -, und warten Sie mit Zeitlimit, bis der Dienst wieder gesund ist.
  6. Verifizieren Sie: Vergleichen Sie den Fingerabdruck des tatsächlich ausgelieferten Zertifikats mit dem neuen Zertifikat.
  7. Im Fehlerfall nach Schritt 3: Sicherung aus Schritt 2 wiederherstellen, erneut aktivieren und mit einem Code ungleich null beenden. Beenden Sie nur mit 0, wenn das neue Zertifikat nachweislich im Einsatz ist.

Machen Sie das Skript idempotent: Zweimal mit demselben Zertifikat ausgeführt, muss es im selben Zustand enden - keine doppelten Zertifikatsobjekte, keine Rechte, die sich mit jedem Lauf ändern. Automatische Erneuerungen wiederholen sich, und ein erneuter Lauf muss harmlos sein. Können zwei Erneuerungen gleichzeitig denselben Dienst treffen, serialisieren Sie sie, etwa mit einer Lock-Datei (flock unter Linux).

Gerüst (Linux)

#!/usr/bin/env bash
set -euo pipefail
CERT=$1 KEY=$2 HOST=$3            # Dateipfade und zu prüfender Hostname
DIR=/etc/myservice/tls

# 1. Prüfen
openssl x509 -in "$CERT" -noout -checkend 0
[ "$(openssl pkey -in "$KEY" -pubout | sha256sum)" = \
  "$(openssl x509 -in "$CERT" -noout -pubkey | sha256sum)" ] || { echo "key mismatch" >&2; exit 1; }

# 2. Sichern, 3. installieren
cp -p "$DIR/cert.pem" "$DIR/cert.pem.bak"; cp -p "$DIR/key.pem" "$DIR/key.pem.bak"
install -m 0644 "$CERT" "$DIR/cert.pem.new" && mv "$DIR/cert.pem.new" "$DIR/cert.pem"
install -m 0600 "$KEY"  "$DIR/key.pem.new"  && mv "$DIR/key.pem.new"  "$DIR/key.pem"

rollback() {
  mv "$DIR/cert.pem.bak" "$DIR/cert.pem"; mv "$DIR/key.pem.bak" "$DIR/key.pem"
  systemctl reload myservice || true
  echo "rolled back" >&2; exit 1
}

# 4. Testen, 5. aktivieren
myservice --check-config || rollback
systemctl reload myservice || rollback

# 6. Ausgeliefertes Zertifikat prüfen
want=$(openssl x509 -in "$CERT" -noout -fingerprint -sha256)
got=$(openssl s_client -connect "$HOST:443" -servername "$HOST" </dev/null 2>/dev/null |
      openssl x509 -noout -fingerprint -sha256)
[ "$want" = "$got" ] || rollback
echo "ok"

Ersetzen Sie myservice --check-config, die Pfade und den Port durch die Ihres Produkts. Unter Windows gilt in PowerShell derselbe Aufbau: mit Import-PfxCertificate importieren, Bindung ändern, ausgeliefertes Zertifikat prüfen, im Fehlerfall alte Bindung wiederherstellen - und nie ein PFX-Kennwort in den Quelltext des Skripts schreiben.

Rollback

Der Fehlerpfad des Skripts (Schritt 7) ist der automatische Rollback. Halten Sie außerdem einen Weg bereit, ihn von Hand auszulösen - einen Rollback-Modus oder ein eigenes Skript -, und testen Sie ihn vor dem ersten Produktiveinsatz.

Häufige Probleme

  • Schlüsselmaterial erscheint in Argumenten, Ausgaben oder Logs.
  • Das Skript kopiert die Dateien, aktiviert sie aber nie oder prüft das ausgelieferte Zertifikat nicht.
  • Wiederholte Läufe erzeugen doppelte Zertifikatsobjekte.
  • Ein Fehler wird abgefangen, und das Skript endet trotzdem mit 0.
  • Der Rollback stellt die Dateien wieder her, aber nicht die Bindung.

Zertifikatstausch mit aethercert automatisieren

Die aethercert-Deployment-Ziele für eigene Skripte führen ein von der Administration bereitgestelltes Skript aus, das bereits im geschützten Skriptverzeichnis des Agents liegt, und übergeben konfigurierte Werte als Umgebungsvariablen AC_VAR_<NAME>. aethercert lädt keinen Skriptinhalt hoch. Das Skript bekommt Ihre Variablen und nichts sonst: aethercert schreibt für ein Skript-Ziel weder Zertifikat noch Kette noch Schlüssel und übergibt keine Pfade. Braucht das Skript das Material, geben Sie dem Zertifikat ein zweites Deployment-Ziel, das die Dateien schreibt, und übergeben Sie dem Skript deren Pfade als Variablen.

Unter Deployment-Ziele finden Sie die Felder dieser Vorlage, die Freigabeprüfung, die ein Skript bestehen muss, und was in seiner Umgebung ankommt.

Auf dieser Seite