Add optional SMTP configuration for Authentik, including email host, port, and credentials. Update README and .env.sample to clarify usage for outbound email settings. Introduce blueprint support for enhanced deployment flexibility, with assertions in Ansible tasks to ensure required variables are set when enabled.

This commit is contained in:
Nikholas Pcenicni
2026-05-14 22:21:11 -04:00
parent e48b19b64c
commit fbcd2416e6
14 changed files with 478 additions and 6 deletions

View File

@@ -25,6 +25,24 @@ global:
value: "{{ noble_authentik_s3_region }}"
- name: AUTHENTIK_STORAGE__S3__ADDRESSING_STYLE
value: "{{ noble_authentik_s3_addressing_style }}"
{% if noble_authentik_smtp_host | default('') | trim | length > 0 %}
- name: AUTHENTIK_EMAIL__HOST
value: {{ noble_authentik_smtp_host | trim | to_json }}
- name: AUTHENTIK_EMAIL__PORT
value: {{ (noble_authentik_smtp_port | default('587') | string) | to_json }}
- name: AUTHENTIK_EMAIL__USERNAME
value: {{ noble_authentik_smtp_username | default('') | to_json }}
- name: AUTHENTIK_EMAIL__PASSWORD
value: {{ noble_authentik_smtp_password | default('') | to_json }}
- name: AUTHENTIK_EMAIL__USE_TLS
value: {{ (noble_authentik_smtp_use_tls | default('true') | string) | to_json }}
- name: AUTHENTIK_EMAIL__USE_SSL
value: {{ (noble_authentik_smtp_use_ssl | default('false') | string) | to_json }}
- name: AUTHENTIK_EMAIL__TIMEOUT
value: {{ (noble_authentik_smtp_timeout | default('30') | string) | to_json }}
- name: AUTHENTIK_EMAIL__FROM
value: {{ noble_authentik_smtp_from | trim | to_json }}
{% endif %}
postgresql:
auth:
password: "{{ noble_authentik_postgresql_password }}"
@@ -46,3 +64,8 @@ server:
- {{ h }}
{% endfor %}
{% endif %}
{% if noble_authentik_blueprints_enabled | default(false) | bool %}
blueprints:
configMaps:
- {{ noble_authentik_blueprints_configmap_name }}
{% endif %}

View File

@@ -0,0 +1,13 @@
# Noble — directory groups for the **public** hostname Brand (see role README).
# Groups are global to the instance; use policies and OAuth scope mappings to scope claims per app.
version: 1
metadata:
name: noble-public-groups
labels:
blueprints.goauthentik.io/instantiate: "true"
entries:
{% for group in noble_authentik_blueprint_public_groups | default([]) %}
- model: authentik_core.group
identifiers:
name: "{{ group | trim }}"
{% endfor %}

View File

@@ -0,0 +1,101 @@
# Noble — authentication flow for the **lab** hostname Brand: only members of operator groups may continue.
# Reuses default identification / password / MFA / login stages; adds a policy on the password stage binding.
version: 1
metadata:
name: noble-lab-operator-authentication
labels:
blueprints.goauthentik.io/instantiate: "true"
entries:
- model: authentik_blueprints.metaapplyblueprint
attrs:
identifiers:
name: Default - Password change flow
required: false
- model: authentik_flows.flow
id: flow
identifiers:
slug: {{ noble_authentik_blueprint_lab_flow_slug | trim | to_json }}
attrs:
name: Noble lab (operators)
title: Noble lab — operators only
designation: authentication
authentication: none
- id: noble-lab-identification-binding
model: authentik_flows.flowstagebinding
identifiers:
order: 10
stage: !Find [authentik_stages_identification.identificationstage, [name, default-authentication-identification]]
target: !KeyOf flow
- id: noble-lab-password-binding
model: authentik_flows.flowstagebinding
identifiers:
order: 20
stage: !Find [authentik_stages_password.passwordstage, [name, default-authentication-password]]
target: !KeyOf flow
attrs:
re_evaluate_policies: true
- id: noble-lab-authenticator-binding
model: authentik_flows.flowstagebinding
identifiers:
order: 30
stage: !Find [authentik_stages_authenticator_validate.authenticatorvalidatestage, [name, default-authentication-mfa-validation]]
target: !KeyOf flow
- model: authentik_flows.flowstagebinding
identifiers:
order: 100
stage: !Find [authentik_stages_user_login.userloginstage, [name, default-authentication-login]]
target: !KeyOf flow
- model: authentik_policies_expression.expressionpolicy
id: noble-lab-password-optional
identifiers:
name: noble-lab-password-optional
attrs:
expression: |
flow_plan = request.context.get("flow_plan")
if not flow_plan:
return True
return not hasattr(flow_plan.context.get("pending_user"), "backend")
- model: authentik_policies_expression.expressionpolicy
id: noble-lab-authenticator-validate-optional
identifiers:
name: noble-lab-authenticator-validate-optional
attrs:
expression: |
flow_plan = request.context.get("flow_plan")
if not flow_plan:
return True
return not (flow_plan.context.get("auth_method") == "auth_webauthn_pwl")
- model: authentik_policies_expression.expressionpolicy
id: noble-lab-operators-only
identifiers:
name: {{ noble_authentik_blueprint_operator_policy_name | trim | to_json }}
attrs:
expression: |
u = context.get("pending_user")
if u is None:
return False
{% for g in noble_authentik_blueprint_lab_operator_groups | default([]) %}
if ak_is_group_member(u, name={{ g | trim | to_json }}):
return True
{% endfor %}
ak_message("This login URL is for administrators only. Use the public Authentik hostname instead.")
return False
- model: authentik_policies.policybinding
identifiers:
order: 5
target: !KeyOf noble-lab-password-binding
policy: !KeyOf noble-lab-operators-only
- model: authentik_policies.policybinding
identifiers:
order: 10
target: !KeyOf noble-lab-password-binding
policy: !KeyOf noble-lab-password-optional
attrs:
failure_result: true
- model: authentik_policies.policybinding
identifiers:
order: 10
target: !KeyOf noble-lab-authenticator-binding
policy: !KeyOf noble-lab-authenticator-validate-optional
attrs:
failure_result: true

View File

@@ -0,0 +1,27 @@
# Noble — Brands so **Host** selects authentication flow: lab hostname → operator-only flow; extra hosts → default login.
version: 1
metadata:
name: noble-brands-domain-split
labels:
blueprints.goauthentik.io/instantiate: "true"
entries:
- model: authentik_brands.brand
identifiers:
domain: {{ noble_authentik_host | trim | to_json }}
attrs:
default: false
title: {{ noble_authentik_blueprint_lab_brand_title | trim | to_json }}
flow_authentication: !Find [authentik_flows.flow, [slug, {{ noble_authentik_blueprint_lab_flow_slug | trim | to_json }}]]
flow_invalidation: !Find [authentik_flows.flow, [slug, default-invalidation-flow]]
flow_user_settings: !Find [authentik_flows.flow, [slug, default-user-settings-flow]]
{% for host in noble_authentik_ingress_extra_hosts | default([]) %}
- model: authentik_brands.brand
identifiers:
domain: {{ host | trim | to_json }}
attrs:
default: false
title: {{ ((noble_authentik_blueprint_public_brand_title_prefix | default('Noble public')) ~ ' (' ~ (host | trim) ~ ')') | to_json }}
flow_authentication: !Find [authentik_flows.flow, [slug, default-authentication-flow]]
flow_invalidation: !Find [authentik_flows.flow, [slug, default-invalidation-flow]]
flow_user_settings: !Find [authentik_flows.flow, [slug, default-user-settings-flow]]
{% endfor %}