Files
home-server/ansible/roles/noble_authentik/templates/blueprints/20-noble-lab-operator-authentication-flow.yaml.j2

149 lines
5.9 KiB
Django/Jinja

# Noble — **lab** hostname authentication: operator-only, stricter password checks, MFA required (no WebAuthn-PWL skip).
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_stages_password.passwordstage
id: noble-lab-password-stage
identifiers:
name: noble-lab-authentication-password
attrs:
backends:
- authentik.core.auth.InbuiltBackend
- authentik.sources.kerberos.auth.KerberosBackend
- authentik.sources.ldap.auth.LDAPBackend
- authentik.core.auth.TokenBackend
configure_flow: !Find [authentik_flows.flow, [slug, default-password-change]]
failed_attempts_before_cancel: {{ noble_authentik_blueprint_lab_password_failed_attempts | int }}
- model: authentik_stages_authenticator_validate.authenticatorvalidatestage
id: noble-lab-authenticator-validate-strict
identifiers:
name: noble-lab-authenticator-validate-strict
attrs:
not_configured_action: {{ noble_authentik_blueprint_lab_mfa_not_configured_action | trim | lower | to_json }}
{% if noble_authentik_blueprint_lab_mfa_not_configured_action | trim | lower == 'configure' %}
configuration_stages:
- !Find [authentik_stages_authenticator_totp.authenticatortotpstage, [name, default-authenticator-totp-setup]]
{% endif %}
- 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: !KeyOf noble-lab-password-stage
target: !KeyOf flow
attrs:
re_evaluate_policies: true
- id: noble-lab-authenticator-binding
model: authentik_flows.flowstagebinding
identifiers:
order: 30
stage: !KeyOf noble-lab-authenticator-validate-strict
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-password-strength
identifiers:
name: noble-lab-password-strength
attrs:
expression: |
import re
_zxc = {{ noble_authentik_blueprint_lab_password_policy_check_zxcvbn | bool }}
_zxc_thr = {{ noble_authentik_blueprint_lab_password_policy_zxcvbn_score_threshold | int }}
pwd = request.context.get("password")
if not pwd:
return True
msg = {{ noble_authentik_blueprint_lab_password_policy_error_message | trim | to_json }}
if len(pwd) < {{ noble_authentik_blueprint_lab_password_policy_length_min | int }}:
ak_message(msg)
return False
if len(re.findall(r"[A-Z]", pwd)) < {{ noble_authentik_blueprint_lab_password_policy_amount_uppercase | int }}:
ak_message(msg)
return False
if len(re.findall(r"[a-z]", pwd)) < {{ noble_authentik_blueprint_lab_password_policy_amount_lowercase | int }}:
ak_message(msg)
return False
if len(re.findall(r"[0-9]", pwd)) < {{ noble_authentik_blueprint_lab_password_policy_amount_digits | int }}:
ak_message(msg)
return False
sym = sum(1 for c in pwd if (not c.isalnum()) and (not c.isspace()))
if sym < {{ noble_authentik_blueprint_lab_password_policy_amount_symbols | int }}:
ak_message(msg)
return False
if _zxc:
try:
from zxcvbn import zxcvbn
if zxcvbn(pwd[:72])["score"] <= _zxc_thr:
ak_message("Password is too weak for the lab policy.")
return False
except Exception:
pass
return True
- 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: 15
target: !KeyOf noble-lab-password-binding
policy: !KeyOf noble-lab-password-strength