Was haben ephemere Secrets in Terraform mit Juan Pujol gemeinsam?
Mit Ephemeral schreibst du Secrets in selbstzerstörender Tinte.
Ein Spion, 400 Funksprüche – und kein einziges Beweisstück
Im Juni 1944 veränderte Juan Pujol, Codename »Garbo«, den Lauf des Zweiten Weltkriegs.
Ohne Schuss, ohne Kampf, nur mit Worten.
Genauer: mit über 400 gezielt platzierten Funksprüchen an die Deutsche Wehrmacht.
Jede einzelne Meldung war frei erfunden.
Garbo ersann Truppenverbände, erfand Invasionspläne, log mit System und taktischem Gespür.
Das Meisterstück: eine fingierte Invasionsflotte vor Calais.
So glaubhaft, dass Hitler dort seine besten Divisionen zurückhielt, während die Alliierten in der Normandie landeten.
Die Operation gelang - nicht zuletzt dank Pujols Desinformation.
Doch was Garbo unsterblich machte: Er löschte jede Nachricht direkt nach dem Senden.
Kein Mitschnitt, kein Protokoll.
Die Deutschen suchten Beweise und fanden … nichts.
Garbo hinterließ keine Spuren.
Du meinst, das sei weit weg von deinem Alltag? Nicht ganz.
Deine Terraform‑States sind das komplette Gegenteil.
Keine Tarnung, kein Selbstschutz.
Im Gegenteil: eine offene Akte.
Prall gefüllt mit allem, was ein digitaler Gegenspion lieben würde.
Zugänge zu Datenbanken, Key‑Vault‑Secrets, Passwörter, private Keys.
Alles im Klartext.
Gespeichert im State.
In der Community-Version von Terraform werden diese Inhalte im Klartext innerhalb der State-Datei gespeichert.
Das kann ein Risiko darstellen, wenn keine geeigneten Sicherheitsmaßnahmen getroffen werden.
Die Wende kam mit Terraform 1.10 und AzureRM ≥ 4.35
HashiCorp hat eine Funktion eingeführt, die deine Infrastrukturkommunikation grundlegend verändert: ephemeral = true
.
So funktioniert ephemeral = true
Infobox – Was bedeutet »ephemeral« technisch?
Attribute, Variablen oder Ressourcen mitephemeral = true
leben nur im RAM des aktuellenterraform apply
. Sie erscheinen weder in Plan‑Dateien noch im Remote State. Nach Prozessende sind sie unwiederbringlich gelöscht.
Ephemere Werte markierst du wie sensitive Variablen, nur mit dem zusätzlichen Flag.
Ideal, wenn ein Dienst temporäre Secrets verlangt oder Write‑Only‑Felder besitzt.
Beispiel 1 – Ephemere Variable mit OIDC‑Token
variable "identity_token" {
type = string
description = "Azure AD OIDC Token"
sensitive = true
ephemeral = true
}
Beispiel 2 – Key‑Vault‑Secret temporär laden
ephemeral "azurerm_key_vault_secret" "db_pw" {
name = "db-admin-pw"
key_vault_id = var.kv_id
}
Beispiel 3 – Kubernetes‑Provider ohne Secret‑Leak
ephemeral "azurerm_key_vault_secret" "kube" {
for_each = toset(["client-cert", "client-key", "ca-cert"])
name = each.key
key_vault_id = var.kv_id
}
provider "kubernetes" {
host = "https://${var.aks_api}"
client_certificate = base64decode(ephemeral.azurerm_key_vault_secret.kube["client-cert"].value)
client_key = base64decode(ephemeral.azurerm_key_vault_secret.kube["client-key"].value)
cluster_ca_certificate = base64decode(ephemeral.azurerm_key_vault_secret.kube["ca-cert"].value)
}
Beispiel 4 – SQL Server mit Write‑Only‑Password
Warum hier
ephemeral
?
Das Feldadministrator_login_password_wo
ist write‑only. Terraform kann das Passwort nach dem ersten Setzen nicht mehr lesen. Würdest du es im State ablegen, wäre das Geheimnis trotzdem offen. Mitephemeral
verschwindet es nach dem Apply komplett.
ephemeral "azurerm_key_vault_secret" "sql_pw" {
name = "db-admin-pw"
key_vault_id = var.kv_id
}
resource "azurerm_mssql_server" "db" {
name = "demo-sql"
resource_group_name = azurerm_resource_group.rg.name
location = azurerm_resource_group.rg.location
administrator_login = "sqladmin"
administrator_login_password_wo = ephemeral.azurerm_key_vault_secret.sql_pw.value
administrator_login_password_wo_version = 1
}
Beispiel 5 – AzAPI mit sensitive_body
Warum hier
ephemeral
?
Dassensitive_body
landet zwar nicht im State, aber wohl im Plan, sofern du kein Remote‑Plan verwendest. Markierst du das Secret zusätzlich als ephemer, verschwindet es auch aus lokalen Plan‑Dateien. Perfekt für Pull‑Requests.
variable "sql_admin_pw" {
type = string
sensitive = true
}
resource "azapi_resource" "sql_password" {
type = "Microsoft.DBforPostgreSQL/flexibleServers@2023-05-01"
name = "pg-flex"
location = azurerm_resource_group.rg.location
parent_id = azurerm_resource_group.rg.id
body = {
properties = {
version = "16"
}
}
sensitive_body = {
properties = {
administratorLoginPassword = var.sql_admin_pw
}
}
sensitive_body_version = 1
}
Ephemeral ≠ Vault / SOPS – sondern Ergänzung
Ephemeral
verhindert, dass fertige Geheimnisse im State landen.
Vault, SOPS1 oder Azure Key Vault lösen ein anderes Problem: die Speicherung und Rotation der Secrets selbst.
In der Praxis arbeitest du idealerweise so:
Quelle: Secrets liegen verschlüsselt in Vault/SOPS/Key Vault.
Transport: Terraform ruft das Secret im Apply ab.
Verarbeitung: Markiere das Attribut als ephemer.
Löschung: Nach dem Apply bleibt nichts übrig, weder im State noch im Plan.
So ergänzen sich beide Ansätze statt sich zu ersetzen.
Typische Fehlerquellen & Workarounds
Diff‑Flut bei
random_password
: Passwörter ändern sich bei jedem Lauf.
→ Gegenmittel: Passwort nur einmal erzeugen und in Key Vault ablegen.Module‑Outputs: Outputs können nicht ephemer sein.
→ Reiche nur die Secret‑ID, nicht den Wert.
Backend‑Security nicht vergessen
ephemeral
nimmt Geheimnisse aus dem State, der State bleibt trotzdem sensibel.
Sichere dein Backend:
Azure Blob Storage mit Private Endpoint.
RBAC only (kein SAS‑Token) via Managed Identity.
Versioning + Soft Delete aktivieren.
CI/CD – GitHub Actions Quickstart
name: Terraform-Apply
on:
push:
branches: [ main ]
jobs:
deploy:
runs-on: ubuntu-latest
permissions:
id-token: write
contents: read
steps:
- uses: actions/checkout@v4
- name: Azure Login (OIDC)
uses: azure/login@v2
with:
client-id: ${{ secrets.AZURE_CLIENT_ID }}
tenant-id: ${{ secrets.AZURE_TENANT_ID }}
subscription-id: ${{ secrets.AZURE_SUB_ID }}
- uses: hashicorp/setup-terraform@v3
with:
terraform_version: 1.10.0
- run: terraform init -backend-config="resource_group_name=rg-tfstate" \
-backend-config="storage_account_name=satfstate" \
-backend-config="container_name=state" \
-backend-config="key=prod.tfstate"
- env:
ARM_USE_OIDC: true
run: terraform apply -auto-approve
GitHub‑OIDC ersetzt statische Credentials, der Runner vergisst alles beim Shutdown - perfekt für ephemere Secrets.
Teamweite Einführung & Governance
Coding Guidelines: Ergänze das Team‑Style‑Guide um ein Kapitel »Wann
ephemeral
nutzen?«.Pair‑Programming: Führe
ephemeral
zunächst in Feature‑Branches ein und lasse Kolleg:innen Pull‑Requests begutachten.Dokumentation: Beschreibe im README jedes Moduls, welche Secrets ephemer sind und wo sie herkommen.
So vermeidest du Schatten‑States und stellst sicher, dass alle denselben Sicherheitsstandard leben.
Weiterführende Ressourcen
Dein nächster Schritt
Richte dir eine Sandbox ein. Klein, sicher, isoliert.
Aktualisiere dann auf Terraform 1.10 und AzureRM ≥ 4.35. Starte mit einem Mini‑Use‑Case: Hole ein Key‑Vault‑Secret und übergib es z.B. dem AKS‑Provider. Läuft das stabil, geh weiter zu Write‑Only‑Passwörtern oder AzAPI.
Einmal erfolgreich getestet, willst du nicht zurück.
Bleib unsichtbar. Deploy sauber.
Matthias
„SOPS“ steht für Secrets OPerationS, ein Open-Source-Tool von Mozilla.
Sein einziger Job: Dateien mit Geheimnissen so zu verschlüsseln, dass du sie gefahrlos im Git-Repo ablegen kannst.