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

6.5 KiB

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.