Best Practice: Secrets Management
Kontext
Secrets – Datenbankpasswörter, API-Keys, TLS-Zertifikate, OAuth-Client-Secrets – sind das sensibelste Artefakt in jeder Cloud-Architektur. Gleichzeitig ist Secrets Management das am häufigsten falsch implementierte Sicherheitskonzept.
Reale Konsequenzen schlechten Secrets Managements:
-
GitHub Secret Leaks: Tausende Repositories enthalten aktive AWS Access Keys in der Commit-Historie – auch nach Löschung der Dateien über
git log -
CI/CD Credential Exposure: Build-Logs mit
echo $DATABASE_PASSWORDwerden in Artifact-Storage abgelegt und sind für alle CI-Nutzer sichtbar -
Shared Service Credentials: Ein Datenbankpasswort wird an 5 Entwickler und 3 Services verteilt – Rotation bricht alle gleichzeitig, wird deshalb nie durchgeführt
-
Hardcoded in Docker Images: ENV-Variablen in Dockerfiles landen im Image-Layer und sind in jeder Image-Kopie sichtbar
Zugehörige Controls
-
WAF-SEC-060 – Secrets Management – No Hardcoded Credentials
-
WAF-SEC-030 – Encryption at Rest with CMK
Warum Secrets Management kritisch ist
Ein einziger exponierter AWS Access Key mit umfangreichen Berechtigungen kann innerhalb von Minuten zu:
-
Vollständiger Datenexfiltration (S3, RDS-Snapshots)
-
Crypto-Mining auf allen EC2-Instanzen (Kostenpotenzial: Tausende Euro pro Tag)
-
Erstellung von Backdoor-IAM-Users für persistenten Zugang
-
Löschung kritischer Ressourcen (DynamoDB-Tables, S3-Buckets)
führen. AWS selbst erkennt exponierte Keys in öffentlichen GitHub-Repositories durch die GitHub Secret Scanning Integration – aber Reaktion kommt oft zu spät.
Tool-Vergleich: Secrets Manager, SSM Parameter Store, HashiCorp Vault
| Kriterium | AWS Secrets Manager | SSM Parameter Store | HashiCorp Vault |
|---|---|---|---|
Kosten |
~0,40 USD pro Secret pro Monat + API-Aufrufe |
Standard kostenlos; Advanced: ~0,05 USD pro Parameter |
Open Source kostenlos; Enterprise-Features kostenpflichtig |
Automatische Rotation |
Nativ für RDS, DocumentDB, Redshift; Custom Lambda für alle anderen |
Nicht nativ; Custom-Skripte erforderlich |
Nativ für Datenbanken, Cloud-Credentials, SSH |
Dynamic Secrets |
Nicht nativ |
Nicht nativ |
Nativ – Schlüsselfeature |
Cross-Account Zugriff |
Resource-based Policy; IAM |
IAM mit Account-spezifischen ARNs |
Token-basiert; Cloud-agnostisch |
Audit Log |
CloudTrail |
CloudTrail |
Vault Audit Log (detaillierter) |
KMS-Integration |
Nativ; CMK pro Secret konfigurierbar |
Nativ für SecureString |
Transit Engine; eigene Verschlüsselung |
Multi-Cloud |
AWS-only |
AWS-only |
Cloud-agnostisch |
Empfehlung |
Für AWS-native Workloads; Datenbankpasswörter mit auto-rotation |
Für Konfigurationswerte und weniger sensitive Secrets |
Für Multi-Cloud, Dynamic Secrets, komplexe Hierarchien |
Secret-Rotation
Automatische Rotation mit AWS Secrets Manager
resource "aws_secretsmanager_secret" "db_password" {
name = "production/payment-service/db-password"
description = "PostgreSQL-Passwort für den Payment-Service"
# CMK-Verschlüsselung – kein AWS-managed Key
kms_key_id = aws_kms_key.secrets_cmk.arn
# Recovery Window: mindestens 7 Tage (WAF-SEC-060)
recovery_window_in_days = 30
tags = {
owner = "platform-team"
workload = "payment-service"
data-class = "confidential"
environment = "production"
}
}
resource "aws_secretsmanager_secret_rotation" "db_password" {
secret_id = aws_secretsmanager_secret.db_password.id
rotation_lambda_arn = aws_lambda_function.rds_rotation.arn
rotation_rules {
automatically_after_days = 30 # Rotation alle 30 Tage
}
}
AWS-managed Rotation für RDS
Für RDS, Aurora, DocumentDB, ElastiCache und Redshift bietet AWS vorgefertigte Rotation-Lambda-Funktionen ohne Custom Code:
resource "aws_secretsmanager_secret" "rds_master" {
name = "production/payment-db/master-credentials"
kms_key_id = aws_kms_key.secrets_cmk.arn
recovery_window_in_days = 30
tags = {
owner = "platform-team"
data-class = "confidential"
}
}
resource "aws_secretsmanager_secret_version" "rds_master_initial" {
secret_id = aws_secretsmanager_secret.rds_master.id
secret_string = jsonencode({
username = "payment_svc"
password = random_password.db_initial.result
engine = "postgres"
host = aws_db_instance.payment.address
port = 5432
dbname = "payment"
})
}
# Rotation über AWS-managed Lambda – keine Custom Lambda erforderlich
resource "aws_secretsmanager_secret_rotation" "rds_master" {
secret_id = aws_secretsmanager_secret.rds_master.id
rotation_lambda_arn = "arn:aws:lambda:eu-central-1:${data.aws_caller_identity.current.account_id}:function:SecretsManagerRDSPostgreSQLRotationSingleUser"
rotation_rules {
automatically_after_days = 30
}
}
Dynamic Secrets Konzept
Dynamic Secrets sind Credentials, die per Session on-demand generiert und nach einer festgelegten Zeit automatisch ungültig werden. HashiCorp Vault implementiert dieses Konzept nativ für Datenbanken:
Ablauf Dynamic Secrets (HashiCorp Vault Database Engine):
1. Payment-Service startet → Authentifiziert sich bei Vault via Kubernetes Auth
2. Vault generiert temporären Datenbankbenutzer:
- Username: v-k8s-payment-abcd1234
- Password: zufällig generiert
- TTL: 1 Stunde (danach automatisch gelöscht)
3. Payment-Service verbindet zur Datenbank mit diesen Credentials
4. Nach 1 Stunde: Vault löscht den Datenbankbenutzer automatisch
5. Payment-Service erneuert Credentials 15 Minuten vor Ablauf
Vorteile:
-
Kein dauerhaftes Passwort – nichts zu stehlen und langfristig zu missbrauchen
-
Vollständiger Audit-Trail: jeder Datenbankzugang ist einem Service-Token zuordenbar
-
Rotation ist inhärent – Credentials sind per Design kurzlebig
Secrets in CI/CD: GitHub OIDC + AWS STS
Statische AWS Access Keys in CI/CD sind eines der größten Risiken. Die Alternative: GitHub OIDC erlaubt GitHub Actions, temporäre AWS-Credentials ohne statische Keys zu erhalten:
# OIDC Provider für GitHub registrieren
resource "aws_iam_openid_connect_provider" "github" {
url = "https://token.actions.githubusercontent.com"
client_id_list = ["sts.amazonaws.com"]
thumbprint_list = [
"6938fd4d98bab03faadb97b34396831e3780aea1",
"1c58a3a8518e8759bf075b76b750d4f2df264fcd"
]
}
# IAM-Rolle für den Deployment-Workflow
resource "aws_iam_role" "github_deployment" {
name = "github-actions-payment-service-deploy"
assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [{
Effect = "Allow"
Principal = {
Federated = aws_iam_openid_connect_provider.github.arn
}
Action = "sts:AssumeRoleWithWebIdentity"
Condition = {
StringEquals = {
"token.actions.githubusercontent.com:aud" = "sts.amazonaws.com"
}
StringLike = {
# Nur der main-Branch des spezifischen Repositories
"token.actions.githubusercontent.com:sub" = "repo:acme-corp/payment-service:ref:refs/heads/main"
}
}
}]
})
}
GitHub Actions Workflow-Konfiguration (kein statischer Key):
name: Deploy Payment Service
on:
push:
branches: [main]
permissions:
id-token: write # OIDC Token anfordern
contents: read
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Configure AWS Credentials via OIDC
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: arn:aws:iam::123456789012:role/github-actions-payment-service-deploy
aws-region: eu-central-1
# Kein aws-access-key-id oder aws-secret-access-key erforderlich
- name: Deploy to ECS
run: |
aws ecs update-service \
--cluster production \
--service payment-service \
--force-new-deployment
Anti-Patterns
| Anti-Pattern | Warum gefährlich |
|---|---|
Secrets in Umgebungsvariablen im Dockerfile |
Landen in Image-Layers; sichtbar in |
Secrets in Terraform-State |
State-File enthält alle Werte im Klartext; S3-Backend braucht CMK-Verschlüsselung |
Secrets in Git (auch nach |
In der Commit-Historie erhalten; via |
Passwörter nie rotieren, weil Rotation Aufwand macht |
Kompromittierte Credentials bleiben ewig gültig; GDPR Art. 32 und BSI C5 fordern periodische Rotation |
Secrets teilen zwischen Staging und Production |
Leak in Staging kompromittiert Production; keine Audit-Trennung möglich |
Monitoring und Drift-Prüfung
-
wafpass check --pillar security --controls WAF-SEC-060– prüft Secrets Manager Konfiguration -
AWS Config Rule
secretsmanager-rotation-enabled-check– prüft Rotation-Status -
AWS Config Rule
secretsmanager-using-cmk– prüft CMK-Verschlüsselung -
GuardDuty
CredentialAccess:IAMUser/AnomalousBehavior– Credential-Missbrauch -
GitHub Advanced Security Secret Scanning – exponierte Keys in Repositories
-
trufflehog/gitleaksin Pre-Commit-Hook – verhindert Commits mit Secrets