Files
breadcrumb-the-shire/docs/sicherheitsmodell.md
fs 25370a1a55 add composer-unused, comprehensive docs, and project restructure
- Add icanhazstring/composer-unused as dev dependency for dependency hygiene checks
- Add German documentation (docs/) covering architecture, conventions, workflows, and developer checklists
- Add API layer (ApiAuth, ApiBootstrap, ApiResponse), audit, scheduler, custom fields, and SSO services
- Add Microsoft OIDC SSO, API token management, and user lifecycle features
- Add swagger-ui vendor integration and OpenAPI spec
- Add production Docker setup and bin/ scripts
- Update composer dependencies, config, templates, and frontend assets throughout

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-22 15:27:35 +01:00

129 lines
6.5 KiB
Markdown

# Sicherheitsmodell
Letzte Aktualisierung: 2026-02-21
## 1) Grundprinzip
Die Anwendung kombiniert mehrere Sicherheitslayer:
1. Request-Grenze (Nginx + Minty Firewall)
2. Session/Auth-Guard
3. Permission-Checks
4. Tenant-Scope-Checks
5. Endpoint-spezifische Schutzlogik (z. B. Avatar-Dateien, Exporte, Actions)
Kein einzelner Layer ist ausreichend; die Kombination ist der Schutz.
## 2) Authentifizierung
- Session-basierter Login.
- Optionales Remember-Me über `user_remember_tokens`.
- Auto-Login aus Cookie erfolgt früh in `/web/index.php`.
- Zentraler Login-Entry ist `login` (optional `login?tenant=<slug>` für Tenant-Vorauswahl).
- Unknown-Email-Verhalten im Login bleibt generisch (keine Tenant-/Account-Details vor erfolgreicher Auflösung).
Kritisch:
- Tokens sind gehasht gespeichert.
- Tokens können zentral ablaufen gelassen werden (Settings-Gefahrenzone).
## 3) Public vs. Protected Routes
- Public Routes werden in `/config/routes.php` mit `public => true` definiert.
- Daraus wird zur Laufzeit `APP_PUBLIC_PATHS` aufgebaut.
- Alles andere ist loginpflichtig.
## 4) Permission-System
- Berechtigungen sind feingranular (`permissions` + `role_permissions`).
- Rollen vergeben Berechtigungen an User (`user_roles`).
- Actions prüfen Berechtigungen explizit.
Empfehlung:
- Rechte für View/Edit/Delete getrennt halten.
- Admin-only Endpunkte immer serverseitig absichern, nicht nur im UI verstecken.
- Onboarding-PDFs für Benutzer laufen über eigenes Recht `users.access_pdf` (Single + Bulk).
- Tenant-Zusatzfelder sind getrennt abgesichert:
- `custom_fields.manage` für Definitionen/Optionen im Tenant
- `custom_fields.edit_values` für Wertepflege am User.
- `field_key` wird serverseitig erzeugt/stabil gehalten (kein editierbares UI-Feld), damit tenant-weite Eindeutigkeit erhalten bleibt.
- Theme-Wechsel für User wird tenant-spezifisch abgesichert:
- effektive Regel kommt aus `current_tenant.allow_user_theme` (Fallback global `app_theme_user`)
- Endpoint `admin/users/theme` blockt bei deaktivierter Regel mit `403` (`theme_disabled`).
- Tenant-Microsoft-SSO ist separat abgesichert:
- `tenants.sso_manage` für Pflege der Tenant-SSO-Konfiguration.
- Shared-App-Credentials bleiben unter `settings.update`.
- Secrets werden nur verschlüsselt gespeichert (`APP_CRYPTO_KEY` + AES-256-GCM), nie im Klartext gerendert.
- Profil-Sync ist tenant-spezifisch konfigurierbar (`sync_profile_on_login`, `sync_profile_fields`).
- Erlaubte Sync-Felder: `first_name`, `last_name`, `phone`, `mobile`, `avatar`.
- Graph-basierte Felder (`phone/mobile/avatar`) laufen fail-open: Login bleibt erfolgreich, auch wenn Graph nicht verfügbar ist.
## 5) Tenant Scope
- Datenzugriff für tenant-gebundene Inhalte erfolgt nur bei Tenant-Match.
- Departments sind genau einem Tenant zugeordnet (`departments.tenant_id`).
- Beim Speichern von User-Zuordnungen werden Departments serverseitig gegen die aktuell zugewiesenen User-Tenants gefiltert; ungültige Department-Zuordnungen werden entfernt.
- User-Zusatzfeldwerte werden auf Tenant-Wechsel bereinigt (Werte außerhalb der aktuell zugewiesenen Tenants werden gelöscht).
- Filterbare Zusatzfelder sind auf sichere Typen begrenzt (`select`, `multiselect`, `boolean`, `date`); freie Texttypen werden nicht als dynamische Filter zugelassen.
- Theme-Auflösung ist tenant-spezifisch: `default_theme` und `allow_user_theme` werden je `current_tenant` aufgelöst; ohne Tenant-Snapshot greifen globale Defaults.
- SSO-Mapping bleibt tenant-scoped:
- Primär über externe Identität (`provider + tid + oid`).
- Fallback einmalig über E-Mail (create-or-link), danach feste Identity-Linkung.
- Domain-Allowlist (falls gesetzt) wird im Callback serverseitig erzwungen.
- Profil-Sync überschreibt nur konfigurierte Felder und ignoriert leere Quelle-Werte;
`email` bleibt nach JIT-Create unverändert (insert-only).
- Lokaler/SSO-Login ist nur mit mindestens einem aktiven User-Tenant erlaubt (kein Sonderfall ohne Tenant).
- Strict/Non-Strict Verhalten über `TENANT_SCOPE_STRICT`.
- Inaktiv-Status von Tenants beeinflusst Sichtbarkeit (je nach Kontext).
## 6) Verbotene Zugriffe
- Bei fehlender Permission/Tenant-Bindung: forbidden flow (403 Seite) statt stilles Durchrutschen.
- Keine sensitiven Details in Fehlermeldungen leaken.
## 7) Datei-/Media-Endpunkte
- Avatar/Favicon/Logo Endpunkte prüfen Session + Zugriffskontext.
- Storage liegt außerhalb direkter Business-Logik; Zugriff nur über kontrollierte Endpunkte/Symlinks.
## 8) CSRF und Form-Schutz
- Schreibaktionen nutzen CSRF-Token.
- Delete/Status-Aktionen nur per POST und serverseitiger Validierung.
- Bulk-Download für Onboarding-PDF (`admin/users/access-pdf-bulk`) ist POST+CSRF, Scope bleibt aktiv.
- OIDC-Loginfluss nutzt `state`, `nonce` und PKCE; Callback validiert zusätzlich `aud`, `iss`, `tid`, Signatur (JWKS), `exp/nbf`.
## 9) Operative Checks
Regelmäßig prüfen:
- Inaktive Rollen/Permissions werden nicht mehr aktiv zugewiesen/ausgewertet.
- Tenant-Entzüge invalidieren Sichtkontext erwartungsgemäß.
- Remember-Tokens können zentral invalidiert werden.
- Mail-Log enthält Fehlerdaten für Auditing.
- User-Lifecycle-Policy (falls aktiv) läuft täglich und setzt inaktive Accounts automatisch auf `inactive`
bzw. löscht sie später (2-stufig), privilegierte Admins sind ausgenommen.
- Delete schreibt vorher zwingend ein Audit-Snapshot (fail-closed).
- Snapshot ist verschlüsselt gespeichert (`snapshot_enc`) und enthält keine Secrets/Tokens.
- Restore ist separat berechtigt (`users.lifecycle_restore`) und stellt bewusst keine Assignments wieder her.
- Geplante Aufgaben (Scheduler) sind Whitelist-basiert:
- keine frei ausführbaren Shell-Kommandos aus der Datenbank.
- zentrale Rechte: `jobs.view`, `jobs.manage`, `jobs.run_now`.
- Runner-Lock verhindert parallele Mehrfach-Ausführung.
## 10) API-Audit
- Alle `/api/v1/*` Requests werden zentral mit Metadaten in `api_audit_log` protokolliert.
- V1 speichert keine Request-/Response-Bodies, nur Metadaten (Pfad, Status, Dauer, Scope-Kontext).
- Query-Parameter werden redacted gespeichert (z. B. Token/Secret/Password-Felder).
- Zugriff auf die Audit-UI ist über Permission `api_audit.view` abgesichert.
- Retention ist auf 90 Tage ausgelegt (Bereinigung per Admin-Action oder Cron).
## 11) User-Lifecycle-Audit
- Lifecycle-Audit-UI ist über `user_lifecycle_audit.view` abgesichert.
- Restore aus Delete-Snapshot ist getrennt über `users.lifecycle_restore` abgesichert.
- Ohne gültigen Snapshot wird kein Auto-Delete ausgeführt (fail-closed).
- Retention für Lifecycle-Audit-Einträge: 365 Tage.