feat(verzeichnis): Entra ID als Quelle ueber Microsoft Graph (#48)
Ein Haus ohne lokales Active Directory hat kein LDAP, auf das sich zeigen liesse. Eine Verzeichnisquelle hat jetzt eine **Art** — LDAP oder GRAPH —, und beide laufen durch **denselben** Abgleich: anlegen, aktualisieren, deaktivieren, nie loeschen. Nur das Holen der Eintraege unterscheidet sich; zwei Abgleiche nebeneinander wuerden auseinanderdriften, und die Zusage „es wird nichts geloescht“ gaelte dann fuer eine Art und fuer die andere nicht mehr ganz. Gelesen wird mit dem Client-Credentials-Flow, seitenweise ueber @odata.nextLink, der Vorgesetzte ueber $expand=manager($select=id). Das Client-Secret wird verschluesselt gespeichert wie das Bind-Passwort und erreicht keine Antwort und keinen Protokolleintrag. Die Art ist **unveraenderlich**, und das steht nicht im Issue: an ihr haengt, was `externeId` bedeutet. Im AD eine objectGUID, in Entra ID eine andere GUID — nach einem Wechsel wuerde kein einziger Mitarbeiter wiedererkannt, der naechste Abgleich legte die ganze Belegschaft neu an und setzte die alten Zeilen auf aktiv = false, mit allen Laeufen und Geraeten daran. Der teuerste Fund beim Bauen: „in Entra ID deaktiviert“ als *uebersprungen* zu melden haette die Leute **aktiv** gelassen. Uebersprungen heisst im Abgleich „nicht zuordenbar“, und solche Eintraege werden seit #016 absichtlich nicht abgeschaltet. Gefiltert wird deshalb serverseitig mit `$filter=accountEnabled eq true`, als Gegenstueck zum LDAP-Standardfilter. Gefunden hat es der Test — aber nur, weil der Doppelgaenger den Filter wirklich auswertet statt ihn bloss zu empfangen. {{ou}} bleibt bei einer Graph-Quelle leer: Entra ID hat keine OU, und etwas hineinzudeuten waere ein Wert, den kein PowerShell-Befehl brauchen kann — er saehe nur richtig aus. Steht an der Abteilung eine Ziel-OU gepflegt, greift die. Gegen einen echten Entra-Mandanten ist das **nicht** gelaufen. Geprueft ist es gegen einen HTTP-Doppelgaenger mit aufgezeichneten Antworten; die Pruefliste fuer den ersten echten Lauf steht am Ende von docs/betrieb/entra-id.md. Closes #48 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
0158d0292f
commit
76a61ec771
+5
-2
@@ -526,11 +526,14 @@ describe.runIf(datenbankVerfuegbar)("Seed gegen die Datenbank", () => {
|
||||
|
||||
const quelle = await testPrisma.verzeichnisquelle.findFirstOrThrow();
|
||||
expect(quelle.aktiv).toBe(false);
|
||||
expect(quelle.url.startsWith("ldaps://")).toBe(true);
|
||||
// Seit #028 sind die LDAP-Felder nullable (nur bei `art = LDAP` belegt) — die
|
||||
// Beispielquelle ist eine LDAP-Quelle, also stehen sie.
|
||||
expect(quelle.art).toBe("LDAP");
|
||||
expect(quelle.url?.startsWith("ldaps://")).toBe(true);
|
||||
// Das Versionspraefix prueft auch die Datenbank; hier zaehlt, dass sich das
|
||||
// Feld ueberhaupt entschluesseln laesst und nichts Lesbares enthaelt.
|
||||
expect(quelle.bindPasswortVerschluesselt).toMatch(/^v[0-9]+\./u);
|
||||
expect(entschluesseln(quelle.bindPasswortVerschluesselt).length).toBeGreaterThan(16);
|
||||
expect(entschluesseln(quelle.bindPasswortVerschluesselt ?? "").length).toBeGreaterThan(16);
|
||||
});
|
||||
|
||||
it("erzeugt im Modus Dienstleistung die beiden Demo-Kunden mit MUS-PC-001", async () => {
|
||||
|
||||
Reference in New Issue
Block a user