chore: migrate project documentation into repo (18 files)

This commit is contained in:
CRM Bot
2026-06-08 23:56:27 +00:00
parent 822ffb6ccb
commit 3f5b7df178
18 changed files with 2982 additions and 0 deletions
+45
View File
@@ -0,0 +1,45 @@
# 06a Auth-Audit (Security & Data-Engineering)
**Projekt:** CRM System v1.0
**Datum:** 2026-06-04
**Auditor:** Security Data Engineer (Phase 6)
**Repository:** `Leopoldadmin/crm-system`, Branch `main`
**Scope:** JWT-Implementation, Password-Hashing, Auth-Endpoints, CORS/CSP-Header, Token-Rotation, Secrets in Git-Verlauf
---
## Findings
| ID | Severity | Kategorie | Beschreibung | Empfehlung |
|----|----------|-----------|-------------|------------|
| AUTH-01 | **PASS** | JWT-Algorithmus | HS256 mit `python-jose[cryptography]==3.3.0` gemäß Architecture-Decision Section 13.1. `decode_access_token()` validiert Signatur und Ablauf korrekt über `jwt.decode()` mit explizitem Algorithmus-Parameter. | Beibehalten. Für v1.2 RS256 evaluieren (bessere Rotation, kein Shared-Secret). |
| AUTH-02 | **PASS** | Secret-Länge | `AUTH_SECRET` wird in `config.py` mit `Field(..., min_length=32)` validiert. Ein benutzerdefinierter Validator `validate_auth_secret()` lehnt Platzhalter wie `replace-me`, `changeme` und den Literal `secret` ab. Hard-Fail bei fehlendem oder zu kurzem Secret (kein Fallback). | Keine Änderung nötig. Erfüllt NFR-2 und Architecture R-5. |
| AUTH-03 | **PASS** | Token-Expiry | 24h über `JWT_EXPIRY_HOURS` in `config.py` konfigurierbar. `create_access_token()` setzt `exp`-Claim korrekt via `datetime.now(UTC)` + `timedelta`. `decode_access_token()` fängt `JWTError` ab (deckt auch Expiry). | Kurzfristigeres Expiry (z.B. 2h) + Refresh-Token in v1.1 für höhere Sicherheit. |
| AUTH-04 | **PASS** | Token-Validation | `get_current_user` in `deps.py` nutzt `decode_access_token()`, prüft `sub`-Claim und User-Existenz (inkl. `deleted_at IS NULL`). 401-Response mit `token_expired_or_invalid` für konsistente Client-Behandlung. | Validierung ist robust. Zusätzlicher Check auf `iat`-Claim könnte Replay-Angriffe erschweren (optional). |
| AUTH-05 | **PASS** | Password-Hashing | bcrypt via `passlib[bcrypt]==1.7.4` mit `bcrypt==4.0.1`. `pwd_context` mit `deprecated="auto"`. `BCRYPT_ROUNDS=12` konfigurierbar. `hash_password()` und `verify_password()` korrekt implementiert. | Keine Änderung nötig. bcrypt 4.0.1 ist aktuell und sicher. |
| AUTH-06 | **PASS** | Kein Default-Admin | Bootstrap-Registrierung via `POST /api/v1/auth/register` nur bei leerer `users`-Tabelle. Nach erstem User → 403 (`BootstrapAlreadyCompleted`). Kein `admin/admin`-Fallback. | Erfüllt Architecture R-3. |
| AUTH-07 | **PASS** | Register-Endpoint | `POST /api/v1/auth/register` validiert via `UserRegisterRequest`: `email: EmailStr`, `password: str(min_length=8, max_length=128)`, `name: str(min_length=1, max_length=255)`. 409 bei doppelter Email (generisch), 201 bei Erfolg. | Validiert korrekt. Rate-Limiting fehlt noch (v1.1, siehe Architecture 13.4). |
| AUTH-08 | **PASS** | Login-Endpoint | `POST /api/v1/auth/login` (OAuth2Form) + `/login/json` (JSON). 401 mit generischer Meldung `"Invalid email or password"` leakt nicht, ob Email existiert. `WWW-Authenticate: Bearer` Header gesetzt. | Erfüllt FR-1.2 Akzeptanzkriterien. |
| AUTH-09 | **PASS** | Logout-Endpoint | `POST /api/v1/auth/logout` validiert Token (Dependency `get_current_user`), aber keine serverseitige Blacklist. Client-seitiger Token-Discard dokumentiert. | Für v1 akzeptabel. Server-seitige Blacklist erst in v1.1. |
| AUTH-10 | **PASS** | /users/me-Endpoint | `GET /api/v1/users/me` via `get_current_user` geschützt. 401 ohne Token, 401 mit expired Token (`token_expired_or_invalid`), `password_hash` nie im Response. | Erfüllt FR-1.6 Akzeptanzkriterien AC#7-#9. |
| AUTH-11 | **PASS** | CORS-Whitelist | `CORS_ORIGINS` aus Env-Var (Komma-separiert), Default `http://localhost:5500,http://localhost:8000`. Kein `*`. `settings.cors_origins_list` parsed korrekt. | Erfüllt Architecture R-4. |
| AUTH-12 | **INFO** | CSP-Header | In `main.py` `security_headers_middleware` gesetzt. Dev: `script-src 'self' 'unsafe-inline' ...` (für Alpine.js). Prod: nur `script-src 'self' ...` (ohne unsafe-inline) Alpine.js-Inline-Skripte würden blockiert. X-Content-Type-Options, X-Frame-Options, HSTS (Prod) gesetzt. | **Vor Produktion:** Nonce-basierte CSP für Alpine.js implementieren (v1.1 ToDo). Aktuelle Prod-CSP würde Frontend blockieren. |
| AUTH-13 | **INFO** | Refresh-Token-Rotation | `/api/v1/auth/refresh` existiert, re-signed aber nur mit gleichem Secret keine echte Rotation. Rotation ist für v1.1 geplant und im Code-Kommentar dokumentiert. | Kein Sicherheitsrisiko für v1, da Token-Expiry 24h beträgt. Für v1.1: Refresh-Token mit separatem Secret + Rotation. |
| AUTH-14 | **WARN** | Secrets im Git-Verlauf | `git log -p` zeigt Passwörter in Test-Dateien (`test_auth.py`, `test_smoke.py`, `conftest_helper.py`), z.B. `"password": "Test1234!"`, `"password": "SuperSecret123!"`. Dies sind Test-Credentials ohne Produktionsrelevanz. | Kein kritisches Risiko, aber Good-Practice: Test-Passwörter aus Git-Verlauf entfernen (via `git filter-branch` oder `git rebase`). Kein Blocker für Phase 7. |
---
## Summary: **PASS** ✅
Das Auth-System ist sicher und erfüllt alle Anforderungen aus 01-requirements.md (FR-1.x, NFR-2) und 02-architecture.md (13.113.5). JWT-Implementation, Passwort-Hashing und Endpoint-Access-Control sind korrekt implementiert. Keine kritischen Findings.
**Einzig offener Punkt:** CSP-Header muss vor Produktion auf Nonce umgestellt werden (AUTH-12), da die aktuelle Prod-CSP Alpine.js-Inline-Skripte blockieren würde. Dies ist ein geplanter v1.1-Task.
---
## Empfehlungen für Phase 7 (Quality-Reviewer)
1. **CSP-Nonce-Migration vor Deployment** Prod-CSP aktuell ohne `unsafe-inline` → Frontend funktioniert nicht. Muss vor Production-Release behoben werden.
2. **Password-Hashing-Verifikation** Sicherstellen, dass `bcrypt==4.0.1` korrekt gepinnt ist (4.1+ bricht passlib).
3. **Token-Expiry-Test automatisieren** `test_auth.py:test_expired_token_returns_401` prüft explizit `token_expired_or_invalid`, aber Integration-Test könnte race-condition bei `iat`/`exp` haben.
4. **Rate-Limiting-Akzeptanz prüfen** Ohne LoginAttempt-Tabelle (v1.1) ist der Login-Endpoint ungebremst. In Phase 7 dokumentieren, ob dies für v1-Go-Live akzeptabel ist.