docs: close the LDAP bind password backlog item
Notes what was deliberately left out: extracting and renaming the crypto service out of calendar/ touches five modules and belongs in its own change, so the existing provider is reused as-is and the naming smell is recorded in LdapModule instead. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,67 @@
|
||||
---
|
||||
created: 2026-08-11
|
||||
resolved: 2026-08-11
|
||||
resolution: |
|
||||
Behoben in Commit 4f687ea. Spalte heisst jetzt encryptedBindPassword,
|
||||
Verschluesselung ueber den bestehenden CalendarCryptoService, Entschluesselung
|
||||
zentral in getConfig()/getAllActiveConfigs(), Bootstrap-Backfill fuer
|
||||
Altbestand, 9 neue Tests. Punkt 1 der Loesung (Dienst aus calendar/
|
||||
herausheben und umbenennen) bewusst NICHT mitgemacht — beruehrt fuenf Module
|
||||
und gehoert in eine eigene Aenderung; im LdapModule als Notiz vermerkt.
|
||||
title: LDAP-Bind-Passwort liegt im Klartext in der DB, obwohl der Verschluesselungsdienst schon existiert
|
||||
area: ldap
|
||||
severity: major
|
||||
trigger: vor dem Verkauf an externe Kunden; unabhaengig davon jederzeit machbar, da klein und ohne Produktfragen
|
||||
files:
|
||||
- apps/api/prisma/schema.prisma:72
|
||||
- apps/api/src/ldap/ldap-config.service.ts:38
|
||||
- apps/api/src/calendar/crypto.service.ts
|
||||
---
|
||||
|
||||
## Problem
|
||||
|
||||
`LdapConfig.bindPassword` wird so gespeichert, wie es aus dem Formular kommt —
|
||||
`ldap-config.service.ts:38` und `:76` schreiben den Wert unveraendert in die
|
||||
Datenbank. Wer Lesezugriff auf die Datenbank hat, hat damit die Zugangsdaten des
|
||||
AD-Dienstkontos.
|
||||
|
||||
Hashen ist hier KEIN gangbarer Weg: Tessera muss sich mit diesem Passwort am
|
||||
Domain Controller anmelden, braucht es also im Original. Der richtige Weg ist
|
||||
symmetrische Verschluesselung mit einem Schluessel ausserhalb der Datenbank.
|
||||
|
||||
Genau das macht das Projekt an drei anderen Stellen bereits, mit AES-256-GCM:
|
||||
|
||||
| Feld | Modell |
|
||||
|---|---|
|
||||
| `encryptedPassword` | `CalendarSource` (schema.prisma:333) |
|
||||
| `encryptedInboxCreds` | `DkvModuleConfig` (:264) |
|
||||
| `encryptedInboxCreds` | `TenderEmailConfig` (:289) |
|
||||
| `encryptedPassword` | `SmtpConfig`-naher Bereich (:237) |
|
||||
|
||||
Der Dienst dafuer existiert: `calendar/crypto.service.ts`, AES-256-GCM, Schluessel
|
||||
aus der Umgebungsvariable `CALENDAR_ENCRYPTION_KEY`. Die LDAP-Konfiguration nutzt
|
||||
ihn schlicht nicht — LDAP war frueher dran als der Verschluesselungsdienst und
|
||||
wurde nie nachgezogen.
|
||||
|
||||
Was bereits richtig ist: die API gibt das Passwort nie heraus, `ldap.controller.ts`
|
||||
maskiert es an allen vier Stellen zu `********`.
|
||||
|
||||
Aufgefallen am 2026-08-11 waehrend der Phase-16-Tests, als die LDAP-Konfiguration
|
||||
fuer eine read-only-Pruefung aus der Datenbank gelesen wurde.
|
||||
|
||||
## Solution
|
||||
|
||||
1. Den bestehenden Verschluesselungsdienst aus `calendar/` heraushebeln, damit er
|
||||
nicht laenger nach einem Modul benannt ist, das ihn zufaellig zuerst brauchte —
|
||||
samt Schluesselvariable. Alternativ zunaechst unveraendert wiederverwenden und
|
||||
die Umbenennung als eigenen Schritt fuehren; das ist die kleinere Aenderung.
|
||||
2. `LdapConfigService.create/update` verschluesselt schreiben, alle Lesestellen
|
||||
entschluesseln. Lesestellen sind `ldap.controller.ts` (Zeilen 136, 177, 210,
|
||||
244, 277, 313) und der Sync selbst.
|
||||
3. Migration, die den vorhandenen Klartext-Eintrag einmalig verschluesselt.
|
||||
Muster vorhanden — dieselbe Form wie die bestehenden Backfill-Migrationen.
|
||||
4. Feld umbenennen (`bindPassword` → `encryptedBindPassword`), damit am Schema
|
||||
ablesbar ist, was drinsteht, wie bei den anderen vier Feldern.
|
||||
|
||||
Keine offenen Produktfragen — reine Umsetzung, entlang eines im Projekt bereits
|
||||
etablierten Musters.
|
||||
Reference in New Issue
Block a user