HashiCorp Vault löst eines der hartnäckigsten Probleme moderner Infrastruktur: Wo bewahrt man Secrets sicher auf und wie verteilt man sie? Hartcodierte Credentials in Konfigurationsdateien, in Git eingecheckte Umgebungsvariablen und gemeinsam genutzte Passwort-Tabellen sind für einen unverhältnismäßig großen Anteil an Datenlecks verantwortlich. HashiCorp Vault bietet eine einheitliche API für Secrets-Management, dynamische Credential-Generierung, Verschlüsselung als Dienst und feingranulare Zugriffssteuerung — alles mit einem vollständigen Audit-Trail. In diesem Leitfaden erfahren Sie, wie Vault funktioniert, wie Sie es einsetzen und wie Sie es in einem echten Produktions-Workflow mit Kubernetes und Terraform integrieren.

Voraussetzungen

  • Linux- oder macOS-Host (oder ein Kubernetes-Cluster für den cloud-nativen Weg)
  • Grundlegende Kenntnisse der Kommandozeile und YAML-Konfiguration
  • Docker (optional, für einen schnellen Dev-Server)
  • Ein Kubernetes-Cluster mit kubectl-Zugang (für den Abschnitt zur Kubernetes-Integration)
  • Terraform 1.x installiert (für den Abschnitt zum Terraform-Provider)
  • Kenntnisse über TLS-Zertifikate sind hilfreich, aber nicht erforderlich

Wie HashiCorp Vault funktioniert

Im Kern ist Vault ein Prozess, der eine HTTP-API bereitstellt. Alles — Secrets lesen, authentifizieren, Policies verwalten — läuft über diese API. Vault speichert seine Daten in einem Storage-Backend (Integrated Storage auf Basis von Raft ist der empfohlene Standard) und verschlüsselt alles im Ruhezustand mit einem Master-Schlüssel, der den Speicher nie verlässt.

Beim Start ist Vault versiegelt: Es hält die verschlüsselten Daten, kann sie aber nicht entschlüsseln, weil der Master-Schlüssel mithilfe von Shamirs Secret Sharing auf mehrere Unseal-Schlüsselanteile aufgeteilt ist. Vault wird erst betriebsbereit, nachdem das Mindestquorum an Schlüsselanteilen bereitgestellt wurde. Dieses Design bedeutet, dass selbst bei einem Diebstahl des Storage-Backends keine Secrets ohne die Unseal-Schlüssel gelesen werden können.

Schlüsselkonzepte

  • Secrets-Engines — Plugins, die Secrets erzeugen oder speichern. Die KV-Engine speichert statische Schlüssel/Wert-Paare. Die Database-Engine generiert dynamische Credentials. Die PKI-Engine stellt X.509-Zertifikate aus.
  • Auth-Methoden — wie Clients ihre Identität gegenüber Vault nachweisen. Optionen umfassen AppRole (für Maschinen), Kubernetes-Service-Accounts, AWS IAM, LDAP, GitHub und OIDC.
  • Policies — HCL-Dateien, die Lese-, Schreib- oder Admin-Zugriff auf bestimmte Pfade in Vault gewähren.
  • Leases und TTLs — jedes Secret hat einen Lease; wenn der Lease abläuft, widerruft Vault ihn. Anwendungen müssen Credentials vor Ablauf erneuern oder neu anfordern.
  • Audit-Geräte — Vault kann jede Anfrage und Antwort in eine Log-Datei, Syslog oder einen Socket schreiben. Audit-Logs sind manipulationssicher und kryptografisch verifiziert.

Vault installieren und initialisieren

Für ein produktionsreifes Deployment empfiehlt HashiCorp den Betrieb von Vault im High Availability (HA)-Modus mit Integrated Storage auf drei oder fünf Knoten. Zum Lernen genügt ein einzelner Dev-Server.

Schneller Dev-Server (nicht für Produktion):

vault server -dev

Dies startet ein In-Memory-Vault, entsiegelt es automatisch und gibt einen Root-Token aus. Daten gehen beim Beenden des Prozesses verloren.

Produktions-Einzelknoten mit Integrated Storage:

Erstellen Sie /etc/vault.d/vault.hcl:

ui = true

storage "raft" {
  path    = "/opt/vault/data"
  node_id = "vault-node-1"
}

listener "tcp" {
  address     = "0.0.0.0:8200"
  tls_cert_file = "/opt/vault/tls/vault.crt"
  tls_key_file  = "/opt/vault/tls/vault.key"
}

api_addr     = "https://vault.example.com:8200"
cluster_addr = "https://vault.example.com:8201"

Starten Sie den Dienst und initialisieren Sie ihn anschließend:

vault operator init -key-shares=5 -key-threshold=3

Dieser Befehl gibt fünf Unseal-Schlüssel und einen Root-Token aus. Speichern Sie diese sofort an separaten sicheren Orten — der Verlust von genügend Schlüsselanteilen bedeutet dauerhaften Verlust des Zugangs zu allen Daten. Entsiegeln Sie mit drei der fünf Schlüssel:

vault operator unseal <key-1>
vault operator unseal <key-2>
vault operator unseal <key-3>

Dynamische Secrets: Der zentrale Vorteil

Statische Credentials (ein Datenbankpasswort, das sich nie ändert) sind ein Sicherheitsrisiko. Wenn sie durchsickern, ist das Expositionsfenster unbegrenzt. Dynamische Secrets schließen dieses Fenster.

Aktivieren Sie die Datenbank-Secrets-Engine und konfigurieren Sie sie für PostgreSQL:

vault secrets enable database

vault write database/config/myapp-db \
  plugin_name=postgresql-database-plugin \
  allowed_roles="myapp-role" \
  connection_url="postgresql://{{username}}:{{password}}@db.example.com:5432/myapp" \
  username="vault" \
  password="vault-superuser-password"

vault write database/roles/myapp-role \
  db_name=myapp-db \
  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"

Nun kann jede Anwendung oder jeder CI-Job mit der richtigen Vault-Policy ausführen:

vault read database/creds/myapp-role

Vault verbindet sich mit PostgreSQL, erstellt einen eindeutig benannten Benutzer und gibt Credentials zurück, die in einer Stunde ablaufen. Wenn der Lease abläuft (oder die Anwendung vault lease revoke aufruft), löscht Vault den Datenbankbenutzer. Die Anwendung hält niemals ein langlebiges Passwort.

PKI-Secrets-Engine für interne Zertifikate

Die manuelle Verwaltung von TLS-Zertifikaten ist fehleranfällig und wird selten auditiert. Vaults PKI-Secrets-Engine fungiert als interne Zertifizierungsstelle und stellt kurzlebige Zertifikate auf Anfrage aus.

vault secrets enable pki
vault secrets tune -max-lease-ttl=87600h pki

# Root-CA generieren (Zertifikat extern speichern, wenn möglich offline aufbewahren)
vault write -field=certificate pki/root/generate/internal \
  common_name="example.com" \
  ttl=87600h > CA_cert.crt

# CRL- und Ausstellungs-URLs konfigurieren
vault write pki/config/urls \
  issuing_certificates="https://vault.example.com:8200/v1/pki/ca" \
  crl_distribution_points="https://vault.example.com:8200/v1/pki/crl"

# Intermediate-CA aktivieren (Best Practice für Produktion)
vault secrets enable -path=pki_int pki
vault write -format=json pki_int/intermediate/generate/internal \
  common_name="example.com Intermediate Authority" | jq -r '.data.csr' > pki_int.csr

vault write -format=json pki/root/sign-intermediate csr=@pki_int.csr \
  format=pem_bundle ttl="43800h" | jq -r '.data.certificate' > intermediate.cert.pem

vault write pki_int/intermediate/set-signed certificate=@intermediate.cert.pem

# Rolle für die Ausstellung von Server-Zertifikaten erstellen
vault write pki_int/roles/example-dot-com \
  allowed_domains="example.com" \
  allow_subdomains=true \
  max_ttl="72h"

Jeder Dienst, der ein TLS-Zertifikat benötigt, fordert eines an mit:

vault write pki_int/issue/example-dot-com common_name="api.example.com" ttl="24h"

24 Stunden gültige Zertifikate eliminieren das Risiko vergessener Zertifikatsrotationen.

Kubernetes-Integration mit dem Vault Agent Injector

Kubernetes-Secrets sind base64-kodiert und in etcd gespeichert. Ohne zusätzliche Kontrollen kann jeder Benutzer mit kubectl get secret-Zugriff sie lesen. Vaults Agent Injector hält Secrets vollständig aus Kubernetes heraus.

Installation mit Helm:

helm repo add hashicorp https://helm.releases.hashicorp.com
helm install vault hashicorp/vault \
  --set "injector.enabled=true" \
  --set "server.dev.enabled=false"

Kubernetes-Auth in Vault aktivieren und konfigurieren:

vault auth enable kubernetes

vault write auth/kubernetes/config \
  kubernetes_host="https://kubernetes.default.svc" \
  kubernetes_ca_cert=@/var/run/secrets/kubernetes.io/serviceaccount/ca.crt

Policy und Rolle erstellen:

vault policy write myapp - <<EOF
path "secret/data/myapp/*" {
  capabilities = ["read"]
}
EOF

vault write auth/kubernetes/role/myapp \
  bound_service_account_names=myapp \
  bound_service_account_namespaces=production \
  policies=myapp \
  ttl=1h

Annotieren Sie Ihren Pod, um Secrets zur Laufzeit zu injizieren:

annotations:
  vault.hashicorp.com/agent-inject: "true"
  vault.hashicorp.com/role: "myapp"
  vault.hashicorp.com/agent-inject-secret-config.env: "secret/data/myapp/config"
  vault.hashicorp.com/agent-inject-template-config.env: |
    {{- with secret "secret/data/myapp/config" -}}
    export DB_PASSWORD="{{ .Data.data.db_password }}"
    {{- end }}

Der Vault-Agent-Sidecar authentifiziert sich, ruft das Secret ab, schreibt es in ein gemeinsames In-Memory-Volume und erneuert es vor Ablauf. Die Anwendung liest eine Datei — sie führt niemals einen Vault-API-Aufruf durch.

Vergleich: Vault vs. Alternativen für Secrets-Management

FunktionHashiCorp VaultAWS Secrets ManagerAzure Key VaultKubernetes Secrets
Dynamische SecretsJa (Datenbank, Cloud, PKI)Begrenzt (nur RDS)NeinNein
Multi-CloudJaNur AWSNur AzureJa (mit CSI)
PKI / CAVollständige CA mit CRLNeinJa (begrenzt)Nein
Audit-LoggingEingebaut, manipulationssicherCloudTrailAzure MonitorBenötigt Add-on
Self-HostedJaNeinNeinJa
KostenKostenlos (Community)Pro Secret + API-AufrufPro OperationKostenlos
Kubernetes-nativAgent Injector / VSOCSI-TreiberCSI-TreiberNativ
LernkurveHochNiedrigNiedrigSehr niedrig

Vault ist die richtige Wahl, wenn Sie herstellerneutrales, auditierbares Secrets-Management mit dynamischer Credential-Generierung über mehrere Plattformen hinweg benötigen. AWS Secrets Manager ist besser, wenn Sie zu 100 % AWS-nativ sind und Einfachheit Priorität hat.

Praxisbeispiel: Absicherung einer mehrstufigen Anwendung

Sie betreiben einen Kubernetes-Produktionscluster mit einer Node.js-API, einer PostgreSQL-Datenbank und einem Redis-Cache. Ihre aktuelle Konfiguration speichert das Datenbankpasswort als Kubernetes-Secret und das Redis-Passwort in einer ConfigMap. Ein internes Audit hat beide als Compliance-Risiken eingestuft.

So sieht der Migrationspfad aus:

  1. Vault einsetzen im HA-Modus (3 Knoten) neben dem Cluster mit Helm. Integrated Storage mit Raft-Quorum verwenden.
  2. Dynamische Secrets aktivieren für PostgreSQL. Die statische PGPASSWORD-Umgebungsvariable entfernen. Der Vault Agent Injector schreibt alle 55 Minuten eine neue Credential-Datei (vor Ablauf der 1-Stunden-TTL).
  3. Das Redis-Passwort speichern in Vault KV v2 unter secret/data/production/redis. Der Agent Injector injiziert es als /vault/secrets/redis.env, das vom Entrypoint-Skript der Anwendung gesourct wird.
  4. PKI aktivieren für die interne TLS-Verbindung zwischen API und Datenbank. Zertifikate rotieren automatisch alle 24 Stunden.
  5. Audit-Logging konfigurieren, um in ein Syslog-Ziel zu schreiben, das an Ihr SIEM weitergeleitet wird. Jeder Secret-Zugriff wird jetzt mit Client-Identität, Quell-IP und Zeitstempel protokolliert.
  6. Mit Terraform integrieren mithilfe des Vault-Providers, um Policies und Rollen als Code zu verwalten, versioniert in Ihrem Infrastruktur-Repository.

Ergebnis: keine Secrets in Kubernetes etcd, keine statischen Credentials, vollständiger Audit-Trail und automatische Rotation — alles ohne eine einzige Zeile Anwendungscode zu ändern.

Stolperfallen und Sonderfälle

Versiegelung nach Neustart. Vault versiegelt sich bei jedem Prozessneustart selbst. Sie benötigen in der Produktion einen automatisierten Entsiegelungsmechanismus. Optionen sind HashiCorps eigenes Auto Unseal (mit AWS KMS, GCP Cloud KMS oder Azure Key Vault als Schlüsselquelle) oder eine Vault HSM-Integration. Planen Sie dies, bevor Sie in der Produktion einsetzen.

Lease-Explosion. Wenn Sie dynamische Secrets für Tausende kurzlebiger CI-Jobs generieren und diese nie explizit widerrufen, wächst Vaults Lease-Speicher unbegrenzt und verschlechtert schließlich die Leistung. Rufen Sie immer vault lease revoke am Ende eines Jobs auf oder verwenden Sie Vault Agent, der Erneuerung und Widerruf automatisch verwaltet.

Root-Token sollte widerrufen werden. Der bei vault operator init generierte Root-Token hat uneingeschränkten Zugriff. Generieren Sie nach der Ersteinrichtung einen zeitlich begrenzten Root-Token für den Notfallgebrauch und widerrufen Sie das Original: vault token revoke <root-token>.

Storage-Backend-Leistung. Integrated Storage (Raft) funktioniert gut für die meisten Workloads, reagiert aber empfindlich auf Disk-I/O-Latenz. Verwenden Sie auf Cloud-VMs SSD-basierte Volumes. Vermeiden Sie NFS oder netzwerkgebundenen Speicher für das Raft-Datenverzeichnis.

Namespace-Verwirrung. Vault Enterprise Namespaces sind logische Isolationseinheiten (wie separate Vault-Instanzen). Vault Community Edition hat keine Namespaces. Wenn Sie mit Enterprise testen und Community deployen, existieren zuvor funktionierende Pfade nicht mehr.

Uhrzeitabweichung. Mehrere Auth-Methoden (AWS IAM, Kubernetes, JWT) validieren signierte Tokens mit einem Zeitstempel. Wenn die Server-Uhren um mehr als wenige Sekunden abweichen, schlägt die Authentifizierung stillschweigend fehl. Stellen Sie sicher, dass NTP auf allen Vault-Knoten konfiguriert ist.

Fehlerbehebung

“Error initializing: Post https://127.0.0.1:8200/v1/sys/init: x509: certificate signed by unknown authority” Setzen Sie VAULT_SKIP_VERIFY=true nur zum Testen oder fügen Sie Ihr CA-Zertifikat dem System-Vertrauensspeicher hinzu und setzen Sie VAULT_CACERT=/path/to/ca.crt.

“Error making API request: Code: 503. Errors: Vault is sealed.” Vault wurde neu gestartet und wartet auf Unseal-Schlüssel. Führen Sie vault operator unseal mit der erforderlichen Anzahl an Schlüsselanteilen aus oder überprüfen Sie Ihre Auto-Unseal-Konfiguration.

Vault Agent schlägt bei der Kubernetes-Authentifizierung mit “permission denied” fehl Überprüfen Sie, ob Name und Namespace des ServiceAccounts des Pods genau mit bound_service_account_names und bound_service_account_namespaces in der Vault-Kubernetes-Rolle übereinstimmen. Überprüfen Sie außerdem, ob die Vault-Policy Zugriff auf die angeforderten Pfade gewährt.

“context deadline exceeded” beim Datenbankzugriff aus Vault Das Datenbank-Plugin kann den Datenbankhost nicht erreichen. Überprüfen Sie die connection_url in database/config/<name>, die Netzwerkkonnektivität und Firewall-Regeln zwischen Vault und der Datenbank und stellen Sie sicher, dass der Vault-Superuser CREATEROLE-Rechte besitzt.

Secrets werden in einem laufenden Pod nach Vault-Agent-Erneuerung nicht aktualisiert Standardmäßig rendert Vault Agent Templates in Dateien. Die Anwendung muss die Datei auf Änderungen überwachen oder neu starten, um neue Credentials zu übernehmen. Verwenden Sie den command-Block im Vault-Agent-Template-Stanza, um ein kill -HUP oder ein ähnliches Signal auszulösen.

Zusammenfassung

  • HashiCorp Vault ist der Industriestandard für herstellerneutrales, auditierbares Secrets-Management in Cloud- und On-Premises-Umgebungen.
  • Die KV-v2-Engine verwaltet statische Secrets; die Database- und PKI-Engines generieren kurzlebige dynamische Credentials und Zertifikate, die automatisch widerrufen werden.
  • Vault Agent entkoppelt Ihre Anwendung von der Vault-API — er übernimmt Authentifizierung, Secret-Abruf, Template-Rendering, Erneuerung und Widerruf.
  • Die Kubernetes-Integration über den Agent Injector oder den Vault Secrets Operator eliminiert statische Kubernetes-Secrets und etcd-Exposition.
  • Jede Operation über Vault wird in Audit-Logs erfasst und gibt Ihnen einen vollständigen, manipulationssicheren Nachweis für Compliance-Anforderungen.
  • Planen Sie Auto Unseal von Anfang an, um betriebliche Unterbrechungen bei Vault-Knotenneustart zu vermeiden.
  • Dynamische Secrets reduzieren den Schadenradius eines Credential-Lecks drastisch — ein einstündiges Datenbankzertifikat ist weit weniger gefährlich als ein Passwort, das seit drei Jahren gültig ist.

Verwandte Artikel