# FILE: infra/base/authentik/bootstrap-prod.yaml # Authentik Bootstrap for Production (app.harkon.co.uk) version: 1 metadata: name: AI Tax Agent — Production Bootstrap entries: # --- Groups first (so the admin user can reference them) ------------------- - model: authentik_core.group state: present identifiers: name: "Administrators" attrs: is_superuser: true - model: authentik_core.group state: present identifiers: name: "Tax Reviewers" attrs: is_superuser: false - model: authentik_core.group state: present identifiers: name: "Accountants" attrs: is_superuser: false - model: authentik_core.group state: present identifiers: name: "Clients" attrs: is_superuser: false # --- Admin user ------------------------------------------------------------ - model: authentik_core.user state: present identifiers: username: admin attrs: name: "System Administrator" email: admin@app.harkon.co.uk is_active: true is_staff: true is_superuser: true groups: - !Find [authentik_core.group, [name, "Administrators"]] # --- Scope mappings -------------------------------------------------------- - id: scope_openid model: authentik_providers_oauth2.scopemapping identifiers: scope_name: openid - id: scope_profile model: authentik_providers_oauth2.scopemapping identifiers: scope_name: profile - id: scope_email model: authentik_providers_oauth2.scopemapping identifiers: scope_name: email - id: scope_groups model: authentik_providers_oauth2.scopemapping identifiers: scope_name: groups attrs: name: "authentik default OAuth Mapping: OpenID 'groups'" expression: | return { "groups": [group.name for group in request.user.ak_groups.all()] } - id: scope_offline model: authentik_providers_oauth2.scopemapping identifiers: scope_name: offline_access # Helper finders/definitions - id: default_signing_key model: authentik_crypto.certificatekeypair state: present identifiers: name: "authentik Self-signed Certificate" - id: default_authz_flow model: authentik_flows.flow state: present identifiers: slug: "default-authentication-flow" - id: default_inval_flow model: authentik_flows.flow state: present identifiers: slug: "default-invalidation-flow" # --- AI Tax Agent API (Production) ----------------------------------------- - model: authentik_providers_oauth2.oauth2provider state: present identifiers: name: "AI Tax Agent API (Production)" attrs: client_id: "ai-tax-agent-api-prod" client_secret: !Env [AUTHENTIK_API_CLIENT_SECRET, "changeme-api-secret"] authorization_grant_type: "authorization-code" client_type: "confidential" issuer_mode: "per_provider" sub_mode: "hashed_user_id" include_claims_in_id_token: true signing_key: !KeyOf default_signing_key redirect_uris: - matching_mode: strict url: "https://api.app.harkon.co.uk/auth/callback" scope_mappings: - !KeyOf scope_openid - !KeyOf scope_profile - !KeyOf scope_email - !KeyOf scope_groups - !KeyOf scope_offline authorization_flow: !KeyOf default_authz_flow invalidation_flow: !KeyOf default_inval_flow - model: authentik_core.application state: present identifiers: slug: "ai-tax-agent-api-prod" attrs: name: "AI Tax Agent API (Production)" provider: !Find [ authentik_providers_oauth2.oauth2provider, [name, "AI Tax Agent API (Production)"], ] meta_launch_url: "https://api.app.harkon.co.uk" meta_description: "AI Tax Agent API Services (Production)" meta_publisher: "AI Tax Agent" policy_engine_mode: "any" # --- MinIO (Production) ---------------------------------------------------- - model: authentik_providers_oauth2.oauth2provider state: present identifiers: name: "MinIO (Production)" attrs: client_id: "minio-prod" client_secret: !Env [AUTHENTIK_MINIO_CLIENT_SECRET, "changeme-minio-secret"] authorization_grant_type: "authorization-code" client_type: "confidential" issuer_mode: "per_provider" sub_mode: "hashed_user_id" include_claims_in_id_token: true signing_key: !KeyOf default_signing_key redirect_uris: - matching_mode: strict url: "https://minio.app.harkon.co.uk/oauth_callback" scope_mappings: - !KeyOf scope_openid - !KeyOf scope_profile - !KeyOf scope_email - !KeyOf scope_groups - !KeyOf scope_offline - !KeyOf scope_minio_policy authorization_flow: !KeyOf default_authz_flow invalidation_flow: !KeyOf default_inval_flow - model: authentik_core.application state: present identifiers: slug: "minio-prod" attrs: name: "MinIO (Production)" provider: !Find [ authentik_providers_oauth2.oauth2provider, [name, "MinIO (Production)"], ] meta_launch_url: "https://minio.app.harkon.co.uk" meta_description: "Object storage console (Production)" meta_publisher: "AI Tax Agent" policy_engine_mode: "any" # --- Vault (Production) ---------------------------------------------------- - model: authentik_providers_oauth2.oauth2provider state: present identifiers: name: "Vault (Production)" attrs: client_id: "vault-prod" client_secret: !Env [AUTHENTIK_VAULT_CLIENT_SECRET, "changeme-vault-secret"] authorization_grant_type: "authorization-code" client_type: "confidential" issuer_mode: "per_provider" sub_mode: "hashed_user_id" include_claims_in_id_token: true signing_key: !KeyOf default_signing_key redirect_uris: - matching_mode: strict url: "https://vault.app.harkon.co.uk/ui/vault/auth/oidc/oidc/callback" - matching_mode: strict url: "https://vault.app.harkon.co.uk/oidc/callback" scope_mappings: - !KeyOf scope_openid - !KeyOf scope_profile - !KeyOf scope_email - !KeyOf scope_groups - !KeyOf scope_offline authorization_flow: !KeyOf default_authz_flow invalidation_flow: !KeyOf default_inval_flow - model: authentik_core.application state: present identifiers: slug: "vault-prod" attrs: name: "Vault (Production)" provider: !Find [ authentik_providers_oauth2.oauth2provider, [name, "Vault (Production)"], ] meta_launch_url: "https://vault.app.harkon.co.uk" meta_description: "Secrets management (Vault) (Production)" meta_publisher: "AI Tax Agent" policy_engine_mode: "any" # --- Grafana (Production) -------------------------------------------------- # Custom Role Mapping for Grafana - id: scope_grafana_roles model: authentik_providers_oauth2.scopemapping state: present identifiers: name: "Grafana Role Mapping" attrs: name: "Grafana Role Mapping" description: "Maps Authentik groups to Grafana roles" scope_name: "role" expression: | # Map Authentik groups to Grafana roles user_groups = [group.name for group in request.user.ak_groups.all()] # Admin role mapping if "authentik Admins" in user_groups or "Administrators" in user_groups: return {"role": "Admin"} # Editor role mapping if "Tax Reviewers" in user_groups or "Accountants" in user_groups: return {"role": "Editor"} # Default to Viewer role return {"role": "Viewer"} # Custom Scope Mapping for MinIO - id: scope_minio_policy model: authentik_providers_oauth2.scopemapping state: present identifiers: name: "MinIO Policy Mapping" attrs: name: "MinIO Policy Mapping" description: "Maps Authentik groups to MinIO policies" scope_name: "minio" expression: | # Map Authentik groups to MinIO policies user_groups = [group.name for group in request.user.ak_groups.all()] # Admin policy mapping if "Administrators" in user_groups: return {"policy": ["consoleAdmin"]} # Default to readwrite for other known groups if "Tax Reviewers" in user_groups or "Accountants" in user_groups: return {"policy": ["readwrite"]} # Default fallback return {"policy": ["readonly"]} - model: authentik_providers_oauth2.oauth2provider state: present identifiers: name: "Grafana (Production)" attrs: client_id: "grafana-prod" client_secret: !Env [AUTHENTIK_GRAFANA_CLIENT_SECRET, "changeme-grafana-secret"] client_type: "confidential" redirect_uris: - matching_mode: strict url: "https://grafana.app.harkon.co.uk/login/generic_oauth" sub_mode: "hashed_user_id" include_claims_in_id_token: true issuer_mode: "per_provider" signing_key: !KeyOf default_signing_key property_mappings: - !KeyOf scope_openid - !KeyOf scope_email - !KeyOf scope_profile - !KeyOf scope_groups - !KeyOf scope_grafana_roles authorization_flow: !KeyOf default_authz_flow invalidation_flow: !KeyOf default_inval_flow - model: authentik_core.application state: present identifiers: slug: "grafana-prod" attrs: name: "Grafana (Production)" provider: !Find [ authentik_providers_oauth2.oauth2provider, [name, "Grafana (Production)"], ] meta_launch_url: "https://grafana.app.harkon.co.uk" meta_description: "Grafana monitoring (Production)" meta_publisher: "Grafana Labs" policy_engine_mode: "any" # --- Policies -------------------------------------------------------------- - id: policy_always_allow model: authentik_policies_expression.expressionpolicy state: present identifiers: name: "Always Allow" attrs: expression: "return True" - model: authentik_policies.policybinding state: present identifiers: policy: !KeyOf policy_always_allow target: !Find [authentik_core.application, [slug, "ai-tax-agent-api-prod"]] attrs: order: 0 - model: authentik_policies.policybinding state: present identifiers: policy: !KeyOf policy_always_allow target: !Find [authentik_core.application, [slug, "minio-prod"]] attrs: order: 0 - model: authentik_policies.policybinding state: present identifiers: policy: !KeyOf policy_always_allow target: !Find [authentik_core.application, [slug, "vault-prod"]] attrs: order: 0 - model: authentik_policies.policybinding state: present identifiers: policy: !KeyOf policy_always_allow target: !Find [authentik_core.application, [slug, "grafana-prod"]] attrs: order: 0 # --- Qdrant (Production) --------------------------------------------------- - id: provider_qdrant model: authentik_providers_proxy.proxyprovider state: present identifiers: name: "Qdrant (Production)" attrs: external_host: "https://qdrant.app.harkon.co.uk:8444" authorization_flow: !KeyOf default_authz_flow invalidation_flow: !KeyOf default_inval_flow mode: "forward_single" - model: authentik_core.application state: present identifiers: slug: "qdrant-prod" attrs: name: "Qdrant (Production)" provider: !KeyOf provider_qdrant meta_launch_url: "https://qdrant.app.harkon.co.uk:8444/dashboard" meta_description: "Vector Database Dashboard" meta_publisher: "AI Tax Agent" policy_engine_mode: "any" # --- Neo4j (Production) ---------------------------------------------------- - id: provider_neo4j model: authentik_providers_proxy.proxyprovider state: present identifiers: name: "Neo4j (Production)" attrs: external_host: "https://neo4j.app.harkon.co.uk:8444" authorization_flow: !KeyOf default_authz_flow invalidation_flow: !KeyOf default_inval_flow mode: "forward_single" - model: authentik_core.application state: present identifiers: slug: "neo4j-prod" attrs: name: "Neo4j (Production)" provider: !KeyOf provider_neo4j meta_launch_url: "https://neo4j.app.harkon.co.uk:8444" meta_description: "Knowledge Graph Browser" meta_publisher: "AI Tax Agent" policy_engine_mode: "any" # --- Policy Bindings for New Apps ------------------------------------------ - model: authentik_policies.policybinding state: present identifiers: policy: !KeyOf policy_always_allow target: !Find [authentik_core.application, [slug, "qdrant-prod"]] attrs: order: 0 - model: authentik_policies.policybinding state: present identifiers: policy: !KeyOf policy_always_allow target: !Find [authentik_core.application, [slug, "neo4j-prod"]] attrs: order: 0 # --- Outpost Assignment ---------------------------------------------------- - model: authentik_outposts.outpost state: present identifiers: name: "authentik Embedded Outpost" attrs: providers: - !KeyOf provider_qdrant - !KeyOf provider_neo4j