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
|
|
|
# Sicherheitsmodell
|
|
|
|
|
|
2026-03-04 15:56:58 +01:00
|
|
|
Letzte Aktualisierung: 2026-03-03
|
|
|
|
|
|
|
|
|
|
## Ziel
|
|
|
|
|
|
|
|
|
|
Kurze, verbindliche Übersicht der Sicherheitsmechanik für Web und API.
|
|
|
|
|
|
|
|
|
|
## Sicherheitskette pro Request
|
|
|
|
|
|
|
|
|
|
1. Firewall/Request-Grenze
|
|
|
|
|
2. Authentifizierung
|
|
|
|
|
3. Permission-Check
|
|
|
|
|
4. Tenant-Scope-Check
|
|
|
|
|
5. Endpoint-spezifische Regeln (z. B. Exporte, Media, Audit)
|
|
|
|
|
|
|
|
|
|
Kein Layer allein reicht aus.
|
|
|
|
|
|
|
|
|
|
## Public vs. Protected
|
|
|
|
|
|
|
|
|
|
- Public-Routen kommen aus `config/routes.php` (`public => true`).
|
|
|
|
|
- Zusätzlich sind Präfixe technisch immer public (`branding/`, `flash/`, `auth/microsoft/`, `api/`) in `lib/Http/AccessControl.php`.
|
|
|
|
|
- Alles andere erfordert Login.
|
|
|
|
|
|
|
|
|
|
API-Sonderfall:
|
|
|
|
|
|
|
|
|
|
- `pages/api/v1/auth/login().php` nutzt `ApiBootstrap::init(false)` (public Login-Endpunkt).
|
|
|
|
|
- Geschützte API-Endpunkte nutzen `ApiBootstrap::init()`.
|
|
|
|
|
|
|
|
|
|
## Auth und Login
|
|
|
|
|
|
|
|
|
|
- Web-Login ist session-basiert (`pages/auth/login().php`).
|
|
|
|
|
- Remember-Me-Autologin läuft früh in `web/index.php`.
|
|
|
|
|
- Multi-Tenant-Login wählt Tenant-Kontext serverseitig.
|
|
|
|
|
- Microsoft-SSO läuft über OIDC (`auth/microsoft/start` + `auth/microsoft/callback`) mit `state`, `nonce`, PKCE und ID-Token-Validierung.
|
|
|
|
|
|
|
|
|
|
## Permission und Tenant-Scope
|
|
|
|
|
|
|
|
|
|
- Rechte werden serverseitig geprüft (`PermissionService` + Policies).
|
|
|
|
|
- UI-Sichtbarkeit wird ebenfalls serverseitig vorbereitet (`UiAccessService` + `$viewAuth`), nicht im Template selbst entschieden.
|
|
|
|
|
- Globaler Scope-Bypass ist explizit: `tenant.scope.global`.
|
|
|
|
|
- Beispiel für harte Feature-Gates:
|
|
|
|
|
- `users.access_pdf`
|
|
|
|
|
- `custom_fields.manage`, `custom_fields.edit_values`
|
|
|
|
|
- `tenants.sso_manage`
|
|
|
|
|
- `api_audit.view`
|
|
|
|
|
|
|
|
|
|
## API-Schutz
|
|
|
|
|
|
|
|
|
|
- Zentrale API-Rate-Limits laufen in `lib/Http/ApiBootstrap.php`.
|
|
|
|
|
- API-Audit läuft zentral über `ApiAuditService`:
|
|
|
|
|
- loggt Metadaten (Pfad, Status, Dauer, Kontext)
|
|
|
|
|
- redigiert sensible Query-Parameter
|
|
|
|
|
- speichert keine Request-/Response-Bodies
|
|
|
|
|
|
|
|
|
|
## Edge-Hardening (Nginx)
|
|
|
|
|
|
|
|
|
|
- Security-Header werden zentral im Nginx gesetzt.
|
|
|
|
|
- Baseline:
|
|
|
|
|
- `X-Content-Type-Options: nosniff`
|
|
|
|
|
- `X-Frame-Options: SAMEORIGIN`
|
|
|
|
|
- `Referrer-Policy: strict-origin-when-cross-origin`
|
|
|
|
|
- `Permissions-Policy: camera=(), microphone=(), geolocation=(), payment=(), usb=()`
|
|
|
|
|
- `X-Permitted-Cross-Domain-Policies: none`
|
|
|
|
|
- Produktion ergänzt:
|
|
|
|
|
- `Strict-Transport-Security: max-age=31536000`
|
|
|
|
|
- Lokale Entwicklung setzt bewusst kein HSTS, um HTTP-/localhost-Workflows nicht zu beeinflussen.
|
|
|
|
|
|
|
|
|
|
## System-Audit (fachliche Aktionen)
|
|
|
|
|
|
|
|
|
|
- Separater Audit-Stream: `system_audit_log` (unabhängig von `api_audit_log`).
|
|
|
|
|
- Scope V2:
|
|
|
|
|
- Web: Auth-Events + Admin-Write-Aktionen.
|
|
|
|
|
- API: selektive `api.request`-Events (Write-Requests, `>=500`, Security-Endpunkte bei `>=400`).
|
|
|
|
|
- Scheduler: `scheduler.run` (Runner-Zusammenfassung) und `scheduler.job.run` (pro Joblauf).
|
|
|
|
|
- CLI: `cli.command` für zentrale Betriebsbefehle (z. B. `bin/doctor.php`).
|
|
|
|
|
- Privacy-Default:
|
|
|
|
|
- keine Request-/Response-Bodies
|
|
|
|
|
- keine Klartext-Secrets/Passwörter/Tokens/E-Mails
|
|
|
|
|
- IP/User-Agent nur gehasht (HMAC)
|
|
|
|
|
- Globaler Schalter über Settings:
|
|
|
|
|
- `system_audit_enabled` (hard-off: keine neuen Events)
|
|
|
|
|
- `system_audit_retention_days` (Retention/Purge)
|
|
|
|
|
- RBAC:
|
|
|
|
|
- `system_audit.view`
|
|
|
|
|
- `system_audit.purge`
|
|
|
|
|
|
|
|
|
|
## Schreibschutz
|
|
|
|
|
|
|
|
|
|
- Web-Schreibaktionen laufen mit CSRF-Token.
|
|
|
|
|
- Kritische Actions sind POST-only + serverseitige Validierung.
|
|
|
|
|
- API nutzt Bearer-Auth und eigenes Schutzmodell (kein Form-CSRF).
|
|
|
|
|
|
|
|
|
|
## Betriebschecks
|
|
|
|
|
|
|
|
|
|
- Permission-Set und Rollen regelmäßig prüfen.
|
|
|
|
|
- Tenant-Entzug/Scope-Verhalten testen.
|
|
|
|
|
- Rate-Limits und `429`-Verhalten bei Login/API testen.
|
|
|
|
|
- Audit-Streams bewusst getrennt nutzen:
|
|
|
|
|
- `system_audit_log`: fachliche/sicherheitsrelevante Ereignisse (summary-level)
|
|
|
|
|
- `api_audit_log`: API-Request-Telemetrie (Status, Dauer, Pfad)
|
|
|
|
|
- `import_audit_runs`, `user_lifecycle_audit_log`, `scheduled_job_runs`: Domänen-/Betriebsdetails
|
|
|
|
|
- Audit-Retention prüfen:
|
|
|
|
|
- API-Audit: 90 Tage
|
|
|
|
|
- Import-Audit: 90 Tage
|
|
|
|
|
- User-Lifecycle-Audit: 365 Tage
|
|
|
|
|
- System-Audit: konfigurierbar (Default 365 Tage)
|
|
|
|
|
|
|
|
|
|
## Vertiefung
|
|
|
|
|
|
|
|
|
|
- `/docs/anfragelimits.md`
|
|
|
|
|
- `/docs/06-security-tenant-scope.md`
|
|
|
|
|
- `/docs/rbac-permissions-playbook.md`
|