Secrets Management Best Practices
Secrets Management: Credentials sicher verwalten
Secrets gehören nie in den Code. Lernen Sie, wie Sie Passwörter, API-Keys und andere sensible Daten sicher verwalten.
Was sind Secrets?
❌ NIEMALS im Code: - Datenbank-Passwörter - API-Keys und Tokens - Private Keys (SSH, SSL) - OAuth Client Secrets - Encryption Keys - Service Account Credentials
Die Basics: Environment Variables
# .env (NICHT in Git!) DATABASE_URL=postgres://user:password@localhost:5432/mydb API_KEY=sk_live_abc123 JWT_SECRET=super-secret-key # .env.example (in Git, ohne echte Werte) DATABASE_URL=postgres://user:password@host:5432/db API_KEY=your-api-key-here JWT_SECRET=change-me # .gitignore .env .env.local .env.*.local *.pem *.key
// Node.js
require('dotenv').config();
const dbUrl = process.env.DATABASE_URL;
// PHP
$dbUrl = getenv('DATABASE_URL');
// Python
import os
db_url = os.environ.get('DATABASE_URL')
Secrets in CI/CD
# GitHub Actions: Secrets
# Settings → Secrets → Actions
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Deploy
env:
DATABASE_URL: ${{ secrets.DATABASE_URL }}
API_KEY: ${{ secrets.API_KEY }}
run: ./deploy.sh
# GitLab CI: Variables
# Settings → CI/CD → Variables
deploy:
script:
- echo $DATABASE_URL # Aus GitLab Variables
variables:
DEPLOY_ENV: production
Docker Secrets
# Docker Swarm
echo "mysecretpassword" | docker secret create db_password -
# docker-compose.yml
version: '3.8'
services:
app:
image: myapp
secrets:
- db_password
environment:
- DB_PASSWORD_FILE=/run/secrets/db_password
db:
image: postgres
secrets:
- db_password
environment:
- POSTGRES_PASSWORD_FILE=/run/secrets/db_password
secrets:
db_password:
external: true
# Im Container: /run/secrets/db_password enthält das Secret
Kubernetes Secrets
# Secret erstellen
kubectl create secret generic db-credentials \
--from-literal=username=admin \
--from-literal=password=secret123
# Oder aus Datei
kubectl create secret generic tls-cert \
--from-file=cert.pem --from-file=key.pem
# Als YAML (base64 encoded!)
apiVersion: v1
kind: Secret
metadata:
name: db-credentials
type: Opaque
data:
username: YWRtaW4= # echo -n 'admin' | base64
password: c2VjcmV0MTIz # echo -n 'secret123' | base64
# Im Deployment verwenden
spec:
containers:
- name: app
env:
- name: DB_USER
valueFrom:
secretKeyRef:
name: db-credentials
key: username
- name: DB_PASS
valueFrom:
secretKeyRef:
name: db-credentials
key: password
# Oder als Volume
volumeMounts:
- name: secrets
mountPath: /etc/secrets
readOnly: true
volumes:
- name: secrets
secret:
secretName: db-credentials
HashiCorp Vault
# Vault starten (Dev)
vault server -dev
# Secret speichern
vault kv put secret/myapp/config \
db_password="supersecret" \
api_key="sk_live_123"
# Secret lesen
vault kv get secret/myapp/config
vault kv get -field=db_password secret/myapp/config
# In Anwendung (Node.js)
const vault = require('node-vault')();
async function getSecrets() {
const result = await vault.read('secret/data/myapp/config');
return result.data.data;
}
# Kubernetes Integration (Vault Agent)
# Automatische Secret-Injection in Pods
AWS Secrets Manager
# Secret erstellen
aws secretsmanager create-secret \
--name myapp/production/db \
--secret-string '{"username":"admin","password":"secret"}'
# Secret lesen (CLI)
aws secretsmanager get-secret-value --secret-id myapp/production/db
# In Node.js
const { SecretsManagerClient, GetSecretValueCommand } = require('@aws-sdk/client-secrets-manager');
const client = new SecretsManagerClient({ region: 'eu-central-1' });
async function getSecret(secretId) {
const command = new GetSecretValueCommand({ SecretId: secretId });
const response = await client.send(command);
return JSON.parse(response.SecretString);
}
// In Lambda
const secrets = await getSecret('myapp/production/db');
console.log(secrets.username);
Git-Leaks verhindern
# Pre-commit Hook mit gitleaks
# .pre-commit-config.yaml
repos:
- repo: https://github.com/gitleaks/gitleaks
rev: v8.18.0
hooks:
- id: gitleaks
# Oder manuell
gitleaks detect --source . --verbose
# Wenn Secret committet wurde:
# 1. Secret SOFORT rotieren (neues erstellen)
# 2. Altes Secret invalidieren
# 3. History bereinigen (git filter-branch oder BFG)
# ACHTUNG: Bei Public Repos ist es zu spät!
Best Practices
✅ Do:
- Secrets in Secret Manager (nicht .env in Prod)
- Regelmäßig rotieren
- Least Privilege (minimale Rechte)
- Audit-Logging wer auf Secrets zugreift
- Separate Secrets pro Umgebung
❌ Don't:
- Secrets in Git (auch nicht "kurz")
- Secrets in Logs ausgeben
- Gleiche Secrets für Dev/Prod
- Secrets in URLs/Query Params