feat(authentik): blueprints-as-code baseline + drafted MFA (phase 1, not applied)#2014
Merged
Conversation
…not applied) PLAN-011 Phase 1 (agent-safe, read-only against live). Reproduces the live Authentik estate (2026.5.3) as declarative blueprints so brand/flows/source become config-as-code, and drafts native-account MFA without applying anything. Delivery: app/kustomization.yaml bundles the baseline blueprints into ConfigMap authentik-hnet-blueprints (stable name); helmrelease.yaml lists it under values.blueprints.configMaps, so the chart mounts it onto the worker at /blueprints/mounted/cm-authentik-hnet-blueprints (verified via helm template). Baseline (discovered, drift-zero — only delta vs the branding apply-seed was a single trailing newline the server strips): - 10-hnet-brand.yaml default brand: title, media paths, full ~70KB brand CSS - 20-hnet-flows.yaml 4 login flows + stages + bindings + flow policies - 30-hnet-sources.yaml Plex OAuth source (plex_token omitted; stays in Authentik/1P) Drafted, NOT discovered (excluded from configMapGenerator): - pending/40-hnet-mfa.yaml WebAuthn+TOTP validation/enroll after the password stage; mfa-exempt group (hnet-e2e, hnet-e2e-member) + fail-closed skip policy. Q-02 (verified structurally against the exported flow graph): Plex-source logins are OUTSIDE the password+MFA path — existing users authenticate via default-source-authentication (a login-only flow, no password/MFA stage); the MFA stage lives only at order 30 of default-authentication-flow, which source logins never enter. exports/ holds the sanitized read-only API snapshot (secrets -> 1P refs) the blueprints were authored from. Nothing here is applied — Flux only reconciles main. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PU9cU9mSv19WMB64bMGP71
Contributor
Flux
|
Contributor
Flux
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What this is
Turns the haynesnetwork Authentik customizations into config-as-code and drafts
native-account MFA on top, per PLAN-011.
so applying them changes nothing observable:
app/blueprints/10-hnet-brand.yamlapp/blueprints/20-hnet-flows.yamlapp/blueprints/30-hnet-sources.yamlplex_tokenomitted)app/blueprints/pending/40-hnet-mfa.yaml— WebAuthn +TOTP validation/enrollment after the password stage, an
mfa-exemptgroup(
hnet-e2e,hnet-e2e-member) and a fail-closed skip policy.exports/— the sanitized read-only API snapshot (secrets →1P://…refs) theblueprints were authored from.
Delivery (supported chart mechanism)
app/kustomization.yamlgenerates ConfigMapauthentik-hnet-blueprints(
disableNameSuffixHash: true) from the three baseline files;app/helmrelease.yamladds
values.blueprints.configMaps: [authentik-hnet-blueprints]. The goauthentik chartmounts it onto the worker at
/blueprints/mounted/cm-authentik-hnet-blueprints, whereonly
*.yamlkeys are discovered. Thepending/MFA file is deliberately not in thegenerator, so it is never mounted. Verified offline:
kubectl kustomize app/→ ConfigMap with keys10/20/30-hnet-*.yaml(no MFA), stable name.helm template(chart 2026.5.3,blueprints.configMapsset) → worker getsvolume/volumeMount blueprints-cm-authentik-hnet-blueprints → /blueprints/mounted/cm-authentik-hnet-blueprints.Exported inventory (names + pks)
Brand (1): default
authentik-defaultuuidde1b7109-2d4d-466c-8890-326e969015d5, titlehaynesnetwork.Flows (branded, 4 of 14):
default-authentication-flowc8e7b494-…bac40default-source-authentication67b51e33-…4dc5bc→flow67b51e33-…a6d9default-source-enrollmentf80cd9b5-…1198ddefault-invalidation-flow8ba7e7a7-…602c62Key stages: identification
default-authentication-identification08af63fb-…2772f;password
default-authentication-passwordabf918bc-…e40fde; authenticator-validatedefault-authentication-mfa-validation3cdaa8fa-…a1c88; logindefault-authentication-loginae85d3ba-…fb69c; source logindefault-source-authentication-logind81d77d2-…dc5bc.Flow policies:
default-authentication-flow-password-stagec2c42fe2-…f5f0(skippassword if a backend is already attached),
default-authentication-flow-authenticator-validate-stage38f627a5-…cffe6(skip MFA if webauthn-passwordless),default-source-authentication-if-sso5d457f9a-…1ab5e(return ak_is_sso_flow).Groups (3):
authentik Admins3a1337de-…e084(superuser; akadmin+thaynes),authentik Read-only0a15001d-…3180,grafana_adminffd4d3b4-…1a63. Nomfa-exemptyet (this PR drafts it).Source (1): Plex
HaynesTowerslughaynestower2c61a5af-…c22891—promoted: true,authentication_flow: 67b51e33(default-source-authentication),enrollment_flow: f80cd9b5(default-source-enrollment),
user_matching_mode: identifier.Provider/application (deferred — Q-11):
Provider for haynesnetworkpk109(confidential,
grant_types [authorization_code, refresh_token],include_claims_in_id_token),application slug
haynesnetworkb427e696-…b7355. Exported+sanitized underexports/, not blueprinted.Q-02 — are Plex-source logins structurally outside the password + MFA path?
Yes. Verified against the exported flow graph:
default-authentication-flow(the native path) stage-binding order: 10 identification →20 password (gated by
…password-stagepolicy) → 30 authenticator-validation(
default-authentication-mfa-validation, gated by…authenticator-validate-stagepolicy) →100 login. This is the ONLY flow containing an authenticator-validation stage.
authentication_flow = default-source-authenticationand new users to
enrollment_flow = default-source-enrollment.default-source-authenticationhas exactly one stage-binding — order 0default-source-authentication-login(user-login). No password stage, noauthenticator-validation stage. (
default-source-enrollment= prompt → user-write(
user_type: external) → login; also no password/MFA.)default-authentication-flowand neverreaches the order-30 MFA stage. The drafted MFA blueprint modifies only
default-authentication-flow's order-30 stage + binding — nothing in the source flows.Caveat for Phase 2: MFA gates the username+password path. A native account that signs
in via the Plex button also bypasses MFA (that is the source path) — consistent with owner
requirement #2 ("Log in with Plex accounts pass through untouched").
Drift vs the branding apply-seed
Essentially none. All brand media fields (
hnet/logo-%(theme)s.svg,hnet/favicon.png,hnet/bg-c-%(theme)s.svg), the title, and all three flow titles matchdocs/ops/authentik-apply-seedexactly. The only difference is a single trailingnewline in the brand custom CSS (Authentik strips it on save); the committed blueprint uses
the live value, so a merge is truly drift-zero.
Phase 2 — apply / rollback (owner-present)
Full runbooks:
app/blueprints/README.mdandapp/blueprints/pending/README.md.Content rollback to stock Authentik remains the API payloads in
haynesnetwork:docs/ops/authentik-apply-seed/.Carried open questions
brand/flows/source-only? (Provider secrets stay in 1P either way.)
AUTHENTIK_BOOTSTRAP_PASSWORD; rotate viaakshell in Phase 2 (keep as break-glass with MFA, or disable interactive login).