Commit Graph
7 Commits
Author SHA1 Message Date
patrickandClaude Opus 4.8 2b74f95e68 fix(security): K-5 – LDAP/CalDAV/SMTP-Verschlüsselung auf zentralen Datenschlüssel
ldap_service/caldav_service/email_service hatten je eine eigene _fernet()/
_decrypt_password(), die am JWT-SECRET_KEY hing. Damit honorierten sie das in
core/crypto bereits umgesetzte SECRET_KEY_DATA NICHT – eine JWT-Key-Kompromittierung
hätte weiterhin LDAP-/CalDAV-/SMTP-Passwörter offengelegt.

Jetzt delegieren alle drei an core.crypto.get_fernet_key()/decrypt_value. Da auf
beiden Servern SECRET_KEY_DATA nicht gesetzt ist, ist die Ableitung heute identisch
(sha256(SECRET_KEY)) → bestehende verschlüsselte Werte bleiben lesbar, kein Bruch.
Sobald SECRET_KEY_DATA gesetzt wird, gilt die Trennung dann konsistent für ALLE
Datenverschlüsselung (TOTP + LDAP + CalDAV + SMTP).

190/190 Tests grün. Deployed 137 + 164.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-23 13:56:01 +02:00
patrickandClaude Opus 4.8 6fa66b8c13 feat: agent-11 PR1 – Vertretung, Storno-Re-Genehmigung, Kommentare
Abwesenheits-Modul abgerundet (Feature-Parität mit Urlaubsverwaltung):

- Vertretung: Overlap-Warnung beim Anlegen, E-Mail an Vertretung bei
  Genehmigung, GET /absences/?as_substitute=true, neuer schlanker
  GET /users/colleagues (alle Rollen, RLS-gefenced) für die Auswahl;
  Vertreter-Dropdown + Anzeige in der Liste.
- Stornierung mit Re-Genehmigung: neuer Status CANCELLATION_REQUESTED,
  POST /absences/{id}/request-cancellation; Manager genehmigt/lehnt über
  bestehende approve/reject ab (Urlaub + FZA-Rückbuchung via _apply_cancellation).
- Kommentare: Model AbsenceComment (company_id-RLS), GET/POST comments,
  System-Kommentare bei Statuswechsel, AbsenceCommentsModal.
- Fix: CalDAV fire-and-forget nutzte die Request-Session weiter (in Tests
  geteilt -> "another operation in progress"); jetzt sync_*_bg mit eigener
  Session + RLS-Bypass.

Migration 0035. 178/178 Tests grün. Deployed auf 137 + 164.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-23 11:47:47 +02:00
patrickandClaude Sonnet 4.6 1bcb09a822 security: H-1 settings-Whitelist + H-5 UUID-Guard + H-6 DNS-Pinning + H-7 Heartbeat-Timing
H-1: company.settings als typisiertes Sub-Schema
- schemas/company.py: CompanySettingsUpdate mit extra=forbid
- Nur bekannte Keys (carryover_expires_month/day) erlaubt
- Unbekannte Keys → HTTP 422

H-5: SQL-Injection defensiv absichern
- dependencies.py: UUID-Round-Trip str(_uuid.UUID(...)) + Sicherheitskommentar

H-6: CalDAV DNS-Rebinding-Schutz
- caldav_service.py: PinnedIPTransport — IP einmal auflösen, beim Request fixieren
- _validate_caldav_url gibt aufgelöste IP zurück
- Alle HTTP-Methoden nutzen PinnedIPTransport

H-7: Heartbeat-Timestamp nach Route-Logik
- kiosk_security.py: last_heartbeat_at-Update aus Dependency entfernt
- kiosk_service.py: Update erst in process_heartbeat() nach erfolgreicher Auth

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-26 11:35:18 +02:00
patrickandClaude Sonnet 4.6 ed37d7dca0 security: 9 Findings aus Security-Audit behoben (CRITICAL + HIGH + MEDIUM)
CRITICAL:
- C-1: LDAP tls_verify Default False → True (MITM-Schutz)
- C-2: TOTP-Secret Fernet-verschlüsselt in DB (statt Plaintext)
  - core/crypto.py: encrypt_value() / decrypt_value() helper
  - Migration 0026: totp_secret VARCHAR(64→500), ldap tls_verify default=true
  - _totp_plain() helper mit Legacy-Fallback für bestehende Werte

HIGH:
- H-1: Kiosk Nonce-Cache asyncio.Lock (Race Condition behoben)
- H-2: File-Upload-Limit 10 MB (import_kimai.py + users.py CSV-Import)
- H-3: CORS allow_methods/allow_headers explizit eingeschränkt (war *)
- H-4: TrustedHostMiddleware aktiviert wenn ALLOWED_HOSTS gesetzt

MEDIUM:
- M-1: IP-Logging nutzt X-Forwarded-For hinter nginx-Proxy
- M-4: Audit-Log für password_changed, totp_enabled, totp_disabled
- M-5: CalDAV verify_ssl in Production erzwungen (_effective_verify_ssl)

152/152 Tests grün

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-24 19:45:09 +02:00
patrickandClaude Sonnet 4.6 73029a0912 feat: CALDAV_ALLOWED_CIDRS Whitelist für interne CalDAV/Nextcloud-Server
Interne Nextcloud-Instanzen im LAN können jetzt per .env-Variable
von der SSRF-Blockliste ausgenommen werden.

Beispiel in .env:
CALDAV_ALLOWED_CIDRS=192.168.1.0/24,10.10.5.50/32

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-24 12:53:22 +02:00
patrickandClaude Sonnet 4.6 43ae6f76a2 fix(security): SSRF-Schutz für CalDAV-URLs
Neue _validate_caldav_url() Funktion in caldav_service.py:
- Prüft Schema (nur http/https erlaubt)
- Blockiert private IP-Ranges (RFC 1918, Loopback, Link-local)
- DNS-Auflösung + Prüfung der aufgelösten IP (DNS-Rebinding-Schutz)
- Blockiert: 10/8, 172.16/12, 192.168/16, 127/8, 169.254/16, fc00::/7 etc.

Validierung in allen drei HTTP-Helpers (_http_put, _http_delete, _http_propfind)
sowie beim Speichern in caldav.py Router (company + user config) – doppelter Schutz.

Getestet: 8 böse URLs geblockt, 2 legitime URLs erlaubt (10/10 OK)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-24 12:39:59 +02:00
sysopsandClaude Sonnet 4.6 45218cc744 Initial commit – TimeMaster Zeiterfassung & HR-Tool
Stand: agent-06 (Audit-Log), agent-05 (Krankmeldung), agent-07 Phase 1 (Personalnummer),
Busylight-Pull-Integration, TOTP/2FA, Abwesenheiten, Zeiterfassung, Kiosk-Grundgerüst.
Migrations 0001–0023 deployed auf 192.168.1.137 + .164.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-23 20:03:27 +02:00