From e7f1b5d6f8e85699816eed6be8349e40bcbd35c5 Mon Sep 17 00:00:00 2001 From: Thore Cimbal Date: Thu, 6 Aug 2026 12:00:00 +0000 Subject: [PATCH] Authentik: MFA-Pflicht fuer Admins (gitops#57) Eigene Validate-Stage hinter der vorhandenen, gebunden an die Admin-Gruppe. Fasst KEIN Authentik-Standardobjekt an: not_configured_action haengt an der Stage statt an der Bindung, eine Umstellung am Standard haette alle Mitglieder getroffen. not_configured_action=configure statt deny - wer keinen Faktor hat, wird beim Login durch die Einrichtung gefuehrt statt ausgesperrt. Bei einem Admin-Konto gaebe es nach einem deny keinen Weg zurueck ausser ueber den Cluster. last_auth_threshold=hours=1 verhindert die doppelte Abfrage: die Standard-Stage auf Ordnung 30 validiert bereits, wer einen Faktor hat; diese hier ueberspringt sich dann. BEWUSST auf einem Branch: die Gruppe ist mit dem Authentik-Standard "authentik Admins" angenommen und von sorb noch nicht bestaetigt. Trifft sie nicht zu, greift die Regel fuer niemanden - das waere schlimmer als keine Regel, weil es sich sicher anfuehlt. --- apps/authentik/authentik-blueprints.yaml | 57 ++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/apps/authentik/authentik-blueprints.yaml b/apps/authentik/authentik-blueprints.yaml index 059d4af..fc5dce3 100644 --- a/apps/authentik/authentik-blueprints.yaml +++ b/apps/authentik/authentik-blueprints.yaml @@ -206,6 +206,63 @@ data: order: 10 attrs: stage: !Find [authentik_stages_redirect.redirectstage, [name, matrix-invitation-redirect]] + admin-mfa-enforcement.yaml: | + # yaml-language-server: $schema=https://goauthentik.io/blueprints/schema.json + version: 1 + metadata: + name: admin-mfa-enforcement + labels: + blueprints.goauthentik.io/instantiate: "true" + entries: + # MFA-Pflicht fuer Admins, ohne sie fuer alle anderen zu erzwingen. + # + # Warum eine ZWEITE Validate-Stage statt not_configured_action am + # bestehenden default-authentication-mfa-validation umzustellen: dieses Feld + # haengt an der Stage, nicht an der Bindung - eine Umstellung wuerde alle + # Mitglieder treffen. Und die Standard-Stage anzufassen hiesse, ein Objekt + # aus Authentiks eigenem Blueprint zu veraendern. + # + # Diese Loesung fasst KEIN Authentik-Standardobjekt an. Sie haengt eine + # eigene Stage hinter die vorhandene und bindet sie an die Admin-Gruppe. + - model: authentik_stages_authenticator_validate.authenticatorvalidatestage + state: present + identifiers: + name: admin-mfa-validation + id: admin_mfa_stage + attrs: + # configure statt deny: Wer keinen Faktor hat, wird beim Login durch die + # Einrichtung GEFUEHRT. deny wuerde ihn aussperren - und bei einem + # Admin-Konto gibt es dann keinen Weg zurueck ausser ueber den Cluster. + not_configured_action: configure + configuration_stages: + - !Find [authentik_stages_authenticator_totp.authenticatortotpstage, [name, default-authenticator-totp-setup]] + - !Find [authentik_stages_authenticator_webauthn.authenticatorwebauthnstage, [name, default-authenticator-webauthn-setup]] + # Verhindert die doppelte Abfrage: Die Standard-Stage auf Ordnung 30 + # validiert bereits, wer einen Faktor hat. Diese hier laeuft danach und + # ueberspringt sich, wenn das Geraet gerade eben benutzt wurde. Uebrig + # bleibt genau der Fall, um den es geht - Admin ohne zweiten Faktor. + last_auth_threshold: hours=1 + + # Ordnung 31: direkt hinter der Standard-MFA-Stage (30), vor dem Login (100). + - model: authentik_flows.flowstagebinding + state: present + identifiers: + target: !Find [authentik_flows.flow, [slug, default-authentication-flow]] + order: 31 + id: admin_mfa_binding + attrs: + stage: !KeyOf admin_mfa_stage + + # Eine PolicyBinding mit gesetztem "group" prueft Gruppenmitgliedschaft + # (PolicyResult(group.is_member(user))). Ohne diese Bindung wuerde die + # Stage fuer ALLE gelten - dann waere 2FA fuer die ganze Instanz Pflicht. + - model: authentik_policies.policybinding + state: present + identifiers: + target: !KeyOf admin_mfa_binding + order: 0 + attrs: + group: !Find [authentik_core.group, [name, "authentik Admins"]] matrix-brand-default-app.yaml: | # yaml-language-server: $schema=https://goauthentik.io/blueprints/schema.json version: 1