Files
aza/AzA march 2026 - Kopie (15)/security/handovers/STEP_4_3_SECRET_KEY.md
2026-04-19 20:41:37 +02:00

4.8 KiB
Raw Permalink Blame History

STEP 4.3 HARDCODED SECRET KEY ENTFERNT (LÜCKE #19)

Status: ABGESCHLOSSEN


Fundstellen

Datei Zeile Problem
workforce_planner/config.py 18 SECRET_KEY = os.getenv("WP_SECRET_KEY", "dev-secret-change-in-production") Hardcoded Fallback-Secret
workforce_planner/api/auth.py 35, 47 Konsument: JWT encode/decode mit SECRET_KEY

Keine weiteren hardcoded Secrets gefunden:

  • basis14.py: OPENAI_API_KEY kommt aus ENV, kein Fallback
  • basis14.py: MEDWORK_API_TOKEN kommt aus ENV oder Datei, kein hardcoded Wert
  • aza_email_config.json: Passwörter im Klartext (separates GAP, nicht in diesem Schritt)

Neue ENV-Variablen

Variable Pflicht Beschreibung
AZA_SECRET_KEY Ja (ausser DEV) JWT-Signing-Key, min. 32 Zeichen
AZA_ENV Nein dev = erlaubt auto-generierten Key

Alte Variable WP_SECRET_KEY wird nicht mehr verwendet.


Implementierung

workforce_planner/config.py (komplett neu)

ALT:

SECRET_KEY = os.getenv("WP_SECRET_KEY", "dev-secret-change-in-production")

NEU:

def _load_secret_key() -> str:
    key = os.getenv("AZA_SECRET_KEY", "").strip()
    env_mode = os.getenv("AZA_ENV", "").strip().lower()

    # Kein Key: DEV auto-gen oder Fail-Start
    if not key:
        if env_mode == "dev":
            return secrets.token_hex(64)  # temporär, nur diese Session
        sys.exit(1)  # Fehlermeldung + Exit

    # Zu kurz (< 32 Zeichen): Fail-Start
    if len(key) < 32:
        sys.exit(1)

    # Triviales Muster: Fail-Start
    for pattern in ("dev", "test", "password", "secret", ...):
        if key.startswith(pattern) und nicht-alphanumerisches Folgezeichen:
            sys.exit(1)

    return key

SECRET_KEY = _load_secret_key()

workforce_planner/api/auth.py

Keine Änderung nötig importiert weiterhin SECRET_KEY aus config.py. Die Variable hat denselben Namen, der Wert kommt jetzt validiert aus ENV.


Fail-Start Verhalten

Szenario Ergebnis
Kein AZA_SECRET_KEY, kein AZA_ENV=dev Exit 1 + Fehlermeldung
AZA_ENV=dev, kein Key OK (auto-gen, Warnung auf stderr)
Key < 32 Zeichen Exit 1 + "zu kurz"
Key mit trivialem Muster ("dev-...", "test-...", "password...") Exit 1 + "triviales Muster"
Gültiger Key >= 32 Zeichen OK
Nur WP_SECRET_KEY gesetzt (alt) Exit 1 (wird ignoriert)

Testkommandos + erwartete Outputs

1. Fail-Start (kein Key)

python -c "from workforce_planner.config import SECRET_KEY"
# → Exit 1: FEHLER: AZA_SECRET_KEY ist nicht gesetzt.

2. DEV-Modus (auto-gen)

AZA_ENV=dev python -c "from workforce_planner.config import SECRET_KEY; print(len(SECRET_KEY))"
# → 128 (hex-encoded 64 Bytes) + Warnung auf stderr

3. Zu kurzer Key

AZA_SECRET_KEY=short123 python -c "from workforce_planner.config import SECRET_KEY"
# → Exit 1: FEHLER: AZA_SECRET_KEY ist zu kurz (8 Zeichen, Minimum: 32)

4. Triviales Muster

AZA_SECRET_KEY="test-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" python -c "from workforce_planner.config import SECRET_KEY"
# → Exit 1: FEHLER: AZA_SECRET_KEY enthält triviales Muster ('test')

5. Gültiger Key

AZA_SECRET_KEY=$(python -c "import secrets; print(secrets.token_hex(64))") python -c "from workforce_planner.config import SECRET_KEY; print('OK:', len(SECRET_KEY), 'chars')"
# → OK: 128 chars

Testergebnis (automatisiert)

12/12 PASS, 0/12 FAIL
GESAMTBEWERTUNG: PASS
Test Ergebnis
Fail-Start ohne Key PASS
Fehlermeldung enthält 'AZA_SECRET_KEY' PASS
DEV auto-gen Key PASS
Key geladen (128 chars) PASS
Warnung ausgegeben PASS
Fail-Start kurzer Key PASS
Fehlermeldung 'zu kurz' PASS
Fail-Start alter Fallback PASS
Fail-Start triviales Pattern (lang) PASS
Start mit gültigem Key PASS
Key geladen (64 chars) PASS
WP_SECRET_KEY allein -> Fail-Start PASS

Session/Token-Invalidierung

Impact: Bestehende JWT-Tokens (HS256), die mit dem alten Fallback-Key "dev-secret-change-in-production" signiert wurden, werden nach dem Setzen eines neuen AZA_SECRET_KEY ungültig.

  • Betroffene Nutzer müssen sich einmalig neu anmelden.
  • Dies betrifft nur den workforce_planner (Arbeitsplan-Modul).
  • basis14.py verwendet keine JWT-Tokens (nur lokales Passwort-Hashing).
  • Keine komplexe Rotation implementiert (nicht im Scope dieses Schrittes).
  • Bei Produktivbetrieb: Key einmalig setzen und dauerhaft beibehalten.

Geänderte Dateien

Datei Änderung
workforce_planner/config.py Hardcoded Fallback entfernt, _load_secret_key() mit Validierung + Fail-Start implementiert