From dbc309dfd6fa5924e819b2b126190bfe55c9e405 Mon Sep 17 00:00:00 2001 From: Thore Cimbal Date: Tue, 11 Aug 2026 12:00:00 +0000 Subject: [PATCH] docs(adr): 0011 - reject localpart collisions in provisioning Records on_conflict: fail as standing policy (identity provisioning never links a new upstream identity to an existing local account), the residual prompt-stage uniqueness check, and the SOPS-secret-needs-restart rule. Decided by sorb. --- ...rollment-localpart-kollision-verweigern.md | 59 +++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 decisions/0011-enrollment-localpart-kollision-verweigern.md diff --git a/decisions/0011-enrollment-localpart-kollision-verweigern.md b/decisions/0011-enrollment-localpart-kollision-verweigern.md new file mode 100644 index 0000000..82e6076 --- /dev/null +++ b/decisions/0011-enrollment-localpart-kollision-verweigern.md @@ -0,0 +1,59 @@ +# 0011 — Provisionierung verweigert Localpart-Kollisionen, statt an bestehende Konten zu verknüpfen + +**Status:** akzeptiert · **Datum:** 2026-08-11 · **Entscheider:** sorb + +## Kontext + +Der MAS-Upstream-Provider für Authentik stand auf +`claims_imports.localpart.on_conflict: add`. MAS-Semantik: Kollidiert der aus dem +Authentik-Claim abgeleitete Localpart mit einem **bestehenden** Matrix-Konto, +verknüpft MAS die neue Upstream-Identität mit diesem Konto — ohne Abbruch, ohne +Warnung. Authentiks eigene Benutzernamen-Eindeutigkeit fängt das nicht ab: sie +gilt nur innerhalb von Authentik und ist case-sensitive (`boje` neben `Boje` ging +live durch). Folge: Ein Inhaber eines Einladungstokens konnte einen (auch nur in +der Schreibweise abweichenden) Namen eines bestehenden Kontos registrieren und +würde beim ersten Login in dessen Konto verknüpft — inklusive Dienstkonten ohne +Upstream-Link (`draupnir`, `alerts`, `maintenance-notify`). Das ist ein +Kontoübernahme-Vektor, entdeckt am 2026-08-11 beim Anlegen eines Testkontos +([gitops#61](https://git.lab/axion1337.chat/axion1337.chat-gitops/-/issues/61)). + +## Entscheidung + +**Identitäts-Provisionierung verknüpft eine neue Upstream-Identität niemals mit +einem bereits bestehenden lokalen Konto.** Konkret: `on_conflict: fail` im +`claims_imports.localpart`-Block des MAS-Upstream-Providers +(`gitops/apps/production/custom-configs/mas-secret.yaml`). Ein kollidierender +Localpart bricht die Provisionierung ab. Dies ist ab jetzt stehende Regel, nicht +nur der aktuelle Wert — jede künftige Änderung an diesem Verhalten braucht ein +ablösendes ADR. + +## Konsequenzen + +- **Besser:** Der Übernahme-Weg ist geschlossen. Bestehende Konten (besonders die + ohne Upstream-Link) können nicht mehr durch eine kollidierende Neuregistrierung + gekapert werden. Bestehende, korrekte Verknüpfungen bleiben unberührt. +- **In Kauf genommen:** Ein Nutzer, der einen bereits vergebenen Namen wählt, + erhält die Fehlermeldung erst **beim Login** (wenn MAS provisioniert), nicht + schon bei der Registrierung in Authentik. Das ist eine schlechtere UX, aber kein + Sicherheitsproblem. +- **Jetzt Pflicht:** + - Als offene Härtung eine **case-insensitive Eindeutigkeitsprüfung im + `matrix-invitation`-Prompt-Stage**, damit die Kollision schon bei der + Registrierung sichtbar wird (verfolgt in gitops#61). + - **Nach jeder Änderung an einem SOPS-verwalteten Values-Secret den + konsumierenden Dienst per `rollout restart` neu ausrollen und verifizieren**, + dass der Pod jünger als die Änderung ist. Beim Ausrollen dieses Fixes lief + MAS noch mit der alten Config im Speicher, obwohl das Secret bereits `fail` + zeigte — „committet" ≠ „deployed" ≠ „aktiv" (MAS liest Config nur beim Start). + +## Verworfene Alternativen + +- **`on_conflict: add` belassen und allein auf Authentiks Eindeutigkeit + vertrauen** — verworfen: die greift nur innerhalb Authentiks und + case-sensitive, deckt Kollisionen mit vorbestehenden Matrix-Konten also nicht ab. +- **Nur den Prompt-Stage-Check bauen, MAS auf `add` lassen** — verworfen: der + Client-seitige Check ist umgehbar (direkter Flow-Aufruf), der MAS-seitige + Abbruch ist die eigentliche Sicherheitsgrenze. Der Prompt-Check ist die + UX-Ergänzung, nicht der Schutz. +- **Betroffene Dienstkonten einfach mit Upstream-Links versehen** — verworfen: + behandelt nur das Symptom für heute bekannte Konten, nicht den Mechanismus.