Secret-Rotation
Warum Secrets rotiert werden sollten
| Risiko | Wie die Rotation es abmildert |
|---|---|
| Leak von Anmeldedaten | Ein geleaktes Passwort wird nach dem nächsten Rotationszyklus ungültig |
| Langlebige Tokens | Kürzere Lebensdauern verkleinern das Zeitfenster für einen Angreifer |
| Zugriff ehemaliger Mitarbeiter | Nach dem Offboarding rotierte Anmeldedaten sind selbst dann nutzlos, wenn sie auswendig gelernt wurden |
| Compliance-Anforderungen | PCI-DSS, SOC 2 und ISO 27001 schreiben regelmäßige Änderungen der Anmeldedaten vor |
Rotations-Workflow
Aktualisieren Sie immer zuerst das Zielsystem und speichern Sie erst danach in Passwork. Wenn Sie zuerst in Passwork speichern und die Aktualisierung des Zielsystems fehlschlägt, hält Passwork das neue Passwort, während das System weiterhin das alte verwendet — Ihre Systeme sind dann nicht mehr synchron.
1. Generate new secret
↓
2. Apply to target system (database, API provider, etc.)
↓
3. Verify the new credential works
↓
4. Update Passwork (passwork-cli update / Python SDK)
↓
5. Notify / update downstream consumers
Rotation über die CLI
PostgreSQL
#!/bin/bash
set -euo pipefail
PASSWORK_ITEM_ID="<postgres-item-id>"
DB_USER="order_service"
DB_HOST="pg.prod.internal"
# 1. Generate a new password
NEW_PASS=$(openssl rand -base64 32 | tr -d '=+/' | cut -c1-32)
# 2. Apply to PostgreSQL
psql -h "$DB_HOST" -U postgres -d postgres \
-c "ALTER ROLE ${DB_USER} WITH PASSWORD '${NEW_PASS}';"
# 3. Update in Passwork
passwork-cli update --password-id "$PASSWORK_ITEM_ID" --password "$NEW_PASS"
echo "Rotated password for ${DB_USER}"
MySQL
#!/bin/bash
set -euo pipefail
PASSWORK_ITEM_ID="<mysql-item-id>"
DB_USER="inventory_svc"
NEW_PASS=$(openssl rand -base64 32 | tr -d '=+/' | cut -c1-32)
mysql -h mysql.prod.internal -u root \
-p"$(passwork-cli get --password-id '<mysql-root-item-id>')" \
-e "ALTER USER '${DB_USER}'@'%' IDENTIFIED BY '${NEW_PASS}';"
passwork-cli update --password-id "$PASSWORK_ITEM_ID" --password "$NEW_PASS"
echo "Rotated password for ${DB_USER}"
Externer API-Schlüssel
#!/bin/bash
set -euo pipefail
PASSWORK_ITEM_ID="<stripe-item-id>"
OLD_KEY=$(passwork-cli get --password-id "$PASSWORK_ITEM_ID")
# 1. Request new key from external service (provider-specific)
NEW_KEY=$(curl -s -X POST "https://api.service.example.com/keys/rotate" \
-H "Authorization: Bearer ${OLD_KEY}" \
-H "Content-Type: application/json" | jq -r '.new_key')
# 2. Verify the new key works
curl -s "https://api.service.example.com/verify" \
-H "Authorization: Bearer ${NEW_KEY}" | grep -q '"status":"ok"'
# 3. Save to Passwork
passwork-cli update --password-id "$PASSWORK_ITEM_ID" --password "$NEW_KEY"
echo "API key rotated"
Rotation über das Python SDK
Der Python-Connector gibt Ihnen volle Kontrolle über den Rotations-Workflow — Fehlerbehandlung, Logging, Transaktionssemantik und nachgelagerte Benachrichtigungen.
#!/usr/bin/env python3
"""PostgreSQL password rotation with full error handling."""
import os
import secrets
import sys
import psycopg2
from passwork import Client
from passwork.exceptions import PassworkResponseError
def rotate_postgres_password(item_id: str, db_user: str) -> bool:
client = Client(
url=os.environ["PASSWORK_HOST"],
token=os.environ["PASSWORK_TOKEN"],
refresh_token=os.environ.get("PASSWORK_REFRESH_TOKEN"),
)
# Fetch admin credentials from Passwork
admin_item = client.get_password(item_id=os.environ["PG_ADMIN_ITEM_ID"])
new_password = secrets.token_urlsafe(32)
try:
# Apply to PostgreSQL first
conn = psycopg2.connect(
host=admin_item.fields["PG_HOST"],
dbname="postgres",
user=admin_item.login,
password=admin_item.password,
)
conn.autocommit = True
with conn.cursor() as cur:
cur.execute("ALTER ROLE %s WITH PASSWORD %s", (db_user, new_password))
conn.close()
except psycopg2.Error as e:
print(f"Database error — password NOT changed: {e}", file=sys.stderr)
return False
try:
# Only update Passwork after the target system is confirmed updated
item = client.get_password(item_id=item_id)
item.password = new_password
client.update_password(item)
except PassworkResponseError as e:
# Critical: DB password changed but Passwork not updated
# Alert on-call immediately
print(
f"CRITICAL: DB password rotated but Passwork update failed! "
f"API error {e.code}: {e.message}",
file=sys.stderr,
)
return False
print(f"Password rotated for {db_user}")
return True
if __name__ == "__main__":
success = rotate_postgres_password(
item_id=os.environ["TARGET_ITEM_ID"],
db_user=os.environ["PG_DB_USER"],
)
sys.exit(0 if success else 1)
Planung der Rotation
Cron (Linux)
# /etc/cron.d/passwork-rotation
# Rotate production DB passwords every Sunday at 03:00
0 3 * * 0 deploy /opt/scripts/rotate-postgres.sh \
>> /var/log/passwork-rotation.log 2>&1
Geplante GitLab-CI-Pipeline
# .gitlab-ci.yml
rotate_secrets:
stage: maintenance
image: passwork/passwork-cli:latest
script:
- pip install passwork-python
- python /scripts/rotate-all.py
rules:
- if: '$CI_PIPELINE_SOURCE == "schedule"'
Konfigurieren Sie den Zeitplan unter CI/CD → Schedules (z. B. jeden Sonntag um 03:00 UTC).
Empfohlene Rotationsfrequenzen
| Secret-Typ | Frequenz |
|---|---|
| Produktions-Datenbankpasswörter | 30–90 Tage |
| Externe API-Schlüssel | 90 Tage oder gemäß Anbieterrichtlinie |
| API-Tokens von Service-Accounts (Passwork) | 30 Tage |
| SSH-Schlüssel | 6–12 Monate |
| TLS-Zertifikate | Vor Ablauf (automatisieren über certbot oder ACME) |
Umgang mit nachgelagerten Verbrauchern
Wenn ein Secret rotiert wird, muss jeder Dienst, der es verwendet, den neuen Wert neu laden. Häufige Muster:
Injection von Umgebungsvariablen beim Start: wenn Dienste ihre Secrets beim Start über passwork-cli exec laden, übernehmen sie den neuen Wert beim nächsten Neustart. Kombinieren Sie dies mit einem rollierenden Neustart nach der Rotation.
Sidecar-Aktualisierung: in Kubernetes aktualisiert das Sidecar-Muster (siehe CI/CD-Muster) periodisch die .env-Datei. Die Anwendung überwacht Dateiänderungen und lädt ohne Neustart neu.
Benachrichtigung nach der Rotation: senden Sie im Rotationsskript nach der Aktualisierung von Passwork eine Benachrichtigung an den relevanten Slack-Channel oder lösen Sie eine Deployment-Pipeline aus, die die betroffenen Dienste neu startet.
Die vollständige Rotations-Referenz finden Sie unter Praktiken der Secret-Rotation.