142 lines
6.2 KiB
YAML
142 lines
6.2 KiB
YAML
# infra/authentik/bootstrap/blueprints/03-application-toolctrl-admin.yaml
|
|
#
|
|
# Authentik Blueprint — OIDC provider + application for the Toolctrl
|
|
# admin panel. Consumed by Phase 09 task #82 (admin-panel OIDC login).
|
|
#
|
|
# Creates:
|
|
# - OIDC Provider `toolctrl-admin-panel`
|
|
# * client_type=confidential
|
|
# * client_id from env (TOOLCTRL_ADMIN_OIDC_CLIENT_ID)
|
|
# * client_secret from env (TOOLCTRL_ADMIN_OIDC_CLIENT_SECRET)
|
|
# * scope_mappings: openid, email, profile, groups
|
|
# * subject_mode=hashed_user_id (avoids leaking the Authentik integer PK)
|
|
# * token TTLs: code 1m, access 10m, refresh 7d, id-token 10m
|
|
# * include_claims_in_id_token=true
|
|
# - Application `Toolctrl Admin Panel`
|
|
# * launchURL points at https://admin.boiler.saas-ctrl.com/
|
|
# * Access binding: only members of toolctrl-admin OR toolctrl-staff
|
|
#
|
|
# Also creates a DISABLED placeholder provider `toolctrl-tenant-sso` reserved
|
|
# for Backlog #66. It is created with enabled=false so it occupies the slug
|
|
# without affecting routing. When #66 is picked up, just flip `enabled` and
|
|
# add the per-tenant redirect_uri templates.
|
|
|
|
version: 1
|
|
metadata:
|
|
labels:
|
|
blueprints.goauthentik.io/instantiate: "true"
|
|
name: "Toolctrl Admin Panel OIDC"
|
|
|
|
context:
|
|
client_id: "%(env:TOOLCTRL_ADMIN_OIDC_CLIENT_ID)s"
|
|
client_secret: "%(env:TOOLCTRL_ADMIN_OIDC_CLIENT_SECRET)s"
|
|
redirect_uri: "%(env:TOOLCTRL_ADMIN_OIDC_REDIRECT_URI)s"
|
|
|
|
entries:
|
|
# ---------- Signing key (use the bundled self-signed by default) -----
|
|
# Authentik ships a `authentik Self-signed Certificate` after install; we
|
|
# reference it by name so the blueprint applies cleanly on a fresh boot.
|
|
|
|
# ---------- OIDC Provider: toolctrl-admin-panel ----------------------
|
|
- identifiers:
|
|
name: toolctrl-admin-panel
|
|
model: authentik_providers_oauth2.oauth2provider
|
|
state: present
|
|
attrs:
|
|
client_type: confidential
|
|
client_id: !Context client_id
|
|
client_secret: !Context client_secret
|
|
authorization_flow: !Find [authentik_flows.flow, [slug, default-provider-authorization-implicit-consent]]
|
|
authentication_flow: !Find [authentik_flows.flow, [slug, default-authentication-flow]]
|
|
invalidation_flow: !Find [authentik_flows.flow, [slug, default-provider-invalidation-flow]]
|
|
property_mappings:
|
|
- !Find [authentik_providers_oauth2.scopemapping, [scope_name, openid]]
|
|
- !Find [authentik_providers_oauth2.scopemapping, [scope_name, email]]
|
|
- !Find [authentik_providers_oauth2.scopemapping, [scope_name, profile]]
|
|
property_mappings_group:
|
|
- !Find [authentik_providers_oauth2.scopemapping, [scope_name, openid]]
|
|
signing_key: !Find [authentik_crypto.certificatekeypair, [name, authentik Self-signed Certificate]]
|
|
sub_mode: hashed_user_id
|
|
include_claims_in_id_token: true
|
|
issuer_mode: per_provider
|
|
# Authentik 2026.x changed redirect_uris from a string to a list of
|
|
# {matching_mode, url} dicts (RedirectURI dataclass). See B-007.
|
|
redirect_uris:
|
|
- matching_mode: strict
|
|
url: !Context redirect_uri
|
|
# Short-lived auth code + access token; longer refresh window for
|
|
# admin-panel sessions (operator can revoke in Authentik UI).
|
|
access_code_validity: minutes=1
|
|
access_token_validity: minutes=10
|
|
refresh_token_validity: days=7
|
|
|
|
# ---------- Application: Toolctrl Admin Panel -------------------------
|
|
- identifiers:
|
|
slug: toolctrl-admin-panel
|
|
model: authentik_core.application
|
|
state: present
|
|
attrs:
|
|
name: "Toolctrl Admin Panel"
|
|
provider: !Find [authentik_providers_oauth2.oauth2provider, [name, toolctrl-admin-panel]]
|
|
meta_launch_url: "https://admin.boiler.saas-ctrl.com/"
|
|
meta_description: "Toolctrl admin panel — super-admin + staff console"
|
|
policy_engine_mode: any
|
|
open_in_new_tab: false
|
|
|
|
# ---------- Access bindings: admin OR staff group --------------------
|
|
- identifiers:
|
|
target: !Find [authentik_core.application, [slug, toolctrl-admin-panel]]
|
|
group: !Find [authentik_core.group, [name, toolctrl-admin]]
|
|
order: 0
|
|
model: authentik_policies.policybinding
|
|
state: present
|
|
attrs:
|
|
enabled: true
|
|
|
|
- identifiers:
|
|
target: !Find [authentik_core.application, [slug, toolctrl-admin-panel]]
|
|
group: !Find [authentik_core.group, [name, toolctrl-staff]]
|
|
order: 10
|
|
model: authentik_policies.policybinding
|
|
state: present
|
|
attrs:
|
|
enabled: true
|
|
|
|
# ---------- MFA-TOTP-for-admin binding on the application -----------
|
|
- identifiers:
|
|
target: !Find [authentik_core.application, [slug, toolctrl-admin-panel]]
|
|
policy: !Find [authentik_policies_expression.expressionpolicy, [name, toolctrl-require-mfa-totp-for-admin]]
|
|
order: 20
|
|
model: authentik_policies.policybinding
|
|
state: present
|
|
attrs:
|
|
enabled: true
|
|
|
|
# ---------- DISABLED placeholder: toolctrl-tenant-sso (#66) ---------
|
|
- identifiers:
|
|
name: toolctrl-tenant-sso
|
|
model: authentik_providers_oauth2.oauth2provider
|
|
state: present
|
|
attrs:
|
|
client_type: confidential
|
|
# Sentinel values; #66 will rewrite these.
|
|
client_id: "toolctrl-tenant-sso-placeholder"
|
|
client_secret: "placeholder-do-not-use"
|
|
authorization_flow: !Find [authentik_flows.flow, [slug, default-provider-authorization-implicit-consent]]
|
|
authentication_flow: !Find [authentik_flows.flow, [slug, default-authentication-flow]]
|
|
invalidation_flow: !Find [authentik_flows.flow, [slug, default-provider-invalidation-flow]]
|
|
signing_key: !Find [authentik_crypto.certificatekeypair, [name, authentik Self-signed Certificate]]
|
|
sub_mode: hashed_user_id
|
|
include_claims_in_id_token: true
|
|
issuer_mode: per_provider
|
|
# Authentik has no `enabled` flag at the provider level; we keep this
|
|
# provider un-attached to any Application so it has no live route.
|
|
# 2026.x requires redirect_uris even on unattached providers — use a
|
|
# non-routable placeholder. #66 will rewrite when tenant SSO lands.
|
|
redirect_uris:
|
|
- matching_mode: strict
|
|
url: "https://placeholder.invalid/oidc/callback"
|
|
access_code_validity: minutes=1
|
|
access_token_validity: minutes=10
|
|
refresh_token_validity: days=7
|