In nahezu jedem modernen Softwareprojekt gibt es sie: Passwörter, API-Keys, Zertifikate, Datenbankverbindungsstrings,
OAuth-Tokens und andere sensible Werte. Diese Informationen – zusammenfassend als Secrets bezeichnet –
müssen irgendwo gespeichert werden, damit Anwendungen und Dienste zur Laufzeit darauf zugreifen können.
Das Problem ist so alt wie die Softwareentwicklung selbst, wird aber mit zunehmender Automatisierung,
Containerisierung und CI/CD-Pipelines immer relevanter.
Der klassische Fehler: Secrets landen direkt im Quellcode oder in Konfigurationsdateien, die in
Git eingecheckt werden. Ein öffentliches GitHub-Repository mit einem hartcodierten AWS-Access-Key
ist keine Seltenheit – die Folgen reichen von unerwarteten Cloud-Rechnungen in fünfstelliger Höhe
bis hin zu vollständigen Datenpannen. Selbst in privaten Repositories ist das Speichern von Secrets
in Git ein ernstes Risiko, weil der gesamte Git-Verlauf dauerhaft erhalten bleibt. Ein Secret, das
einmal committed wurde, existiert in der Historie – auch nach einem späteren Löschen des Eintrags.
Umgebungsvariablen sind ein häufiger Ausweichweg. Sie sind besser als Klartext im Code, lösen das
Problem aber nicht vollständig. In Container-Umgebungen landen Umgebungsvariablen häufig in
Deployment-Manifesten (z. B. Kubernetes YAML-Dateien), die wiederum in Git versioniert werden.
Außerdem sind Umgebungsvariablen oft für alle Prozesse eines Systems sichtbar, bieten keine
Zugriffskontrolle, kein Audit-Log und keine automatische Rotation.
Secrets Management löst diese Probleme durch einen zentralisierten, kontrollierten und
auditierbaren Umgang mit sensiblen Daten. Statt Secrets in Dateien oder Umgebungsvariablen zu
verteilen, werden sie in einem dedizierten System gespeichert, das Zugriffskontrollen, Verschlüsselung,
Ablaufdaten und Protokollierung bietet. Die Anwendung ruft das Secret zur Laufzeit ab – und nur
wenn sie die nötige Berechtigung hat.
2. HashiCorp Vault
HashiCorp Vault ist eines der bekanntesten und mächtigsten Open-Source-Werkzeuge im Bereich
Secrets Management. Es bietet eine zentrale Plattform zur sicheren Speicherung, zum Zugriff
und zur Verwaltung von Secrets aller Art. Vault ist in Go geschrieben, läuft als einzelne Binary
und ist für Produktionsumgebungen wie für den Homelab-Betrieb geeignet.
2.1 Architektur
Vault besteht aus mehreren zentralen Komponenten:
Das Storage Backend ist für die dauerhafte Speicherung der verschlüsselten Daten
zuständig. Vault selbst speichert nichts im Klartext – alle Daten werden vor dem Schreiben
verschlüsselt. Unterstützte Backends sind unter anderem Consul, PostgreSQL, S3 und das integrierte
Raft-Backend, das für die meisten Installationen empfohlen wird.
Auth Methods steuern, wie sich Clients gegenüber Vault authentifizieren. Es gibt
Methoden für Token-basierte Authentifizierung, AppRole (für Maschinen und CI-Systeme), Kubernetes,
LDAP, GitHub und viele weitere. Ein Kubernetes-Pod kann sich beispielsweise automatisch über seinen
Service-Account-Token bei Vault anmelden.
Secret Engines sind Plugins, die verschiedene Arten von Secrets verwalten.
Die KV-Engine speichert beliebige Key-Value-Paare, die PKI-Engine stellt X.509-Zertifikate aus,
die Datenbank-Engine generiert dynamische Zugangsdaten, und die Transit-Engine stellt
kryptografische Operationen als Dienst bereit (Encryption as a Service).
2.2 Dev-Modus vs. Produktions-Setup
Für lokale Entwicklung und Tests bietet Vault einen Dev-Modus, der sich mit einem
einzigen Befehl starten lässt:
vault server -dev
Im Dev-Modus ist Vault automatisch initialisiert und entsiegelt, verwendet In-Memory-Storage
(alle Daten gehen beim Neustart verloren) und gibt einen Root-Token direkt auf der Konsole aus.
Dieser Modus eignet sich ausschließlich für Experimente – niemals für produktive Workloads.
Ein Produktions-Setup benötigt hingegen ein persistentes Storage-Backend, eine sorgfältig
konfigurierte TLS-Terminierung, einen dedizierten Initialisierungsprozess und ein durchdachtes
Unseal-Verfahren.
2.3 Seal und Unseal
Vault startet in einem versiegelten (sealed) Zustand. Es kann zwar laufen, aber nicht
auf die verschlüsselten Daten zugreifen, weil der Verschlüsselungsschlüssel nicht im Speicher
liegt. Dieser Zustand schützt vor einem unbefugten Zugriff auf das Storage-Backend.
Beim ersten Start wird Vault mit folgendem Befehl initialisiert:
Dieser Befehl erzeugt fünf Unseal-Keys und einen initialen Root-Token. Drei der fünf Keys
(entsprechend dem Schwellenwert) werden benötigt, um Vault zu entsiegeln. Dieses auf
Shamir's Secret Sharing basierende Verfahren stellt sicher, dass kein einzelner Administrator
allein Zugriff erlangen kann. Die Unseal-Keys müssen sicher und getrennt voneinander aufbewahrt
werden. Für automatisiertes Unsealing in Produktionsumgebungen wird oft Auto-Unseal über
Cloud-KMS-Dienste (AWS KMS, GCP Cloud KMS) oder HashiCorp's eigene Transit-Engine verwendet.
3. Vault KV Engine
Die KV-Engine (Key-Value) ist die einfachste und am häufigsten genutzte Secret Engine in Vault.
Sie erlaubt das Speichern beliebiger Schlüssel-Wert-Paare unter einem definierten Pfad.
3.1 KV v1 vs. KV v2
Es gibt zwei Versionen der KV-Engine. KV v1 ist die ältere, einfachere Variante:
Secrets werden gespeichert und beim Überschreiben vollständig ersetzt. Es gibt keine
Versionsverwaltung, kein automatisches Aufbewahren älterer Werte und keine Metadaten zum
Zeitpunkt der letzten Änderung.
KV v2 führt Versionierung ein. Jeder Schreibvorgang erzeugt eine neue Version
des Secrets. Standardmäßig werden die letzten zehn Versionen behalten. Das ist besonders
nützlich für Audits, Rollbacks und die Secret-Rotation: Wenn ein rotiertes Secret Probleme
verursacht, lässt sich die vorherige Version schnell wiederherstellen.
Eine KV v2 Engine wird folgendermaßen aktiviert und befüllt:
# Engine aktivieren
vault secrets enable -path=secret kv-v2
# Secret schreiben
vault kv put secret/myapp/database \
username="appuser" \
password="s3cr3tP@ssw0rd"
# Secret lesen
vault kv get secret/myapp/database
# Bestimmte Version lesen
vault kv get -version=2 secret/myapp/database
# Metadaten anzeigen
vault kv metadata get secret/myapp/database
3.2 Policies und ACLs
Vault verwendet ein capabilities-basiertes Rechtesystem. Zugriffsrechte werden über
Policies in HCL (HashiCorp Configuration Language) definiert. Eine Policy
legt fest, welche Pfade ein Token lesen, schreiben oder verwalten darf.
Das Prinzip der minimalen Rechtevergabe (Principle of Least Privilege) ist hier direkt
umsetzbar: Jede Anwendung bekommt nur Zugriff auf die Pfade, die sie tatsächlich benötigt –
lesend oder schreibend, je nach Bedarf.
4. Vault Dynamic Secrets
Eine der mächtigsten Funktionen von Vault ist die Generierung dynamischer Secrets.
Statt eines statischen Datenbankpassworts, das manuell rotiert werden muss, generiert Vault
auf Anfrage temporäre Zugangsdaten mit begrenzter Lebensdauer – direkt in der Zieldatenbank.
Kein Passwort wird vorab gespeichert oder an irgendeiner Stelle dauerhaft hinterlegt.
4.1 PostgreSQL-Beispiel
Für PostgreSQL sieht das Setup folgendermaßen aus:
# Datenbank-Engine aktivieren
vault secrets enable database
# PostgreSQL-Verbindung konfigurieren
vault write database/config/mypostgres \
plugin_name=postgresql-database-plugin \
allowed_roles="readonly" \
connection_url="postgresql://{{username}}:{{password}}@db.example.com:5432/mydb" \
username="vault_admin" \
password="admin_password"
# Rolle definieren: welche SQL-Statements beim Anlegen eines Users ausgeführt werden
vault write database/roles/readonly \
db_name=mypostgres \
creation_statements="CREATE ROLE \"{{name}}\" WITH LOGIN PASSWORD '{{password}}' \
VALID UNTIL '{{expiration}}'; \
GRANT SELECT ON ALL TABLES IN SCHEMA public TO \"{{name}}\";" \
default_ttl="1h" \
max_ttl="24h"
# Dynamische Zugangsdaten abrufen
vault read database/creds/readonly
Vault legt in PostgreSQL automatisch einen neuen Benutzer an, gibt Benutzername und Passwort
zurück und löscht den Account nach Ablauf der TTL (Time-to-Live) wieder. Der anfragende Client
bekommt einmalig gültige Zugangsdaten – und nur für die Dauer, die er tatsächlich benötigt.
4.2 TTL und Lease
Jedes dynamische Secret in Vault ist mit einem Lease verknüpft – einer
Mietdauer, nach deren Ablauf das Secret ungültig wird. Leases können vor Ablauf erneuert
(renew) oder vorzeitig widerrufen (revoke) werden. Das ist besonders
wertvoll in Notfallsituationen: Wenn Zugangsdaten kompromittiert wurden, können alle
aktiven Leases für eine Rolle mit einem einzigen Befehl widerrufen werden.
# Alle Leases einer Datenbankrolle widerrufen
vault lease revoke -prefix database/creds/readonly
5. SOPS (Secrets OPerationS)
SOPS ist ein von Mozilla entwickeltes Kommandozeilenwerkzeug zum Verschlüsseln von Dateien,
die Secrets enthalten. Im Gegensatz zu Vault, das einen laufenden Dienst voraussetzt,
arbeitet SOPS dateibasiert. Das macht es ideal für Konfigurationsmanagement, GitOps-Workflows
und Umgebungen, in denen ein vollständiges Vault-Setup zu aufwändig wäre.
Die zentrale Idee: YAML-, JSON-, ENV- oder INI-Dateien werden teilweise verschlüsselt.
SOPS verschlüsselt nur die Werte, nicht die Schlüssel. Das bedeutet, dass die
Struktur einer Konfigurationsdatei im Repository lesbar bleibt – nur die sensiblen Werte
sind chiffriert. Die verschlüsselten Dateien können sicher in Git eingecheckt werden.
5.1 SOPS mit age
age ist ein modernes, einfaches Verschlüsselungswerkzeug und die bevorzugte
Wahl für neue SOPS-Setups. PGP wird weiterhin unterstützt, ist aber in der Schlüsselverwaltung
deutlich komplexer. Mit age kommt man mit einem einzigen Schlüsselpaar aus.
Die Datei .sops.yaml im Projektstamm steuert, welche Schlüssel für welche
Dateien verwendet werden sollen. Über reguläre Ausdrücke lassen sich verschiedene Regeln
für verschiedene Dateitypen oder Verzeichnisse definieren:
Eine bestehende YAML-Datei mit Secrets wird folgendermaßen verschlüsselt:
# Ausgangsdatei secrets/database.yaml (Klartext)
# database:
# host: db.example.com
# username: appuser
# password: s3cr3tP@ssw0rd
# Datei in-place verschlüsseln
sops --encrypt --in-place secrets/database.yaml
# Nach der Verschlüsselung: Schlüssel lesbar, Werte chiffriert
# database:
# host: ENC[AES256_GCM,data:...,tag:...,type:str]
# username: ENC[AES256_GCM,data:...,tag:...,type:str]
# password: ENC[AES256_GCM,data:...,tag:...,type:str]
# Datei im Editor öffnen und bearbeiten (auto re-encrypt beim Speichern)
sops secrets/database.yaml
# Einzelnen Wert lesen
sops -d --extract '["database"]["password"]' secrets/database.yaml
# Gesamte Datei entschlüsselt ausgeben (stdout, kein Schreiben auf Disk)
sops -d secrets/database.yaml
# Als Umgebungsvariablen exportieren (.env-Datei)
export $(sops -d .env.encrypted | xargs)
SOPS öffnet beim direkten Aufruf ohne Flags die Datei im konfigurierten Editor (EDITOR-Variable).
Beim Speichern wird automatisch re-verschlüsselt. Für CI/CD-Pipelines steht der
-d-Flag (decrypt) zur Verfügung, der die Datei in den stdout dekodiert,
ohne sie auf die Festplatte zu schreiben.
5.4 Entschlüsselung zur Laufzeit in CI/CD
In einer CI/CD-Pipeline wird der private age-Schlüssel als verschlüsselte Pipeline-Variable
hinterlegt. Zur Laufzeit wird er in die Datei ~/.config/sops/age/keys.txt
geschrieben, und SOPS kann die Secrets automatisch entschlüsseln. Da der Schlüssel selbst
nie in Git landet, bleibt das gesamte Setup sicher. Ein Beispiel für GitHub Actions:
Vault und SOPS lösen dasselbe Grundproblem auf unterschiedliche Weise und sind für
verschiedene Einsatzszenarien geeignet. Beide Werkzeuge schließen sich nicht gegenseitig
aus – in größeren Umgebungen werden sie oft kombiniert eingesetzt.
6.1 HashiCorp Vault – Stärken und Einsatzszenarien
Vault ist die richtige Wahl, wenn es viele Anwendungen und Teams gibt, die zentral
verwaltete Secrets benötigen. Wenn dynamische Secrets mit automatischer Rotation und
Ablaufdaten gefordert sind, ist Vault unschlagbar. Weitere typische Vault-Szenarien
sind: umfangreiches Audit-Log und Zugriffskontrolle auf Secret-Ebene, PKI und
Zertifikatsmanagement, Encryption as a Service und native Kubernetes-Integration
via Vault Agent Injector oder dem Vault Secrets Operator.
Der Nachteil ist der Betriebsaufwand: Vault muss hochverfügbar betrieben, regelmäßig
aktualisiert und abgesichert werden. Ein Vault-Ausfall bedeutet, dass keine Anwendung
mehr auf ihre Secrets zugreifen kann – sofern kein lokales Caching implementiert ist.
Für ein einzelnes Projekt oder ein Homelab ist das oft zu viel Overhead.
6.2 SOPS – Stärken und Einsatzszenarien
SOPS ist die richtige Wahl, wenn Secrets in Git versioniert werden sollen –
typischerweise in GitOps-Workflows, Helm-Charts oder Ansible-Playbooks. Es wird kein
dauerhaft laufender Dienst benötigt, und die Einrichtung dauert wenige Minuten.
Für Homelab-Projekte, kleine Teams oder einzelne Entwickler ist SOPS oft die
pragmatischere Entscheidung.
SOPS hat keine dynamischen Secrets, kein natives Audit-Log und keine feingranulare
Zugriffskontrolle. Wer den privaten age-Schlüssel besitzt, kann alle damit
verschlüsselten Secrets entschlüsseln. Schlüsselrotation ist möglich, erfordert aber
manuelles Re-Verschlüsseln aller betroffenen Dateien.
6.3 Entscheidungshilfe auf einen Blick
Für ein Homelab oder ein kleines Einzelprojekt ist SOPS mit age der
pragmatische Einstieg: minimaler Aufwand, kein zusätzlicher Dienst, direkte
Git-Integration. Wächst das Projekt und werden mehr Kontrolle, Auditing und
dynamische Zugangsdaten notwendig, ist HashiCorp Vault der natürliche
nächste Schritt. Wer früh auf Vault setzt, profitiert von einem zentralen
Secret-Store für alle Dienste – zahlt dafür aber mit erhöhtem Betriebsaufwand.
7. Best Practices
Unabhängig davon, welche Lösung eingesetzt wird, gelten einige Grundregeln, die im
Secrets Management immer beachtet werden sollten.
7.1 Rotation
Secrets sollten regelmäßig rotiert werden – idealerweise automatisiert. Bei Vault erledigt
das die Dynamic Secrets Engine automatisch. Bei statischen Secrets (SOPS, KV) muss ein
Rotationsprozess explizit geplant und dokumentiert werden. Die TTL sollte so kurz wie
möglich und so lang wie nötig gewählt werden. Ein kompromittiertes Secret mit einer
Lebensdauer von einer Stunde verursacht deutlich weniger Schaden als ein dauerhaft
gültiges Passwort, das seit Jahren nicht rotiert wurde.
7.2 Audit-Logs aktivieren und auswerten
Vault bietet integriertes Audit-Logging. Jeder Zugriff auf ein Secret – lesend oder
schreibend – wird protokolliert, inklusive des verwendeten Tokens, des Zeitstempels und
des angefragten Pfads. Das Audit-Log sollte an ein zentrales Log-System weitergeleitet
und auf ungewöhnliche Zugriffsmuster überwacht werden. Bei SOPS gibt es kein natives
Audit-Log; hier hilft die Git-Historie zumindest für Änderungen an verschlüsselten Dateien.
Jede Anwendung, jeder Dienst und jeder Benutzer soll nur auf die Secrets zugreifen
können, die für ihre jeweilige Aufgabe tatsächlich notwendig sind. In Vault wird das
über Policies umgesetzt. Eine Anwendung, die nur eine Datenbankverbindung benötigt,
bekommt ausschließlich Lesezugriff auf den entsprechenden Vault-Pfad – nicht auf den
gesamten secret/-Namensraum. Diese Einschränkung begrenzt den Schaden bei
einer Kompromittierung erheblich.
7.4 Secrets niemals in Logs schreiben
Ein häufig unterschätztes Risiko ist das versehentliche Ausgeben von Secrets in Logs.
Das betrifft Datenbankverbindungsstrings in Exception-Stacktraces, Authorization-Header
in HTTP-Request-Logs und Umgebungsvariablen in Deployment-Protokollen. Logging-Frameworks
sollten so konfiguriert sein, dass bekannte Secret-Muster (Regex für API-Keys, Passwörter
in URLs) automatisch maskiert oder durch Platzhalter ersetzt werden. Ein Secret, das einmal
in einem zentralen Log-System landet, ist faktisch kompromittiert – selbst wenn der Zugriff
auf Logs eingeschränkt ist.
7.5 Keine Secrets in Container-Images
Docker-Images werden gebaut, gepusht und oft in öffentlichen oder halb-öffentlichen
Registries gespeichert. Secrets, die beim Build-Prozess in ein Image gelangt sind –
auch in einem früheren Layer – können mit docker history oder durch direktes
Inspizieren der Layer-Archive extrahiert werden. Secrets gehören niemals in ein Dockerfile
oder den Build-Kontext eines Images. Stattdessen sollten sie zur Laufzeit injiziert werden –
über Vault Agent, Kubernetes Secrets (idealerweise mit einem externen KMS verschlüsselt)
oder zur Laufzeit entschlüsselte SOPS-Dateien.
7.6 Notfallplan dokumentieren und üben
Jedes Secrets-Management-System sollte einen dokumentierten Notfallplan haben: Was passiert,
wenn Vault nicht verfügbar ist? Wer hat Zugriff auf die Unseal-Keys, und wo werden sie
aufbewahrt? Wie werden kompromittierte Secrets schnell widerrufen? Wie lange dauert eine
vollständige Secret-Rotation im Ernstfall? Diese Prozesse müssen bekannt und regelmäßig
geübt werden – am besten im Rahmen von Disaster-Recovery-Übungen, bevor ein echter Incident
eintritt. Ein Secrets-Management-System, dessen Wiederherstellungsprozess unbekannt ist,
bietet im Ernstfall nur falsches Sicherheitsgefühl.