Security Architecture
Die Security-Architektur basiert auf Defense-in-Depth mit 8 Security-Layern: Transport Security (TLS 1.2+ via Traefik), Application Security (RBAC, JWT), Data Security (SHA-256 Audit-Chain, AES-256 Encryption), Container Security (Zero-Trust, Least-Privilege), File Security (ClamAV Virus-Scan), API Security (SSRF-Protection, Rate-Limiting), Authentication (SSO, native MFA/TOTP, FIPS 140-2 kompatibel) und Audit & Compliance-Unterstützung (ISO 27001, DSGVO).
Security-Layer Übersicht
┌────────────────────────────────────────────────────────────────────────┐ │ DEFENSE-IN-DEPTH (8 LAYER) │ └────────────────────────────────────────────────────────────────────────┘ Layer 1: TRANSPORT SECURITY (Traefik API-Gateway) ┌──────────────────────────────────────────────────────────────────────┐ │ • TLS 1.2/1.3 only (no SSLv3, TLS 1.0, TLS 1.1) │ │ • Strong Ciphers: ECDHE-RSA-AES-GCM, ECDHE-ECDSA, ChaCha20-Poly1305 │ │ • HSTS: max-age=31536000; includeSubDomains; preload │ │ • HTTP → HTTPS Redirect (Traefik entrypoint redirect) │ │ • Rate-Limiting: 100 req/s, burst 200 (Traefik middleware) │ │ • Internal service interfaces blocked externally (priority routing) │ │ • Cloudflare Turnstile CAPTCHA (Bot Protection) │ └──────────────────────────────────────────────────────────────────────┘ Layer 2: APPLICATION SECURITY ┌──────────────────────────────────────────────────────────────────────┐ │ • JWT Authentication (HttpOnly Cookies) │ │ • RBAC: 28+ Permission-Module, 350+ Individual Permissions │ │ • Permission cache per role, writes always fresh from DB │ │ • Permissions loaded per request, not from token │ │ • CSP Headers via Traefik: default-src 'self', script-src 'self' │ │ • X-Frame-Options: SAMEORIGIN │ │ • X-Content-Type-Options: nosniff │ │ • X-XSS-Protection: 1; mode=block │ │ • Referrer-Policy: strict-origin-when-cross-origin │ │ • Permissions-Policy: geolocation=(self), microphone=(), camera=() │ │ • CSRF Protection (built-in) │ └──────────────────────────────────────────────────────────────────────┘ Layer 3: DATA SECURITY ┌──────────────────────────────────────────────────────────────────────┐ │ • SHA-256 Audit-Chain (immutable, tamper-evident) │ │ • PII-Scrubbing (Passwords, Tokens auto-redacted) │ │ • AES-256-GCM Encryption (License-Keys, TOTP, alle Credentials) │ │ • Optimistic Locking (version field prevents concurrent mods) │ │ • Soft-Delete (Recovery-Window) │ └──────────────────────────────────────────────────────────────────────┘ Layer 4: CONTAINER SECURITY ┌──────────────────────────────────────────────────────────────────────┐ │ • Read-only Filesystem (av-worker) │ │ • Capability-Drop ALL (av-worker) │ │ • Capability-Drop 3 (ClamAV: NET_RAW, SYS_ADMIN, MKNOD) │ │ • Non-root Users (all workers: UID 1001) │ │ • no-new-privileges (Traefik, ClamAV, av-worker) │ │ • tmpfs for temporary storage (in-memory, volatile) │ │ • Resource-Limits (ClamAV: 2GB, av-worker: 1.5GB) │ │ • Redis Password Authentication (--requirepass) │ └──────────────────────────────────────────────────────────────────────┘ Layer 5: FILE SECURITY ┌──────────────────────────────────────────────────────────────────────┐ │ • Zero-Trust Virus-Scan (ClamAV, av-worker has NO file access) │ │ • Scan-Status-Tracking: PENDING → SCANNING → CLEAN/INFECTED │ │ • Quarantine-Volume (infected files isolated) │ │ • Extension-Blacklist (.exe, .bat, .sh, .dll, .js, .vbs) │ │ • MIME-Type Validation (server-side) │ │ • File-Size-Limits (Global: 100MB, per-Entity configurable) │ │ • Max-Files-Limit (per entity) │ │ • Retention-Policy (Auto-Delete after X days) │ │ • Orphan-Cleanup (unused files after 24h) │ └──────────────────────────────────────────────────────────────────────┘ Layer 6: API SECURITY ┌──────────────────────────────────────────────────────────────────────┐ │ • SSRF Protection (Webhooks, Workflow-Actions, Teams-URLs) │ │ • HMAC Signature (webhooks with shared secret) │ │ • Rate-Limiting (alle Werte ENV-bar): │ │ - Traefik Gateway: 100 req/s, burst 200 │ │ - Global /api/*: 2000/min/IP · Critical-Ops: 60/min (nur Writes) │ │ - Login: 5 Fails/15min je (IP+Konto) + 30/15min/IP Backstop │ │ - File Uploads: 200/hour/IP (FILE_UPLOAD_RATE_LIMIT) │ │ - Email Inbound: 60/min global, 30/hour/sender │ │ • Input Validation (Zod schemas) │ │ • SQL Injection Protection (Prisma ORM) │ │ • XSS Protection (DOMPurify client-side) │ │ • API-Keys (INTERNAL_API_KEY for worker auth) │ └──────────────────────────────────────────────────────────────────────┘ Layer 7: AUTHENTICATION & AUTHORIZATION ┌──────────────────────────────────────────────────────────────────────┐ │ • JWT Tokens (HttpOnly Cookies) │ │ • Password Hashing (PBKDF2-SHA512, 210k iterations — FIPS 140-2) │ │ • Multi-Factor Authentication (native TOTP + Entra ID MFA) │ │ • Entra ID SSO (Azure AD, OAuth 2.0) │ │ • API-Keys (for external integrations) │ │ • Token Refresh (refresh_token flow) │ │ • Session Management (Redis-backed, configurable expiry) │ │ • Cloudflare Turnstile CAPTCHA (Bot Protection) │ └──────────────────────────────────────────────────────────────────────┘ Layer 8: COMPLIANCE & AUDIT ┌──────────────────────────────────────────────────────────────────────┐ │ • SHA-256 Hash-Chain (tamper-evident, immutable) │ │ • Immutability (DB trigger prevents UPDATE/DELETE) │ │ • 9 Audit-Domains (AUTH, ENTITY, ADMIN, SECURITY, SLA, etc.) │ │ • Chain-Verification-API (Quick-Check & Full-Verification) │ │ • FIPS 140-2 compatible algorithms (Standard + FIPS Mode) │ │ • Supports ISO 27001, SOC 2 and GDPR audits │ │ • Retention-Policies (7+ years for Audit-Logs) │ └──────────────────────────────────────────────────────────────────────┘
1. Transport Security (Traefik API-Gateway)
TLS/SSL Configuration
Transport Security wird durch Traefik v3 als zentrales API-Gateway bereitgestellt. Traefik terminiert TLS, setzt Security-Headers und erzwingt Rate-Limits bevor Requests das Backend erreichen.
| Feature | Konfiguration | Details |
|---|---|---|
| TLS-Versionen | TLS 1.2, TLS 1.3 | Blockiert: SSLv3, TLS 1.0, TLS 1.1 (Traefik minVersion: VersionTLS12) |
| Cipher-Suites | ECDHE-RSA/ECDSA-AES-GCM, ChaCha20-Poly1305 | Perfect Forward Secrecy, 6 explizite Cipher-Suites |
| HSTS | max-age=31536000; includeSubDomains; preload | 1 Jahr, alle Subdomains, Preload-fähig |
| HTTP Redirect | 301 Permanent Redirect | Erzwingt HTTPS (Traefik entrypoint redirect) |
| Rate-Limiting | 100 req/s, burst 200 | DDoS-Schutz auf Gateway-Ebene (Traefik middleware) |
| Sperre interner Schnittstellen | Priority-Router → noop@internal | Interne Schnittstellen zwischen den Diensten sind von außen nicht erreichbar (Traefik sperrt sie) |
Externer Reverse Proxy: Wenn Eviworx hinter einem externen Reverse Proxy (z.B. Nginx, HAProxy) betrieben wird, müssen TRUSTED_PROXIES (.env) und forwardedHeaders.trustedIPs (traefik/traefik.yml) konfiguriert werden, damit Client-IPs korrekt geloggt werden und Rate-Limiting auf die echte Client-IP greift. Installation → Externer Reverse Proxy
📘 Details: Siehe Container Architecture → (Traefik Container)
Traefik Routing & Prioritäten
| Router | Rule | Priority | Middlewares |
|---|---|---|---|
| block-internal-api | PathPrefix(/api/internal) | 40 | security-headers |
| backend-api | PathPrefix(/api) | 30 | security-headers, compress, rate-limit |
| backend-ws | PathPrefix(/socket.io) | 20 | security-headers |
| frontend-spa | PathPrefix(/) | 10 | security-headers, compress, rate-limit |
2. Application Security
Role-Based Access Control (RBAC)
- 28+ Permission-Module: tickets, problems, changes, incidents, assets, contracts, licenses, workflows, cronjobs, users, settings, audit, etc.
- 200+ Individual Permissions: viewAll, viewOwn, create, editStatus, assign, approve, delete
- Rechte-Cache: pro Rolle 5 min für lesende Anfragen; ändernde Anfragen und kritische Aktionen lesen die Rechte immer frisch aus der Datenbank
- Keine Rechte im Token: Die Rechte werden bei jeder Anfrage anhand der Rolle geladen; ein älteres Token verschafft keine inzwischen entzogenen Rechte
- 4 System-Roles: END_USER, AGENT, ADMIN, APPROVER (nicht löschbar, nicht deaktivierbar)
- Unified Actor: User (Cookie) und API-Key (X-API-Key mit Rolle) durchlaufen dieselbe Rechteprüfung gegen die Matrix ihrer Rolle
📘 Details: Siehe Permissions & RBAC →, User Management → und Users & Roles API →
Security Headers (via Traefik)
Alle Security-Headers werden zentral durch die Traefik security-headers Middleware gesetzt:
| Header | Wert | Zweck |
|---|---|---|
Content-Security-Policy |
default-src 'self'; script-src 'self' https://challenges.cloudflare.com | XSS-Protection (Turnstile CAPTCHA erlaubt) |
X-Frame-Options |
SAMEORIGIN | Clickjacking-Protection |
X-Content-Type-Options |
nosniff | MIME-Sniffing verhindern |
X-XSS-Protection |
1; mode=block | XSS-Filter aktivieren |
Referrer-Policy |
strict-origin-when-cross-origin | Referrer-Leak verhindern |
Permissions-Policy |
geolocation=(self), microphone=(), camera=(self) | Browser-Permissions einschränken |
Strict-Transport-Security |
max-age=31536000; includeSubDomains; preload | HTTPS erzwingen (1 Jahr) |
3. Data Security
SHA-256 Audit-Chain
- Immutable Logs: UPDATE/DELETE verboten (DB-Trigger)
- Hash-Chain: Jedes Event verlinkt zum vorherigen via SHA-256
- Chain-Verification: API-Endpoint prüft Integrität der gesamten Kette
- PII-Scrubbing: Automatisch Passwords, Tokens, Email, Phone redacted
- Multi-Org Isolation: Separate Chains pro Organisation
- Redis-Fallback: Bei DB-Fehler → Redis-Backup (7 Tage TTL)
📘 Details: Siehe Enterprise Audit System →
Encryption at Rest
| Daten-Type | Verschlüsselung | Key-Management |
|---|---|---|
| License-Keys | AES-256-GCM | LICENSE_ENCRYPTION_KEY (env) |
| Passwords | PBKDF2-SHA512 (210k iterations) | One-way Hash (FIPS 140-2) |
| TOTP-Secrets | AES-256-GCM | TWO_FACTOR_ENCRYPTION_KEY (env) |
| Mailbox-Credentials (SMTP/IMAP) | AES-256-GCM | MAILBOX_ENCRYPTION_KEY (env) |
| Globale Credentials: SMTP-Passwort, MS-Graph & Entra-ID clientSecret, Notification-Adapter (Webex botToken, Teams appPassword) | AES-256-GCM | MAILBOX_ENCRYPTION_KEY (env) |
| JWT Tokens | HMAC-SHA256 (HS256) | JWT_SECRET (env) |
Alle globalen Credentials werden beim Speichern mit AES-256-GCM verschlüsselt (derselbe Schlüssel wie bei den Mailbox-Credentials: MAILBOX_ENCRYPTION_KEY, ersatzweise LICENSE_ENCRYPTION_KEY) und erst beim Gebrauch entschlüsselt. Lässt sich ein gespeicherter Wert nicht entschlüsseln, bricht die Funktion mit einer Fehlermeldung ab; die Credentials müssen dann neu eingegeben werden.
📘 Details: Siehe Contracts & Licenses API → (License-Key Encryption)
Optimistic Locking
- Incidents: Version-Field verhindert Concurrent-Modifications
- Problems: Version-Field für Conflict-Detection
- Assets: Version-Field bei Updates
- Contracts: Version-Field bei Financial-Updates
- Conflict-Response: 409 CONFLICT mit aktuellem Entity-State
4. Container Security
Zero-Trust Architecture (av-worker)
# av-worker: MAXIMUM HARDENING
read_only: true # Filesystem fully read-only
tmpfs:
- /app/tmp:size=64M,mode=1777 # In-memory temporary storage
- /tmp:size=64M,mode=1777
security_opt:
- no-new-privileges:true # Prevents privilege escalation
cap_drop:
- ALL # All capabilities dropped!
# AV-Worker has NO access to the uploads volume
# Communicates only via:
# 1. ClamAV TCP API (Port 3310)
# 2. Backend HTTP API (Status-Updates)
🔒 Zero-Trust: Der av-worker ist der am stärksten gehärtete Container. Siehe Container Architecture → und Attachments API →
Traefik Container Security
# Traefik: API gateway hardening
security_opt:
- no-new-privileges:true # Prevents privilege escalation
volumes:
- ./traefik/traefik.yml:/etc/traefik/traefik.yml:ro # Read-only config
- ./traefik/dynamic.yml:/etc/traefik/dynamic.yml:ro # Read-only routing
- ./certs/cert.pem:/etc/traefik/ssl/cert.pem:ro # Read-only cert
- ./certs/cert.key:/etc/traefik/ssl/cert.key:ro # Read-only key
Redis Password Authentication
Redis ist passwort-geschützt. Alle Services verbinden sich mit authentifizierter URL:
# Redis: password-protected
command: redis-server --appendonly yes --requirepass ${REDIS_PASSWORD}
# All services connect via:
# redis://:${REDIS_PASSWORD}@redis:6379
Least-Privilege Database-Access
| DB-User | Berechtigungen | Verwendet von |
|---|---|---|
helpdesk_user |
Full Access (alle Tabellen) | Backend (Migrations) |
helpdesk_jobworker |
Restricted: CronJob, JobExecution, WorkerInstance | Job-Worker |
helpdesk_readonly |
SELECT-only (alle Tabellen) | Analytics, Reporting |
📘 Details: Siehe Container Architecture → (PostgreSQL Container)
Container-Hardening Summary
| Container | Read-Only | Non-Root | Cap-Drop | no-new-priv | Resources | Härtungsgrad |
|---|---|---|---|---|---|---|
| AV-Worker | ✅ | ✅ | ✅ ALL | ✅ | 1.5G / 1C | ⭐⭐⭐⭐⭐ |
| Email-Worker | ✅ | ✅ | ✅ ALL | ✅ | 512M / 1C | ⭐⭐⭐⭐⭐ |
| Job-Worker | ✅ | ✅ | ✅ ALL | ✅ | 1G / 1C | ⭐⭐⭐⭐⭐ |
| Notification-Worker | ✅ | ✅ | ✅ ALL | ✅ | 512M / 1C | ⭐⭐⭐⭐⭐ |
| Workflow-Engine | ✅ | ✅ | ✅ ALL | ✅ | 512M / 1C | ⭐⭐⭐⭐⭐ |
| Report-Generator | ✅ | ✅ | ✅ ALL | ✅ | 1.5G / 1C | ⭐⭐⭐⭐⭐ |
| Frontend | ✅ | — | ✅ 3 caps | ✅ | 256M / 0.5C | ⭐⭐⭐⭐ |
| Traefik | Partial (ro) | — | — | ✅ | 256M / 1C | ⭐⭐⭐⭐ |
| ClamAV | ❌ | ❌ | ✅ 3 caps | ✅ | 2G / 2C | ⭐⭐⭐⭐ |
| Backend | ❌ | ❌ | ✅ 3 caps | ✅ | 2G / 2C | ⭐⭐⭐ |
| PostgreSQL | ❌ | ❌ | ✅ 2 caps | ✅ | 2G / 2C | ⭐⭐⭐ |
| Redis | ❌ | ❌ | ✅ 2 caps | ✅ | 1G / 1C | ⭐⭐⭐ |
Cap-Drop "ALL" = alle Linux-Capabilities entfernt. "3 caps" = NET_RAW, SYS_ADMIN, MKNOD. "2 caps" = NET_RAW, SYS_ADMIN. Resources = Memory-Limit / CPU-Limit. Alle Container haben JSON-Logging mit Rotation (10MB x 3).
5. File Security
Zero-Trust Virus-Scan Flow
ZERO-TRUST VIRUS-SCAN (7 SCHRITTE):
1. User uploads file
POST /api/attachments/TICKET/:id
↓
2. Backend receives file
• Stores in uploads/ volume
• Creates Attachment record (scanStatus: PENDING)
• NO direct ClamAV scan (zero-trust!)
↓
3. AV-Worker polls (every 10 seconds, SCAN_POLL_CRON)
• Backend returns list of PENDING attachments
↓
4. AV-Worker initiates scan
• TCP 3310 to ClamAV
• Sends file PATH (not content!)
• ClamAV reads from uploads/ volume (read-only)
↓
5. ClamAV scans file
• Returns: CLEAN / INFECTED / ERROR
↓
6. AV-Worker updates Backend
• Reports scan result (e.g. CLEAN)
↓
7. Backend updates Attachment
• scanStatus: PENDING → CLEAN
• If INFECTED:
- Move to quarantine/ volume
- Notify admin
- Block download
SICHERHEITS-FEATURES:
✅ av-worker has NO file access (read-only filesystem, no uploads mount)
✅ ClamAV has a read-only mount on uploads/
✅ Backend has read-write, but no scan access
✅ Quarantine volume isolates infected files
📘 Details: Siehe Attachments API → (Zero-Trust Virus-Scan Section)
File-Upload Security
- Extension-Blacklist: .exe, .bat, .sh, .dll, .js, .vbs, .msi, .com, .cmd, .scr blockiert
- MIME-Type Validation: Server-side (nicht nur Extension)
- File-Size-Limits: Global 100MB, per-Entity konfigurierbar
- Upload Rate-Limit: FILE_UPLOAD_RATE_LIMIT: 200/hour/IP (konfigurierbar)
- Max-Files-Limit: Pro Entity (z.B. max 10 Attachments pro Ticket)
- Retention-Policy: Auto-Delete nach X Tagen (konfigurierbar)
- Orphan-Cleanup: Ungenutzte Files nach 24h löschen
- Soft-Delete: Recovery-Window (Files bleiben X Tage nach Delete)
6. API Security
SSRF Protection
Webhook-URLs und externe API-Calls werden validiert, um SSRF-Angriffe zu verhindern. Dieselbe Prüfung greift beim Speichern und bei der Ausführung (Job-Worker, Workflow-Engine). Ungültige Einträge in der Allowlist werden ignoriert und geben nichts frei.
- Erlaubte Schemes: HTTP und HTTPS (kein HTTPS-Zwang), beschränkt auf erlaubte Ports — Default 80, 443, 8080, 8443, anpassbar via
SSRF_ALLOWED_PORTS - Hart geblockt (NIE per Allowlist freigebbar): localhost, 127.0.0.1, ::1, 0.0.0.0, Cloud-Metadata (169.254.169.254, metadata.google.internal, metadata.azure.com), Link-Local (fe80::), Multicast (ff00::)
- Per Default geblockt, aber via
SSRF_ALLOWLISTfreigebbar: private Netze (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, IPv6 ULA fc00::/fd00::) — z.B. für interne ERP-/Monitoring-Webhooks (IP/CIDR/Hostname, keine Ports) - Teams-URLs: Nur Microsoft-Domains erlaubt (outlook.office.com, outlook.office365.com, webhook.office.com)
📘 Details: Siehe Workflows API →, CronJobs API →, Integrations →
Rate-Limiting
| Endpoint/Feature | Limit | Zeitfenster | Typ |
|---|---|---|---|
| Traefik Gateway | 100 req/s, burst 200 | Pro Sekunde | Global (DDoS-Schutz) |
| File-Uploads | 200 | Pro Stunde | Per IP |
| E-Mail Inbound (Global) | 60 | Pro Minute | Global |
| E-Mail Inbound (Sender) | 30 | Pro Stunde | Per Sender |
| E-Mail Max-Größe | 25 MB | - | Pro E-Mail |
Umsetzung: Traefik-Rate-Limit (Gateway-Ebene) plus Limits im Backend (Anwendungsebene)
📘 Details: Siehe Integrations → (E-Mail Rate-Limiting)
Input Validation
- Zod Schemas: Alle API-Inputs werden validiert (Type-Safe)
- SQL Injection: Prisma ORM verhindert SQL-Injection (Prepared Statements)
- XSS Protection: DOMPurify client-side, CSP Headers server-side (Traefik)
- Path-Traversal: File-Paths validiert, keine ../ erlaubt
7. Authentication & Authorization
Authentication-Methoden
| Methode | Beschreibung | Use-Case |
|---|---|---|
| JWT (HttpOnly Cookies) | Standard Web-Login | Portal-User (Agents, Customers) |
| Entra ID SSO | Azure AD OAuth 2.0 | Enterprise Single-Sign-On |
| Native TOTP MFA | HMAC-SHA256 TOTP (FIPS-kompatibel) | Alle User (Security-Einstellungen) |
| Cloudflare Turnstile | CAPTCHA Bot-Protection | Login/Registrierung |
| API-Keys | Header X-API-Key für externe Systeme | Workflow-API-Trigger, Integrationen |
| INTERNAL_API_KEY | Gemeinsamer Schlüssel, mit dem sich die Worker beim Backend authentifizieren | Inter-Container-Communication |
📘 Details: Siehe Authentication API →
FIPS 140-2 kompatible Kryptografie
Das Backend verwendet ausschließlich FIPS 140-2 kompatible Algorithmen. Hinweis: Es handelt sich um die Nutzung FIPS-kompatibler Algorithmen, nicht um eine offizielle FIPS-Zertifizierung. Es gibt zwei Betriebsmodi:
| Komponente | Algorithmus | Details |
|---|---|---|
| Passwort-Hashing | PBKDF2-SHA512 | 210,000 Iterationen, 64-Byte Key, 32-Byte Salt |
| 2FA (TOTP) | HMAC-SHA256 | Nicht SHA-1 (FIPS-kompatibel) |
| Verschlüsselung | AES-256-GCM | License-Keys, TOTP-Secrets und gespeicherte Credentials |
| JWT Signing | HS256 | HMAC-SHA256 |
Betriebsmodi
| Modus | FIPS-kompatible Algorithmen | FIPS-Modus erzwungen | Docker Image |
|---|---|---|---|
| Standard | ✅ | ❌ | node:24-slim |
| Strict FIPS | ✅ | ✅ | Distroless FIPS-Base-Image (Node.js 24, OpenSSL 3.0 FIPS Provider) |
Im Strict-FIPS-Modus läuft Node.js mit --enable-fips und OpenSSL 3.0 FIPS Provider. MD5, MD4, RIPEMD160 werden blockiert. Der Startup-Check (ENABLE_FIPS=true) stoppt den Server sofort wenn crypto.getFips() !== 1.
FIPS-Konfiguration
| Variable | Default | Beschreibung |
|---|---|---|
DOCKERFILE_BACKEND | Dockerfile | Dockerfile.fips für den Strict-FIPS-Modus |
ENABLE_FIPS | false | Startup-Check: Server stoppt wenn FIPS nicht aktiv |
PBKDF2_ITERATIONS | 210000 | PBKDF2-Iterationen (Bereich: 100k–2M) |
UV_THREADPOOL_SIZE | 16 | libuv Thread Pool für async PBKDF2 |
Password-Hashing Sicherheitsmechanismen
- Verify-Whitelisting: Nur sha512, Keylen 64, Iterationen 100k–2M akzeptiert
- Timing-Safe: crypto.timingSafeEqual für Passwort-Vergleiche
- Gleiche Antwortzeit: Auch für unbekannte Konten wird ein Hash berechnet; die Antwortzeit verrät also nicht, ob ein Konto existiert
- Automatisches Rehash: Hashes mit niedrigerer Iterationszahl als konfiguriert werden beim nächsten erfolgreichen Login neu berechnet
- Hash-Format:
pbkdf2:sha512:<iterations>:<keylen>:<salt_base64>:<hash_base64> - Base64-Validierung: Strikte Prüfung von Salt und Hash-Buffers
Native MFA/TOTP
Zusätzlich zu Entra ID MFA bietet das System native TOTP-basierte Multi-Faktor-Authentifizierung:
- Algorithmus: HMAC-SHA256 (FIPS-kompatibel, nicht SHA-1)
- Secret-Verschlüsselung: AES-256-GCM via TWO_FACTOR_ENCRYPTION_KEY
- Aktivierung: User Security-Einstellungen (self-service)
- Key-Trennung: TWO_FACTOR_ENCRYPTION_KEY ist separat von JWT_SECRET
Cloudflare Turnstile CAPTCHA
- Schutz: Bot-Protection für Login und Registrierung
- CSP-Integration: challenges.cloudflare.com in script-src, connect-src, frame-src erlaubt
- Konfiguration: TURNSTILE_SITE_KEY, TURNSTILE_SECRET_KEY (env)
JWT Token Security
- HttpOnly Cookies: JavaScript kann Token nicht lesen (XSS-Protection)
- Secure Flag: Cookie nur über HTTPS übertragen
- SameSite: CSRF-Protection
- Token-Rotation: JWT_SECRET_OLD unterstützt graduelle Key-Rotation
- Keine Rechte im Token: Die Rechte werden bei jeder Anfrage anhand der Rolle geladen (verhindert Rechteausweitung über veraltete Tokens)
- Expiration: Tokens laufen ab (konfigurierbar)
Session Security
| Variable | Default | Beschreibung |
|---|---|---|
SESSION_MAX_HOURS | 12 | Hartes Session-Ende in Stunden (backend-enforced, per Refresh nicht verlängerbar) |
ACCESS_TOKEN_EXPIRY_MINUTES | 60 | Access-Token Ablaufzeit in Minuten |
REFRESH_TOKEN_EXPIRY_MINUTES | 100 | Refresh-Token Ablaufzeit in Minuten (bewusst knapp — s. Rotation unten) |
IDLE_TIMEOUT_MINUTES | 30 | Auto-Logout bei Inaktivität (Server-Wert, im Client durchgesetzt) |
COOKIE_SECURE | (NODE_ENV) | Secure-Flag der Auth-Cookies explizit erzwingen/abschalten |
JWT_SECRET_OLD | - | Vorheriger JWT-Secret für graduelle Key-Rotation |
Refresh-Token-Rotation & Diebstahl-Erkennung
- Rotation bei jedem Refresh: Ein Refresh-Token ist ein Einmal-Ticket — nach Einlösung wird er ersetzt.
- Grace-Fenster (60 Sek.): Geht die Antwort verloren (Timeout/Abbruch), darf der alte Token kurz erneut eingelöst werden — die Session strandet nicht wegen eines Netzwerkfehlers.
- Reuse-Erkennung (10 Min.): Taucht ein längst ersetzter Token danach wieder auf, gilt er als entwendet: die gesamte Session wird sofort beendet, WebSockets getrennt, Audit-Eintrag REFRESH_TOKEN_REUSE.
- Sofortiger Revoke: Session-Beendigung (Sessions-UI, Passwortwechsel, Reuse) wirkt sofort über die stabile Session-ID — unabhängig davon, wie oft der Token seither rotiert wurde.
- Im Zweifel gesperrt: Ist Redis für Blacklist-/Revoke-Prüfung nicht erreichbar, wird der Zugriff verweigert (503) statt im Zweifel gewährt.
- Beendet bleibt beendet: Wurde eine Session beendet, stellt kein Pfad je wieder Tokens für sie aus — auch nicht das Grace-Fenster der Rotation.
Brute-Force-Schutz & Rate-Limiting
Der Schutz sitzt am ZIEL-Objekt, nicht an der IP. Das ist die wichtigste Designentscheidung dieses Bereichs — denn hinter einem Firmen-NAT teilen sich alle Mitarbeitenden eine einzige IP. Ein IP-Limit, das eng genug wäre, um einen Angreifer aufzuhalten, würde dort zuerst das eigene Büro aussperren.
| Ebene | Schutz |
|---|---|
| 1. Am Objekt (die echte Bremse) | Konto-Sperre pro E-Mail mit exponentieller Verzögerung (5 Fehlversuche → bis zu 4 h), CAPTCHA ab dem 3. Fehlversuch, 2FA-Versuchslimit pro Benutzer, Passwort-Reset 1 Anfrage / 2 min pro E-Mail. Diese Grenzen greifen unabhängig davon, von wie vielen IPs ein Angreifer kommt. |
| 2. An der IP (Flood-Backstop) | Login zählt je Kombination aus IP UND Konto (5/15 min) — ein Kollege mit Tippfehler sperrt nur sich selbst; dazu ein IP-Deckel über alle Konten (30/15 min) gegen das Durchprobieren vieler Adressen. Refresh (60), Logout (120), 2FA/Reset (20), Einladungs-Prüfung (30) und der globale Deckel (2000/min) sind bewusst großzügig: Sie sollen Fluten bremsen, nicht Passwörter raten — dafür sind Refresh-/Reset-Tokens mit 64 Zeichen ohnehin nicht erratbar. |
Warum der Login-Zähler auf (IP + Konto) läuft und nicht auf der E-Mail allein: Ein reiner E-Mail-Zähler ließe sich missbrauchen, um fremde Konten gezielt auszusperren — man müsste nur oft genug ein falsches Passwort schicken. Die Paarung verhindert das.
Wer gegen eine laufende Konto-Sperre anläuft, bekommt dieselbe Antwort wie an jeder anderen Bremse: 429 mit dem Hinweis auf zu viele Fehlversuche. Ein CAPTCHA wird dabei nicht verlangt — es würde an einer laufenden Sperre nichts ändern. Die Meldung sagt damit, was wirklich vorliegt: ein Zustand auf Zeit, kein gesperrtes Konto.
Zwei Betriebshinweise: Die IP-Zähler der Ebene 2 liegen im Speicher der Backend-Instanz; ein Neustart setzt sie zurück. Die Konto-Sperren der Ebene 1 liegen in Redis und bleiben dabei erhalten. Und hinter einem externen Reverse-Proxy muss TRUSTED_PROXIES stimmen — sonst sehen alle Requests wie eine IP aus und jedes IP-Limit trifft sofort alle. Alle Werte sind ENV-bar und ohne Rebuild anhebbar: Environment → Rate-Limits.
Echtzeit-Kanäle prüfen dieselbe Sichtbarkeit
Die Anwendung hält Detailseiten live: wer ein Objekt geöffnet hat, sieht die Betrachter neben sich und bekommt Änderungen ohne Neuladen. Er prüft dieselbe Zeilen-Sicht wie der REST-Endpunkt, die Liste und die globale Suche, aus derselben Quelle.
- Zwei Ebenen, beide geprüft: der Listen-Kanal eines Typs verlangt das Leserecht dieses Typs, der Kanal eines einzelnen Objekts zusätzlich die Sicht auf genau diese Zeile — einschließlich Asset-Typ-Sperren, Mailbox- und Gruppen-Einschränkungen sowie der Freigaben eines Wissensartikels.
- Kein Raten über IDs: Wer für ein Objekt keine Sicht hat, bekommt beim Betreten eine Ablehnung statt einer Betrachter-Liste, und ein Sammel-Abonnement filtert solche Objekte still heraus. Unbekannte Typen werden abgelehnt, und die Zahl der Objekte je Abonnement ist gedeckelt.
- Folge für eingeschränkte Zeilen: Eine Verknüpfung, die nur als Platzhalter sichtbar ist, aktualisiert sich nicht live. Das ist gewollt: Der Platzhalter verrät nichts über den Inhalt, und der Live-Kanal ebenso wenig.
Wie der Kanal arbeitet, was Anwender davon sehen und welche Objektarten er abdeckt: Echtzeit & Presence →
8. Compliance & Audit
Enterprise Audit System
- SHA-256 Hash-Chain: Jeder Eintrag ist per SHA-256 mit dem vorherigen verkettet; Manipulationen werden bei der Prüfung erkannt
- Immutability: UPDATE/DELETE verboten (DB-Trigger)
- PII-Scrubbing: Automatisch Passwords, Tokens, Email, Phone redacted
- 9 Audit-Domains: AUTH, ENTITY, ADMIN, SECURITY, SLA, WORKFLOW, SYSTEM, DATA_ACCESS, NOTIFICATION
- 5 Severity-Levels: DEBUG, INFO, WARNING, ERROR, CRITICAL
- Redis-Fallback: Bei DB-Fehler → Redis-Backup (7 Tage TTL)
- Chain-Verification-API: Quick-Check & Full-Verification
📘 Details: Siehe Enterprise Audit System →
Unterstützte Standards
| Standard | Unterstützte Anforderungen |
|---|---|
| FIPS 140-2 | PBKDF2-SHA512, HMAC-SHA256, AES-256-GCM, Strict-FIPS-Modus verfügbar |
| ISO 27001 | Audit-Logging, Access-Control, Encryption, Incident-Management |
| SOC 2 | Audit-Trail, Change-Management, Monitoring, Security-Controls |
| GDPR | PII-Scrubbing, Data-Retention, User-Anonymisierung, Audit-Logs |
| NIS2 | Incident-Reporting, SLA-Tracking, Security-Monitoring |
Security Best Practices
Secrets-Management
- Alle Secrets ändern: JWT_SECRET, POSTGRES_PASSWORD, INTERNAL_API_KEY, LICENSE_ENCRYPTION_KEY, TWO_FACTOR_ENCRYPTION_KEY, REDIS_PASSWORD
- Docker Secrets: Verwende Docker Secrets (Swarm) oder Kubernetes Secrets statt ENV
- Key-Rotation: JWT_SECRET_OLD ermöglicht graduelle Rotation
- LICENSE_ENCRYPTION_KEY: NIEMALS ändern nach ersten Lizenzen (Daten-Verlust!)
- TWO_FACTOR_ENCRYPTION_KEY: NIEMALS ändern nach erster MFA-Aktivierung (TOTP-Secrets unlesbar!)
- Generation:
openssl rand -hex 32für sichere Keys
📘 Details: Siehe Environment Variables → (Secret-Generation)
Role-Based Access Control (RBAC)
- Least-Privilege: Nutze viewOwn für END_USER, viewAll nur für AGENT/ADMIN
- Custom-Roles: Erstelle Custom-Roles nur bei Bedarf (komplexer zu managen)
- Permission-Audit: Role-Changes werden geloggt (ADMIN Domain, WARNING Severity)
- Critical-Actions: tickets.delete, changes.approve immer DB-Revalidation (kein Cache)
- Permission-Cache: 5min TTL, invalidiert bei Role-Change
Password-Policy
- PBKDF2-SHA512: 210.000 Iterationen (FIPS 140-2 kompatibel, konfigurierbar via PBKDF2_ITERATIONS)
- One-Way-Hash: Passwords können nicht dekodiert werden
- Password-Reset: Secure-Token via E-Mail (zeitlich begrenzt)
- Empfehlung: Min. 12 Zeichen, Sonderzeichen, Zahlen
Security-Features nach Feature-Bereich
ITSM-Core (Tickets, Incidents, Problems, Changes)
- Permission-basierte Visibility: User sehen nur erlaubte Entities
- Internal Notes: Nur sichtbar mit viewInternal-Permission
- Optimistic Locking: Version-Field verhindert Race-Conditions
- Self-Approval Block: Requester ≠ Approver (Changes, Incidents)
- Activity-Timeline: Vollständige Audit-Trail aller Änderungen
Assets & Inventory
- QR-Code Handover: HMAC-Token für Public-Endpoint (zeitlich begrenzt)
- Type-basierte Permissions: 6 Permissions pro Asset-Type
- Financial-Data: Separate Permission für Financial-Fields
- Checkout-Tracking: Wer hat welches Asset wann (vollständiger Verlauf)
📘 Details: Siehe Assets API → (HMAC-Token, Type-Permissions)
Contracts & Licenses
- AES-256-GCM Encryption: License-Keys encrypted at-rest
- Format: iv:authTag:encrypted (Base64)
- Key-Zugriff Audit: Jeder Decrypt wird geloggt (IP, UserAgent, Timestamp)
- viewSensitive Permission: Benötigt für License-Key-Zugriff
📘 Details: Siehe Contracts & Licenses API → (AES-256-GCM Encryption)
Workflows & Automation
- SSRF Protection: Webhook-Actions validiert (private IPs nur via SSRF_ALLOWLIST, Loopback/Metadata immer geblockt)
- Circuit-Breaker: Schutz vor Cascade-Failures (Threshold: 5, Reset: 30s)
- Timeout-Protection: Webhook-Calls max. 30s
- API-Key-Auth: Workflow-API-Trigger benötigen API-Key
📘 Details: Siehe Workflows API → (SSRF-Protection, Circuit-Breaker)
Security-Incident-Response
Detection-Mechanismen
- Virus-Detection: ClamAV scannt ALLE Uploads (keine Ausnahmen)
- Intrusion-Detection: Audit-Events (SECURITY Domain) für verdächtige Aktivitäten
- Failed-Login-Tracking: Audit-Events (AUTH Domain) für Brute-Force-Detection
- Permission-Violations: Audit-Events (SECURITY Domain, ERROR Severity)
Response-Aktionen
- Infizierte Files: Automatisch in Quarantine-Volume verschoben
- Admin-Notification: Multi-Channel Alert bei Security-Events
- User-Deactivation: isActive = false (Soft-Delete, reversibel)
- Permission-Revocation: Rollen-Änderungen wirken sofort (der Rechte-Cache der Rolle wird dabei geleert)
- Audit-Investigation: Chain-Verification-API für Forensik
Security-Checkliste (Production)
Vor Production-Start
⚠️ KRITISCH - MUSS geändert werden:
- ☐ JWT_SECRET ändern (nicht default verwenden!)
- ☐ POSTGRES_PASSWORD ändern (supersecretpassword → secure)
- ☐ JOBWORKER_DB_PASSWORD ändern
- ☐ READONLY_DB_PASSWORD ändern
- ☐ INTERNAL_API_KEY ändern (openssl rand -hex 32)
- ☐ LICENSE_ENCRYPTION_KEY ändern (NIEMALS später ändern!)
- ☐ TWO_FACTOR_ENCRYPTION_KEY ändern (NIEMALS später ändern!)
- ☐ REDIS_PASSWORD ändern (openssl rand -hex 32)
- ☐ TURNSTILE_SITE_KEY + TURNSTILE_SECRET_KEY konfigurieren (Cloudflare Dashboard)
- ☐ VAPID_KEYS neu generieren (Web-Push)
Nach Production-Start
- ☐ Admin-Passwort ändern (admin@company.com) und MFA aktivieren
- ☐ SEED_DATABASE=false setzen (keine neuen Test-User)
- ☐ TLS-Zertifikate von Let's Encrypt (nicht self-signed)
- ☐ Firewall-Rules (nur 80, 443 public)
- ☐ Health-Checks überwachen
- ☐ Backup-Strategy testen (postgres_data, uploads)
- ☐ Audit-Logs regelmäßig prüfen (Chain-Verification)
- ☐ ClamAV Virus-Defs aktualisiert (Freshclam)
- ☐ FIPS-Modus erwägen für regulierte Umgebungen (DOCKERFILE_BACKEND=Dockerfile.fips)
Verwandte Dokumentation
- Container Architecture - Container-Hardening, Zero-Trust, Resource-Limits, Traefik
- Enterprise Audit System - SHA-256 Hash-Chain, Immutability, PII-Scrubbing
- User Management & RBAC - Rollen, Agent-Gruppen, Abwesenheiten
- Authentication API - JWT, Entra ID SSO, TOTP MFA, API-Keys, Token-Refresh
- Attachments API - Zero-Trust Virus-Scan, Extension-Blacklist, MIME-Validation
- Contracts & Licenses - AES-256-GCM Encryption, Key-Access-Audit
- Integrations - SSRF Protection, HMAC-Signature, Rate-Limiting
- Environment Variables - Secret-Generation, FIPS-Konfiguration, Best-Practices