Phase 2 stand bisher nur als acht Stichpunkte im Epic. Jetzt je Meilenstein eine Datei mit Ziel, Aufgaben und Akzeptanzkriterien, dazu im Tracker gespiegelt: #48 bis #55, zusammen 76 h geschaetzt. Die Reihenfolge ist nicht beliebig. M15 fuehrt die Quellenart ein, die M16 braucht; M17 legt die Zusammensetzung fest, auf der M18 aufsitzt. Die anderen vier haengen an nichts und koennen jederzeit dazwischen. Drei Entscheidungen fallen vor dem Code und stehen je Meilenstein als erste Aufgabe mit Empfehlung: - Wie ein Baustein die Unveraenderlichkeit einer veroeffentlichten Version ueberlebt (Verweis im Entwurf, tiefe Kopie beim Veroeffentlichen). Ein Lauf sieht weiterhin konkrete Schritte und muss nichts lernen. - Wo Anhaenge liegen (Dateisystem, Metadaten in der Datenbank) -- mit der Folge, dass Compose-Stand, native Installation und sicherung.md ein Volume brauchen. Eine Sicherung, die nur die Datenbank mitnimmt, verliert ab dort Daten. - Was eine Selbstauskunft zeigt: Titel, Status, Zeitraum, Geraet, aber keine Schritte, Notizen, Kommentare oder Anhaenge. In einem Lauf stehen Arbeitsnotizen ueber Menschen; eine Selbstauskunft ist keine Akteneinsicht. Refs #2
56 lines
3.3 KiB
Markdown
56 lines
3.3 KiB
Markdown
# #028 M15 – Quellenarten und Microsoft-Graph-Quelle
|
||
|
||
**Status:** offen
|
||
**Im Tracker:** [#48](https://git.wilde-server.de/florian.wilde/Laufzettel/issues/48)
|
||
**Meilenstein:** v0.2.0
|
||
**Labels:** phase-2, backend, frontend
|
||
**Geschätzt:** 10 h **Tatsächlich:** –
|
||
|
||
## Ziel
|
||
|
||
Ein Haus ohne lokales AD hat kein LDAP, auf das sich zeigen ließe. Für reine Entra-ID-Umgebungen
|
||
braucht es eine zweite Art von Verzeichnisquelle, die über Microsoft Graph liest — mit denselben
|
||
Regeln wie der LDAP-Abgleich: anlegen, aktualisieren, deaktivieren, **nie löschen**.
|
||
|
||
Dieser Meilenstein legt dazu die Weiche, die auch [#029](029-scim-endpunkt.md) braucht:
|
||
`Verzeichnisquelle` bekommt eine **Art**. Heute ist jede Quelle implizit LDAP.
|
||
|
||
## Zu entscheiden
|
||
|
||
- [ ] **Ein Enum `QuellenArt {LDAP GRAPH SCIM}` auf `Verzeichnisquelle`** — Empfehlung. Die Felder
|
||
`url`, `bindDn` und `basisDn` sind dann je Art unterschiedlich belegt; was eine Art braucht,
|
||
prüft der Service, nicht die Datenbank. Die Alternative wäre eine Tabelle je Art mit
|
||
gemeinsamer Oberklasse — mehr Struktur, als drei Arten rechtfertigen.
|
||
- [ ] **Wie `{{ou}}` in Entra ID aussieht.** Es gibt keinen DN und keine OU. Ehrlich ist, den
|
||
Platzhalter bei einer Graph-Quelle **leer** zu lassen, statt etwas hineinzudeuten — und das
|
||
in der Anleitung zu sagen. Wer OU-abhängige Befehle fährt, braucht ein lokales AD.
|
||
|
||
## Aufgaben
|
||
|
||
- [ ] `QuellenArt` als Enum, Migration mit `LDAP` für alle bestehenden Zeilen
|
||
- [ ] Graph-Zugang: `tenantId`, `clientId`, `clientSecret` (verschlüsselt wie das Bind-Passwort, nie
|
||
in einer Antwort), Token über Client-Credentials-Flow, Zwischenspeicher bis kurz vor Ablauf
|
||
- [ ] Lesen über `GET /v1.0/users` mit `$select`, Seitenabruf über `@odata.nextLink`; der
|
||
Vorgesetzte über `$expand=manager($select=id)`
|
||
- [ ] Attributzuordnung mit Graph-Vorgaben (`givenName`, `surname`, `displayName`, `mail`,
|
||
`userPrincipalName`, `onPremisesSamAccountName`, `department`, `jobTitle`, `accountEnabled`)
|
||
- [ ] `externeId` ist die Entra-`id` (GUID). Sie ist stabil und übersteht eine Umbenennung
|
||
- [ ] „Verbindung testen“ wie bei LDAP: die ersten zehn zugeordneten Treffer zeigen
|
||
- [ ] Der Abgleich läuft durch **denselben** Dienst wie LDAP — nur das Holen der Einträge
|
||
unterscheidet sich. Sonst driften die Regeln auseinander
|
||
- [ ] Admin → Verzeichnis zeigt die Art je Quelle und bietet beim Anlegen die Wahl
|
||
- [ ] Anleitung Kapitel 06 und `docs/betrieb/`: was in Entra ID einzurichten ist
|
||
(App-Registrierung, `User.Read.All`, `Directory.Read.All`, Administratoreinwilligung)
|
||
|
||
## Akzeptanzkriterien
|
||
|
||
- [ ] Test gegen einen **abspielenden HTTP-Doppelgänger** mit aufgezeichneten Graph-Antworten: erster
|
||
Abgleich legt an, zweiter aktualisiert ohne Dubletten, ein `accountEnabled: false` setzt
|
||
`aktiv = false`
|
||
- [ ] Test: der Seitenabruf folgt `@odata.nextLink` über mindestens drei Seiten
|
||
- [ ] Test: `clientSecret` erscheint in keiner Antwort und in keinem Protokolleintrag
|
||
- [ ] Test: eine Graph-Quelle lässt `{{ou}}` leer, statt einen Wert zu erfinden
|
||
- [ ] Der LDAP-Weg verhält sich unverändert — alle Tests aus #016 bleiben grün
|
||
- [ ] **Offen und benannt:** gegen einen echten Entra-Mandanten ist das nicht gelaufen; die
|
||
Gegenprobe gehört in eine Prüfliste wie bei [#024](024-proxmox-echtlauf.md)
|