diff --git a/ansible/roles/noble_authentik/README.md b/ansible/roles/noble_authentik/README.md index b98f13b..1341600 100644 --- a/ansible/roles/noble_authentik/README.md +++ b/ansible/roles/noble_authentik/README.md @@ -42,7 +42,7 @@ Network isolation is enforced at **DNS and the tunnel**, not inside Authentik. O **Two-Brand model:** - **Lab Brand** — domain equals **`noble_authentik_host`**: restricted authentication flow (**`noble_authentik_blueprint_lab_flow_slug`**) so only operator groups (defaults: **`noble-admins`**, **`authentik Admins`**) can continue past identification; dedicated password stage with **`noble_authentik_blueprint_lab_password_failed_attempts`**, expression-based password strength (**length / character classes / optional zxcvbn**), and MFA stage **`noble-lab-authenticator-validate-strict`** with **`noble_authentik_blueprint_lab_mfa_not_configured_action`** (**`configure`** injects default TOTP setup when no device; **`deny`** blocks; **`skip`** matches stock). WebAuthn passwordless does **not** skip MFA on this flow. Your bootstrap / break-glass account must remain in one of those groups (see **`noble_authentik_ensure_admin_ui_access`** and **`configure_authentik.py`** group membership). -- **Public Brand(s)** — one Brand per FQDN in **`noble_authentik_ingress_extra_hosts`**: authentication flow **`noble_authentik_blueprint_public_auth_flow_slug`** (default **`noble-public-authentication-flow`**) mirrors stock **`default-authentication-flow`** (optional password / MFA skip for WebAuthn passwordless) so you can tune lab vs public independently. Assign people to **`noble_authentik_blueprint_public_groups`** and/or **`noble_authentik_blueprint_nikflix_groups`** (defaults include **`nikflix-users`** / **`nikflix-admins`** for the Nikflix hostname); **`noble-admins`** / **`noble-editors`** remain for cluster / Argo / Grafana as today. +- **Nikflix Brand(s)** — one Brand per FQDN in **`noble_authentik_ingress_extra_hosts`**: authentication flow **`noble_authentik_blueprint_public_auth_flow_slug`** (default **`noble-public-authentication-flow`**) mirrors stock **`default-authentication-flow`** (optional password / MFA skip for WebAuthn passwordless). Directory groups default to **`nikflix-users`** / **`nikflix-admins`** only; add optional groups via **`noble_authentik_blueprint_extra_directory_groups`** or the optional **`noble_authentik_blueprint_public_groups`** list. **`noble-admins`** / **`noble-editors`** remain for cluster / Argo / Grafana as today. **OAuth note:** Redirect URIs and **`iss`** must stay consistent with the hostname clients use (internal issuer for in-cluster apps vs public issuer is a deliberate choice — avoid mixing both for the same app). @@ -50,15 +50,15 @@ Network isolation is enforced at **DNS and the tunnel**, not inside Authentik. O | Key | Purpose | | --- | --- | -| **`10-noble-public-groups.yaml.j2`** | **`noble_authentik_blueprint_public_groups`** ∪ **`noble_authentik_blueprint_extra_directory_groups`** ∪ **`noble_authentik_blueprint_nikflix_groups`** → **Group** objects (see **Blueprint: directory groups**). | +| **`10-noble-public-groups.yaml.j2`** | **`noble_authentik_blueprint_public_groups`** (optional, default empty) ∪ **`noble_authentik_blueprint_extra_directory_groups`** ∪ **`noble_authentik_blueprint_nikflix_groups`** → **Group** objects (defaults: **Nikflix** only — see **Blueprint: directory groups**). | | **`20-noble-lab-operator-authentication-flow.yaml.j2`** | Flow **`noble_authentik_blueprint_lab_flow_slug`**: operator policy **`noble_authentik_blueprint_operator_policy_name`**, lab password/MFA tunables (see **`defaults/main.yml`**). | | **`21-noble-public-authentication-flow.yaml.j2`** | Flow **`noble_authentik_blueprint_public_auth_flow_slug`** — public sign-in (same optional policies as stock default authentication). | -| **`22-noble-invitation-enrollment-flows.yaml.j2`** | Two **enrollment** flows + **Invitation** stages: public (**`noble_authentik_blueprint_public_invitation_enrollment_flow_slug`**) vs lab (**`noble_authentik_blueprint_lab_invitation_enrollment_flow_slug`**); see **Invitations** below. | +| **`22-noble-invitation-enrollment-flows.yaml.j2`** | Two **enrollment** flows + **Invitation** stages: Nikflix / extra_hosts (**`noble_authentik_blueprint_public_invitation_enrollment_flow_slug`**) vs lab (**`noble_authentik_blueprint_lab_invitation_enrollment_flow_slug`**); see **Invitations** below. | | **`30-noble-brands-domain-split.yaml.j2`** | Brand for **`noble_authentik_host`** → lab flow; one Brand per **`noble_authentik_ingress_extra_hosts`** → public flow slug above. | Tune titles via **`noble_authentik_blueprint_lab_brand_title`** and **`noble_authentik_blueprint_public_brand_title_prefix`**. After the worker applies blueprints, confirm **System → Brands** and **Flows** in the admin UI; fix any **`!Find`** failures if upstream default stage **names** change between Authentik versions. -#### Invitations (public vs lab) +#### Invitations (Nikflix vs lab) [Brands](https://docs.goauthentik.io/brands/) do **not** expose a default “enrollment” or “invitation” flow: onboarding is driven by **Directory → Invitations**, where each invitation row selects an **enrollment** flow. The link Authentik shows is: @@ -66,7 +66,7 @@ Tune titles via **`noble_authentik_blueprint_lab_brand_title`** and **`noble_aut Use **``** that matches the experience you want: -- **Public / Nikflix** — an FQDN from **`noble_authentik_ingress_extra_hosts`**: use flow slug **`noble_authentik_blueprint_public_invitation_enrollment_flow_slug`** (default **`noble-public-invitation-enrollment`**). New users are added to **`noble_authentik_blueprint_public_invitation_user_group`** (default **`noble-public-users`**; override to **`nikflix-users`** if that is your only audience group). **`noble_authentik_blueprint_public_invitation_user_type`** defaults to **`internal`** so invitees behave like normal users; set **`external`** only if you need that isolation (see [Invitations — “Permission denied” for external users](https://docs.goauthentik.io/users-sources/user/invitations/)). Tune **`noble_authentik_blueprint_public_invitation_user_path`** as needed. +- **Nikflix / internet hostname** — an FQDN from **`noble_authentik_ingress_extra_hosts`**: use flow slug **`noble_authentik_blueprint_public_invitation_enrollment_flow_slug`** (default **`nikflix-invitation-enrollment`**). New users are added to **`noble_authentik_blueprint_public_invitation_user_group`** (default **`nikflix-users`**). **`noble_authentik_blueprint_public_invitation_user_type`** defaults to **`internal`**. If you previously used **`noble-public-invitation-enrollment`** or **`noble-public-users`**, update **Directory → Invitations** to the new flow slug and re-run **`--tags authentik`**; remove obsolete **`noble-public-*`** groups in the admin UI if they are empty (Ansible no longer defines them). - **Lab** — **`noble_authentik_host`** only when you intend to onboard someone who will later get **`noble_authentik_blueprint_lab_operator_groups`** access: use **`noble_authentik_blueprint_lab_invitation_enrollment_flow_slug`** (default **`noble-lab-invitation-enrollment`**). The blueprint creates **`noble_authentik_blueprint_lab_invitee_group_name`** (default **`noble-lab-invited`**) and assigns new enrollments there; **promote** people to **`noble-admins`** / **`authentik Admins`** (or your configured operator groups) in the admin UI when they should sign in on the lab URL. Blueprint **22** does **not** create sample **Invitation** rows (no placeholder emails). Create invitations in the UI after blueprints apply. For richer patterns (prefilled attributes, extra policies), see [Invitations](https://docs.goauthentik.io/users-sources/user/invitations/) and the upstream example blueprint **`flows-invitation-enrollment.yaml`** ([download](https://goauthentik.io/blueprints/example/flows-invitation-enrollment.yaml)). Password strength for enrollment prompts is **not** duplicated from the lab **authentication** flow here; add **Prompt** validation policies or a dedicated policy if you need parity. @@ -77,7 +77,7 @@ Blueprint **22** does **not** create sample **Invitation** rows (no placeholder Three inventory lists are concatenated **in this order** into **`10-noble-public-groups.yaml.j2`**: -1. **`noble_authentik_blueprint_public_groups`** — generic “public hostname” audience (defaults **`noble-public-users`** / **`noble-public-admins`**). +1. **`noble_authentik_blueprint_public_groups`** — optional extra groups merged first (default **empty**; use for legacy names or shared groups that must exist before **`extra`** / Nikflix). 2. **`noble_authentik_blueprint_extra_directory_groups`** — any other groups (empty by default). 3. **`noble_authentik_blueprint_nikflix_groups`** — Nikflix-facing groups (defaults **`nikflix-users`** / **`nikflix-admins`** with **`noble.ak/brand: nikflix`**). Listed last so **`parents`** can reference groups from (1) or (2) if you choose. @@ -88,7 +88,7 @@ Each item may be: | **String** | **`my-app-operators`** — creates a group with that **name** only. | | **Mapping** | **`name`** (required), optional **`is_superuser`**: **`true`** (use sparingly), **`attributes`**: dict (JSON on the group; useful in expression policies), **`parents`**: list of **existing** group **names** (resolved with **`!Find`**). | -Order matters for **`parents`**: every parent must already exist when the child row is applied — list parents **above** children in the merged list, or reference groups Authentik already created (for example **`noble-public-users`** before **`noble-public-admins`** with **`parents: [noble-public-users]`**). See [Group properties and attributes](https://docs.goauthentik.io/users-sources/groups/group_ref/). +Order matters for **`parents`**: every parent must already exist when the child row is applied — list parents **above** children in the merged list, or reference groups Authentik already created (for example **`nikflix-users`** before **`nikflix-admins`** with **`parents: [nikflix-users]`**). See [Group properties and attributes](https://docs.goauthentik.io/users-sources/groups/group_ref/). ##### Audience groups vs per-service groups diff --git a/ansible/roles/noble_authentik/defaults/main.yml b/ansible/roles/noble_authentik/defaults/main.yml index 2ced066..d83a979 100644 --- a/ansible/roles/noble_authentik/defaults/main.yml +++ b/ansible/roles/noble_authentik/defaults/main.yml @@ -29,24 +29,18 @@ noble_authentik_ingress_extra_hosts: [] # Mounted **blueprints** (ConfigMap → worker `/blueprints/mounted/cm-*`). See README § split routing / two-Brand. noble_authentik_blueprints_enabled: false noble_authentik_blueprints_configmap_name: authentik-noble-blueprints -# Directory groups for the public Brand(s), merged with **`noble_authentik_blueprint_extra_directory_groups`** -# and **`noble_authentik_blueprint_nikflix_groups`** into **`templates/blueprints/10-noble-public-groups.yaml.j2`**. Each item may be: +# Directory groups blueprint (**`10-noble-public-groups.yaml.j2`**): merges **`noble_authentik_blueprint_public_groups`** +# (optional — often empty), **`noble_authentik_blueprint_extra_directory_groups`**, and **`noble_authentik_blueprint_nikflix_groups`** +# (defaults: **`nikflix-users`** / **`nikflix-admins`**). Lab onboarding uses **`noble_authentik_blueprint_lab_invitee_group_name`** +# from blueprint **22**, not this list. Each item may be: # - a **string** (group name only), or # - a **dict** with **`name`** (required) and optional **`is_superuser`** (bool), **`attributes`** (dict → JSON in blueprint), # **`parents`** (list of **existing** group names — list parents *before* children in these lists, or use built-in groups). -noble_authentik_blueprint_public_groups: - - name: noble-public-users - attributes: - "noble.ak/audience": public - - name: noble-public-admins - parents: - - noble-public-users - attributes: - "noble.ak/audience": public -# Additional directory groups (same entry shape as **`noble_authentik_blueprint_public_groups`**); merged into one blueprint. +noble_authentik_blueprint_public_groups: [] +# Additional directory groups (same entry shape as **`noble_authentik_blueprint_public_groups`**); merged into blueprint **10** after **`public_groups`**. noble_authentik_blueprint_extra_directory_groups: [] -# Nikflix (e.g. **auth.nikflix.ca**) directory groups — merged **after** public + extra so **`parents`** can reference those. -# Prefer **audience** groups (`nikflix-users` / `nikflix-admins`); add per-service groups only when an app needs a distinct binding. +# Nikflix (e.g. **auth.nikflix.ca**) directory groups — merged **after** optional **`public_groups`** + **`extra_directory_groups`** +# so **`parents`** can reference those. Prefer **`nikflix-users`** / **`nikflix-admins`** for the internet-facing Brand. noble_authentik_blueprint_nikflix_groups: - name: nikflix-users attributes: @@ -67,7 +61,7 @@ noble_authentik_blueprint_lab_operator_groups: - noble-admins - authentik Admins noble_authentik_blueprint_lab_brand_title: Noble lab (operators) -noble_authentik_blueprint_public_brand_title_prefix: Noble public +noble_authentik_blueprint_public_brand_title_prefix: Nikflix # Public hostname Brand(s) → dedicated authentication flow (**21-noble-public-…** blueprint). noble_authentik_blueprint_public_auth_flow_slug: noble-public-authentication-flow # Lab flow: password stage (**failed_attempts_before_cancel**) and strength checks (expression policy; skips when **password** not yet in request context). @@ -84,18 +78,18 @@ noble_authentik_blueprint_lab_password_policy_error_message: >- # Lab MFA when user has no compatible device: **skip** (like stock), **deny** (block), **configure** (TOTP setup via default stage). noble_authentik_blueprint_lab_mfa_not_configured_action: configure # Invitation-based **enrollment** flows (blueprint **22**). Brands do not select enrollment; each **Invitation** picks a flow. -# Link shape: **`https:///if/flow//?itoken=`** — use the **public** hostname for **`noble_authentik_blueprint_public_invitation_enrollment_flow_slug`** invites. -noble_authentik_blueprint_public_invitation_enrollment_flow_slug: noble-public-invitation-enrollment +# Link shape: **`https:///if/flow//?itoken=`** — use your **Nikflix / extra_hosts** FQDN for this flow’s invites. +noble_authentik_blueprint_public_invitation_enrollment_flow_slug: nikflix-invitation-enrollment noble_authentik_blueprint_lab_invitation_enrollment_flow_slug: noble-lab-invitation-enrollment -noble_authentik_blueprint_public_invitation_flow_name: Noble public invitation enrollment +noble_authentik_blueprint_public_invitation_flow_name: Nikflix invitation enrollment noble_authentik_blueprint_public_invitation_flow_title: Complete your signup noble_authentik_blueprint_lab_invitation_flow_name: Noble lab invitation enrollment noble_authentik_blueprint_lab_invitation_flow_title: Lab access — complete enrollment -# **User write** for public invites: must match an existing **Group** name from **`10-noble-public-groups`** (default **`noble-public-users`**; use **`nikflix-users`** if you only maintain Nikflix groups). -noble_authentik_blueprint_public_invitation_user_group: noble-public-users +# **User write** for Nikflix (internet) invites: must match a **Group** created in blueprint **10** (default **`nikflix-users`**). +noble_authentik_blueprint_public_invitation_user_group: nikflix-users # **`internal`** — normal directory users (default). Use **`external`** only when you intentionally isolate invitees from admin / “internal-only” surfaces (see [Invitations troubleshooting](https://docs.goauthentik.io/users-sources/user/invitations/)). noble_authentik_blueprint_public_invitation_user_type: internal -noble_authentik_blueprint_public_invitation_user_path: users/noble/public +noble_authentik_blueprint_public_invitation_user_path: users/noble/nikflix # Lab invites: blueprint creates **`noble_authentik_blueprint_lab_invitee_group_name`**; add members to **`noble_authentik_blueprint_lab_operator_groups`** manually when they should use the lab URL. noble_authentik_blueprint_lab_invitee_group_name: noble-lab-invited noble_authentik_blueprint_lab_invitation_user_type: internal diff --git a/ansible/roles/noble_authentik/templates/blueprints/10-noble-public-groups.yaml.j2 b/ansible/roles/noble_authentik/templates/blueprints/10-noble-public-groups.yaml.j2 index e9e374a..11a61c0 100644 --- a/ansible/roles/noble_authentik/templates/blueprints/10-noble-public-groups.yaml.j2 +++ b/ansible/roles/noble_authentik/templates/blueprints/10-noble-public-groups.yaml.j2 @@ -1,5 +1,5 @@ -# Noble — directory groups (blueprint). Merges (in order): **noble_authentik_blueprint_public_groups**, -# **noble_authentik_blueprint_extra_directory_groups**, **noble_authentik_blueprint_nikflix_groups** (see role README). +# Noble — directory groups (blueprint). Merges (in order): **`noble_authentik_blueprint_public_groups`** (optional), +# **`noble_authentik_blueprint_extra_directory_groups`**, **`noble_authentik_blueprint_nikflix_groups`** (see role **defaults** / README). # Each entry: a string (**name** only), or a mapping with **name** and optional **is_superuser**, **attributes**, **parents**. # **parents** must reference groups that already exist: list those entries *before* children in the merged list, or rely on built-in groups. version: 1