Files
craftvia/docs/sicherheit/Aufgabenpaket-Sicherheit-Administration.md
T
msolarczekandClaude Opus 5 c8e6f30a27
CI / build-and-check (push) Canceled after 0s
CI / audit (push) Canceled after 0s
CI / sbom (push) Canceled after 0s
Basis: Certvia dev@a48c5fb als Fundament für Craftvia
Unveränderter Stand von certvia/dev (a48c5fb) plus Craftvia-Spezifikation
und Brandbook unter docs/craftvia/. ISMS-Module werden im Folgecommit entfernt.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-14 11:05:39 +02:00

79 lines
8.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Umsetzungspaket — Sicherheit & Administration (1 Entwickler)
> Claude-Code-Prompt. Basis-Branch **`dev`**; je Story ein Feature-Branch `dev/sec<n>-…` (PR-Ziel `dev`). Grundlage: `Sicherheit-und-Administration-Konzept.md` + Ist-Stand `STAND-dev-branch.md`.
> **Entscheidungen (fix):** Mail via **SMTP** · **1 Entwickler** (sequenziell) · **2FA bleibt optional**, aber **pro Tenant im Adminportal als Pflicht** einstellbar · **Passkeys** dabei · **DSGVO-Funktionen** dabei.
## Vorhandenes wiederverwenden (nicht neu bauen)
- **MFA-Kern** (TOTP + Recovery-Codes) für Plattform- und Mandanten-Nutzer: `src/server/mfa.ts`; Policy-Flag `securityPolicy.mfaRequired` existiert.
- **Passwort**: `src/lib/password-policy.ts` (Validierung) + `src/server/password.ts` (Argon2id + Generator); **Force-Change**-Gate im `(app)`-Layout.
- **Auth**: zwei NextAuth-Instanzen — Mandant `src/server/auth.ts` (`/login`), Plattform `src/server/platform-auth.ts` (`/platform/login`). **`PlatformAdmin`**-Store getrennt.
- **Queue**: BullMQ + Redis im Stack. **Audit-Log** mit `tenantId` nullable (`scope=platform`). **Task/TaskComment** für Ticket-/Freigabe-Ereignisse.
- **Modul-Guard**: neue Server-Actions in `scripts/check-module-guards.ts` eintragen; tenant-Modelle in `TENANT_MODELS`+RLS.
## Betriebs-/DNS-Voraussetzungen (kein Code, aber Vorbedingung)
Dedizierte Absenderdomain (`no-reply@certvia.de`) mit **SPF, DKIM, DMARC**; TLS/HSTS; SMTP-Zugangsdaten + alle Secrets aus **Env/Secret-Store** (nicht im Repo).
---
## Reihenfolge (sequenziell, 1 Entwickler)
SEC1 → SEC2 → SEC3 → SEC4 → SEC5 → SEC6. Einzelne P0-Härtungen (Rate-Limit an Login/Reset/MFA, Token-Hashing) landen **inline** in SEC2/SEC3; die globalen Härtungen bündelt SEC5.
---
## SEC1 — SMTP-Mail-Fundament (`dev/sec1-mail-smtp`) [L]
**Ziel:** zuverlässiger, gebrandeter, asynchroner Mail-Versand als Fundament für Reset/Einladung/Benachrichtigung.
- **Mail-Service** `src/server/mail/**` mit **SMTP-Transport** (nodemailer, TLS) hinter einem Interface `sendMail(template, to, vars, locale)` — Provider später austauschbar.
- **Queue/Worker** über BullMQ/Redis: asynchron, **Retry mit Backoff**, Dead-Letter, Rate-Limit; Fehler/Bounce ins Log.
- **Templates** (Certvia-gebrandet, **de/en**, HTML + Text-Alternative): Einladung, Passwort-Reset, „Passwort geändert", E-Mail-Änderung bestätigen, „MFA geändert", **Ticket-/Freigabe-/Fristen-Benachrichtigung**.
- **Benachrichtigungsregeln**: je Nutzer/Ereignis opt-in/opt-out + Sprache; strikt mandantengetrennt. Trigger aus Task-Ereignissen (Zuweisung, Freigabe-Anfrage, Entscheidung, Fälligkeit).
- **Admin-Testversand** (eine Aktion „Test-Mail senden") zur Zustellprüfung.
- **AK:** Mail wird asynchron mit Retry versendet; Templates gebrandet + zweisprachig; Bounces/Fehler geloggt; Ticket-Benachrichtigung wird bei Task-Zuweisung/Freigabe ausgelöst; keine Secrets im Repo.
## SEC2 — Passwort-Self-Service & Sessions (`dev/sec2-auth-selfservice`) [M–L] · Abh. SEC1
- **Passwort-Reset**: „Passwort vergessen" → **Single-Use-Token**, kurzlebig (30–60 Min), **serverseitig gehasht** gespeichert, an E-Mail gebunden. **Enumeration-Schutz** (immer gleiche Antwort), **Rate-Limit** je IP/Konto. Nach Reset: **alle Sessions invalidieren** + Bestätigungs-Mail + Audit; deaktivierte/gesperrte Konten erhalten keinen Reset.
- **Passwort selbst ändern**: Profilseite mit **Alt-Passwort-Bestätigung**, Policy-Prüfung, danach **andere Sessions abmelden** (aktuelle behalten), Bestätigungs-Mail + Audit.
- **E-Mail-Änderung**: **Double-Opt-in** an neue Adresse + Benachrichtigung an alte; Audit.
- **Session-Invalidierung** als wiederverwendbarer Baustein (bei Reset/Änderung/Deaktivierung/MFA-Änderung).
- **AK:** Reset-Token single-use/gehasht/rate-limited/enumeration-safe; Self-Change funktioniert; E-Mail-Änderung verifiziert; Sessions werden korrekt invalidiert; alle Ereignisse im Audit.
## SEC3 — MFA pro Tenant erzwingen + Passkeys (`dev/sec3-mfa-passkeys`) [L] · Abh. SEC1
- **Optional bleibt Default.** Im **Adminportal** kann pro Mandant `securityPolicy.mfaRequired` gesetzt werden (Superadmin) → **Enrollment-Gate**: Nutzer dieses Mandanten werden beim nächsten Login zur MFA-Einrichtung gezwungen (analog Force-Change-Gate im `(app)`-Layout). Ebenso erzwingbar für **alle Plattform-Admins**.
- **Passkeys/WebAuthn** als zusätzlicher 2. Faktor (`@simplewebauthn/server` + Browser-API): Registrierung + Login; Nutzer kann **TOTP oder Passkey** verwenden; Credentials verwaltbar (anlegen/entfernen).
- **Step-up-Re-Auth** für sensible Aktionen: MFA deaktivieren, Plattform-Admin anlegen, Datenexport, Mandant löschen.
- **TOTP-Secret at rest verschlüsselt** (falls noch Klartext) + **Rate-Limit** auf Code-Eingabe; Recovery-Codes-Flow (Anzeige/Regenerierung, Verbrauch protokolliert) abrunden.
- **AK:** Admin setzt `mfaRequired` je Tenant → betroffene Nutzer müssen beim Login enrollen; Passkey-Registrierung + -Login funktionieren; Step-up greift bei sensiblen Aktionen; TOTP-Secret verschlüsselt; MFA global weiterhin optional, wenn Policy es nicht verlangt.
## SEC4 — Plattform-Admin-Verwaltung (`dev/sec4-platform-admins`) [M] · Abh. SEC1, SEC3
- **Verwaltungs-UI** im Adminportal (`src/app/(platform)/admin/**`, Actions `platform*.ts`): weitere **`PlatformAdmin`** anlegen (Einladung via SEC1 oder Initial-Passwort), **Rollen** (z. B. „Voll-Admin" vs. „Support/Read-only"), **sperren/reaktivieren**, Passwort-Reset, **MFA-Pflicht** für Plattform-Admins.
- **Selbst-Aussperr-Schutz** auf Plattform-Ebene (letzter Voll-Admin nicht entfernbar/deaktivierbar); kritische Aktionen mit **Step-up** (SEC3).
- **Vollständiges Plattform-Audit** (`scope=platform`) jeder Aktion.
- **AK:** ein zweiter Voll-Admin ist anlegbar und kann verwalten; Rollen greifen (Read-only kann nichts ändern); Last-Admin-Schutz aktiv; jede Aktion protokolliert.
## SEC5 — Härtung P0 (quer) (`dev/sec5-hardening`) [M]
- **HTTP-Security-Header** (zentrale Middleware): CSP, HSTS, `X-Frame-Options`/`frame-ancestors`, `X-Content-Type-Options`, `Referrer-Policy`, `Permissions-Policy`.
- **Rate-Limiting/Brute-Force** global an Login/Reset/MFA/Admin-Aktionen (IP **und** kontobezogen), ergänzt den bestehenden Konto-Lockout.
- **Security-Audit erweitern**: Logins (Erfolg/Fehlschlag), Rechte-/Rollenänderungen, MFA-Änderungen, Exporte, Admin-Aktionen; **append-only**/manipulationssicher; Aufbewahrung definiert.
- **Passwort-Breach-Check** (HaveIBeenPwned k-Anonymity) beim Setzen/Ändern zusätzlich zur Policy.
- **Token-/Secret-Hygiene**: alle Tokens single-use + gehasht (Konsistenz zu SEC2/SEC3); **Secret-Scanning** in CI.
- **AK:** Header messbar gesetzt (z. B. securityheaders-Check); Rate-Limits greifen; Audit-Ereignisse vorhanden; bekannte kompromittierte Passwörter werden abgelehnt.
## SEC6 — DSGVO-Funktionen (`dev/sec6-dsgvo`) [L] · Abh. SEC1, SEC3 (Step-up)
- **Mandanten-Datenexport** (vollständig, maschinenlesbar, z. B. JSON/ZIP), Admin-getriggert, **asynchron** via Queue, Download-Link mit Ablauf.
- **Löschung/Retention**: Mandanten-Löschung (Soft→Hard mit Karenz), **Aufbewahrungsfristen**/Löschkonzept, RLS-bewusste Kaskaden; Audit; Step-up-Bestätigung.
- **Betroffenenrechte**: Export/Löschung nutzerbezogener Daten, soweit anwendbar.
- **Doku-Bausteine** (Inhalt, kein Code): AVV/DPA + TOMs — als offener fachlicher Punkt markieren.
- **AK:** vollständiger Tenant-Export erzeugbar; Löschung respektiert Retention + Audit + Step-up; DSGVO-Aktionen protokolliert.
---
## Definition of Done (jede Story)
`npx tsc --noEmit` → `npm run lint` → `npm run build` (Guard-Check) grün · neue Actions in `check-module-guards.ts` · neue tenant-Modelle in `TENANT_MODELS`+RLS+Migration (RLS-DO-Block) · Security-Verifikation (Header/Rate-Limit/Token) · Browser-Test der Flows · Demo-Umgebung lauffähig · **Secrets nur aus Env**.
## Hot Files (koordiniert, da 1 Entwickler → nur Reihenfolge beachten)
`prisma/schema.prisma` + Migrationsreihenfolge · zentrale **Middleware** (Header/Rate-Limit) · `(app)`- und `(platform)`-Layouts (Enrollment-/Force-Gates) · `src/server/auth.ts` / `platform-auth.ts` / `mfa.ts` · `scripts/check-module-guards.ts`.
## Offene fachliche Punkte
- DNS: SPF/DKIM/DMARC vor Produktivversand aktiv.
- AVV/DPA-Texte + TOMs (Datenschutz/ISB).
- Aufbewahrungsfristen je Datenart festlegen (Grundlage für SEC6-Retention).