fix(authentik): resolve recovery flow via Find instead of KeyOf

Adding name and title was necessary but not sufficient - the blueprint kept failing. Running ak apply_blueprint by hand showed why the real error was never visible: when authentik logs a failed entry it calls str() on the KeyOf object, whose __repr__ resolves against an EMPTY blueprint and raises the very same exception. The logging path masks the actual validation error.

KeyOf also couples every stage binding to that one entry succeeding in the same run. Find resolves against the database instead, which is what the neighbouring blueprints in this same ConfigMap already do, and the flow exists.

Refs axion1337.chat/axion1337.chat-gitops#60
This commit is contained in:
Thore Cimbal
2026-08-07 12:00:00 +00:00
parent 1b35766ad3
commit 3c6f3645b3
+19 -9
View File
@@ -114,7 +114,18 @@ data:
# stages the built-in default-recovery-flow already uses successfully, # stages the built-in default-recovery-flow already uses successfully,
# plus our own redirect stage instead of falling back to the authentik # plus our own redirect stage instead of falling back to the authentik
# dashboard (blocked for type=external Matrix users). # dashboard (blocked for type=external Matrix users).
# ⚠️ name und title MUESSEN hier stehen. Der FlowSerializer verlangt beide # ⚠️ Hier steckten ZWEI Fehler uebereinander (gitops#60).
#
# 1. !KeyOf koppelt jede Bindung daran, dass DIESER Eintrag im selben Lauf
# eine Model-Instanz erzeugt. Scheitert er, faellt der ganze Blueprint.
# Schlimmer: beim Protokollieren des Fehlers ruft Authentik str() auf das
# !KeyOf-Objekt, dessen __repr__ gegen ein LEERES Blueprint aufloest und
# dabei dieselbe Ausnahme wirft - die echte Fehlermeldung wird dadurch
# ueberdeckt. Man sieht nur noch "KeyOf: failed to find entry".
# Deshalb jetzt !Find gegen die Datenbank, wie in den Blueprints darunter
# ohnehin ueblich. Der Flow existiert, das ist stabiler und entkoppelt.
#
# 2. name und title MUESSEN gesetzt sein. Der FlowSerializer verlangt beide
# (keine Model-Defaults). Fehlen sie, scheitert die Validierung, der Eintrag # (keine Model-Defaults). Fehlen sie, scheitert die Validierung, der Eintrag
# bekommt keine Model-Instanz - und JEDES nachfolgende `!KeyOf # bekommt keine Model-Instanz - und JEDES nachfolgende `!KeyOf
# matrix_recovery_flow` laeuft ins Leere. Genau das war der Zustand bis # matrix_recovery_flow` laeuft ins Leere. Genau das war der Zustand bis
@@ -129,7 +140,6 @@ data:
state: present state: present
identifiers: identifiers:
slug: matrix-recovery slug: matrix-recovery
id: matrix_recovery_flow
attrs: attrs:
name: "Welcome to aXion1337! Please provide a username or mail-adress." name: "Welcome to aXion1337! Please provide a username or mail-adress."
title: "Welcome to aXion1337! Please provide a username or mail-adress." title: "Welcome to aXion1337! Please provide a username or mail-adress."
@@ -138,7 +148,7 @@ data:
- model: authentik_flows.flowstagebinding - model: authentik_flows.flowstagebinding
state: present state: present
identifiers: identifiers:
target: !KeyOf matrix_recovery_flow target: !Find [authentik_flows.flow, [slug, matrix-recovery]]
order: 10 order: 10
attrs: attrs:
stage: !Find [authentik_stages_identification.identificationstage, [name, default-recovery-identification]] stage: !Find [authentik_stages_identification.identificationstage, [name, default-recovery-identification]]
@@ -146,7 +156,7 @@ data:
- model: authentik_flows.flowstagebinding - model: authentik_flows.flowstagebinding
state: present state: present
identifiers: identifiers:
target: !KeyOf matrix_recovery_flow target: !Find [authentik_flows.flow, [slug, matrix-recovery]]
order: 20 order: 20
attrs: attrs:
stage: !Find [authentik_stages_email.emailstage, [name, default-recovery-email]] stage: !Find [authentik_stages_email.emailstage, [name, default-recovery-email]]
@@ -154,7 +164,7 @@ data:
- model: authentik_flows.flowstagebinding - model: authentik_flows.flowstagebinding
state: present state: present
identifiers: identifiers:
target: !KeyOf matrix_recovery_flow target: !Find [authentik_flows.flow, [slug, matrix-recovery]]
order: 30 order: 30
attrs: attrs:
stage: !Find [authentik_stages_prompt.promptstage, [name, "Change your password"]] stage: !Find [authentik_stages_prompt.promptstage, [name, "Change your password"]]
@@ -162,7 +172,7 @@ data:
- model: authentik_flows.flowstagebinding - model: authentik_flows.flowstagebinding
state: present state: present
identifiers: identifiers:
target: !KeyOf matrix_recovery_flow target: !Find [authentik_flows.flow, [slug, matrix-recovery]]
order: 40 order: 40
attrs: attrs:
stage: !Find [authentik_stages_user_write.userwritestage, [name, default-recovery-user-write]] stage: !Find [authentik_stages_user_write.userwritestage, [name, default-recovery-user-write]]
@@ -170,7 +180,7 @@ data:
- model: authentik_flows.flowstagebinding - model: authentik_flows.flowstagebinding
state: present state: present
identifiers: identifiers:
target: !KeyOf matrix_recovery_flow target: !Find [authentik_flows.flow, [slug, matrix-recovery]]
order: 100 order: 100
attrs: attrs:
stage: !Find [authentik_stages_user_login.userloginstage, [name, default-recovery-user-login]] stage: !Find [authentik_stages_user_login.userloginstage, [name, default-recovery-user-login]]
@@ -178,7 +188,7 @@ data:
- model: authentik_flows.flowstagebinding - model: authentik_flows.flowstagebinding
state: present state: present
identifiers: identifiers:
target: !KeyOf matrix_recovery_flow target: !Find [authentik_flows.flow, [slug, matrix-recovery]]
order: 110 order: 110
attrs: attrs:
stage: !Find [authentik_stages_redirect.redirectstage, [name, matrix-invitation-redirect]] stage: !Find [authentik_stages_redirect.redirectstage, [name, matrix-invitation-redirect]]
@@ -189,7 +199,7 @@ data:
identifiers: identifiers:
name: default-authentication-identification name: default-authentication-identification
attrs: attrs:
recovery_flow: !KeyOf matrix_recovery_flow recovery_flow: !Find [authentik_flows.flow, [slug, matrix-recovery]]
matrix-mfa-setup-redirect.yaml: | matrix-mfa-setup-redirect.yaml: |
# yaml-language-server: $schema=https://goauthentik.io/blueprints/schema.json # yaml-language-server: $schema=https://goauthentik.io/blueprints/schema.json
version: 1 version: 1