mirror of
https://gitlab.kube.huskypup.net/Scooby/Homelabv4.git
synced 2026-08-20 23:16:49 +00:00
Initial commit
This commit is contained in:
@@ -0,0 +1,49 @@
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: authentik-blueprints-argocd
|
||||
namespace: authentik
|
||||
labels:
|
||||
goauthentik.io/blueprint: "true"
|
||||
data:
|
||||
argocd.yaml: |-
|
||||
version: 1
|
||||
metadata:
|
||||
name: argocd-oidc
|
||||
entries:
|
||||
- model: authentik_providers_oauth2.oauth2provider
|
||||
id: argocd-provider
|
||||
state: present
|
||||
identifiers:
|
||||
name: ArgoCD
|
||||
attrs:
|
||||
name: ArgoCD
|
||||
client_id: 3791058a7de278045e5ec36be29f7a33d635119b8c786f20c86b185139c28841
|
||||
client_secret: f787416822f5bf4c46fe9170e63d1bf9520bab7703d53341aaaec107c8c4ba253d96c30b70d23a1c0b5a401ae1ae4bfb5db06092d338e29e0b0f04cd29bc0b36
|
||||
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]]
|
||||
redirect_uris:
|
||||
- url: "https://argocd.kube.huskypup.net/auth/callback"
|
||||
matching_mode: strict
|
||||
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]]
|
||||
client_type: confidential
|
||||
access_code_validity: "minutes=10"
|
||||
access_token_validity: "hours=1"
|
||||
refresh_token_validity: "days=30"
|
||||
signing_key: !Find [authentik_crypto.certificatekeypair, [name, "authentik Internal JWT Certificate"]]
|
||||
|
||||
- model: authentik_core.application
|
||||
id: argocd-application
|
||||
state: present
|
||||
identifiers:
|
||||
slug: argocd
|
||||
attrs:
|
||||
name: ArgoCD
|
||||
slug: argocd
|
||||
policy_engine_mode: any
|
||||
provider: !KeyOf argocd-provider
|
||||
@@ -0,0 +1,63 @@
|
||||
---
|
||||
# Ceph Dashboard SAML2 Provider Blueprint for Authentik
|
||||
# Creates a SAML2 provider for Ceph Dashboard native SSO
|
||||
# Ceph expects:
|
||||
# - Audience: https://ceph.kube.huskypup.net/auth/saml2/metadata
|
||||
# - ACS URL: https://ceph.kube.huskypup.net/auth/saml2
|
||||
# - Username attribute: "username"
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: authentik-blueprints-ceph
|
||||
namespace: authentik
|
||||
labels:
|
||||
goauthentik.io/blueprint: "true"
|
||||
data:
|
||||
ceph.yaml: |-
|
||||
version: 1
|
||||
metadata:
|
||||
name: ceph-dashboard-saml
|
||||
entries:
|
||||
# SAML Property Mapping for username attribute (required by Ceph)
|
||||
- model: authentik_providers_saml.samlpropertymapping
|
||||
id: ceph-username-mapping
|
||||
state: present
|
||||
identifiers:
|
||||
managed: goauthentik.io/providers/saml/ceph-username
|
||||
attrs:
|
||||
name: "Ceph Dashboard SAML: Username"
|
||||
saml_name: "username"
|
||||
expression: "return request.user.username"
|
||||
|
||||
# SAML2 Provider for Ceph Dashboard
|
||||
- model: authentik_providers_saml.samlprovider
|
||||
id: ceph-dashboard-saml-provider
|
||||
state: present
|
||||
identifiers:
|
||||
name: ceph-dashboard-saml
|
||||
attrs:
|
||||
name: ceph-dashboard-saml
|
||||
authorization_flow: !Find [authentik_flows.flow, [slug, default-provider-authorization-implicit-consent]]
|
||||
invalidation_flow: !Find [authentik_flows.flow, [slug, default-provider-invalidation-flow]]
|
||||
acs_url: "https://ceph.kube.huskypup.net/auth/saml2"
|
||||
audience: "https://ceph.kube.huskypup.net/auth/saml2/metadata"
|
||||
sp_binding: post
|
||||
default_name_id_policy: "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress"
|
||||
signing_kp: !Find [authentik_crypto.certificatekeypair, [name, authentik Self-signed Certificate]]
|
||||
sign_response: true
|
||||
sign_assertion: true
|
||||
property_mappings:
|
||||
- !KeyOf ceph-username-mapping
|
||||
|
||||
# Application entry
|
||||
- model: authentik_core.application
|
||||
id: ceph-dashboard-application
|
||||
state: present
|
||||
identifiers:
|
||||
slug: ceph-dashboard
|
||||
attrs:
|
||||
name: Ceph Dashboard
|
||||
slug: ceph-dashboard
|
||||
policy_engine_mode: any
|
||||
provider: !KeyOf ceph-dashboard-saml-provider
|
||||
meta_launch_url: "https://ceph.kube.huskypup.net"
|
||||
@@ -0,0 +1,58 @@
|
||||
---
|
||||
# DEPRECATED: Ceph Dashboard OIDC Provider Blueprint
|
||||
# This blueprint was used with oauth2-proxy which has been removed.
|
||||
# Ceph Dashboard auth is now handled by Istio ext_authz + Authentik forward-auth.
|
||||
# This file is NOT mounted in Authentik (not in configMaps list).
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: authentik-blueprints-ceph-oidc
|
||||
namespace: authentik
|
||||
labels:
|
||||
goauthentik.io/blueprint: "true"
|
||||
data:
|
||||
ceph-oidc.yaml: |-
|
||||
version: 1
|
||||
metadata:
|
||||
name: ceph-dashboard-oidc
|
||||
entries:
|
||||
# OAuth2/OIDC Provider for Ceph Dashboard (via oauth2-proxy)
|
||||
- model: authentik_providers_oauth2.oauth2provider
|
||||
id: ceph-dashboard-oidc-provider
|
||||
state: present
|
||||
identifiers:
|
||||
name: ceph-dashboard
|
||||
attrs:
|
||||
name: ceph-dashboard
|
||||
authorization_flow: !Find [authentik_flows.flow, [slug, default-provider-authorization-implicit-consent]]
|
||||
invalidation_flow: !Find [authentik_flows.flow, [slug, default-provider-invalidation-flow]]
|
||||
client_type: confidential
|
||||
client_id: ceph-dashboard
|
||||
client_secret: ceph-dashboard-oidc-secret-homelab-2026
|
||||
redirect_uris: |
|
||||
https://ceph.kube.huskypup.net/oauth2/callback
|
||||
signing_key: !Find [authentik_crypto.certificatekeypair, [name, authentik Self-signed Certificate]]
|
||||
access_code_validity: minutes=1
|
||||
access_token_validity: minutes=5
|
||||
refresh_token_validity: days=30
|
||||
include_claims_in_id_token: true
|
||||
sub_mode: user_username
|
||||
issuer_mode: per_provider
|
||||
property_mappings:
|
||||
- !Find [authentik_providers_oauth2.scopemapping, [managed, goauthentik.io/providers/oauth2/scope-openid]]
|
||||
- !Find [authentik_providers_oauth2.scopemapping, [managed, goauthentik.io/providers/oauth2/scope-email]]
|
||||
- !Find [authentik_providers_oauth2.scopemapping, [managed, goauthentik.io/providers/oauth2/scope-profile]]
|
||||
|
||||
# Application entry - update existing or create new
|
||||
- model: authentik_core.application
|
||||
id: ceph-dashboard-application
|
||||
state: present
|
||||
identifiers:
|
||||
slug: ceph-dashboard
|
||||
attrs:
|
||||
name: Ceph Dashboard
|
||||
slug: ceph-dashboard
|
||||
policy_engine_mode: any
|
||||
provider: !KeyOf ceph-dashboard-oidc-provider
|
||||
meta_launch_url: "https://ceph.kube.huskypup.net"
|
||||
meta_icon: "https://ceph.io/assets/favicons/favicon.ico"
|
||||
@@ -0,0 +1,53 @@
|
||||
apiVersion: postgresql.cnpg.io/v1
|
||||
kind: Cluster
|
||||
metadata:
|
||||
name: pg-authentik
|
||||
namespace: authentik
|
||||
spec:
|
||||
imageName: ghcr.io/cloudnative-pg/postgresql:16
|
||||
instances: 2
|
||||
|
||||
# Resource limits to prevent OOM
|
||||
resources:
|
||||
requests:
|
||||
memory: "512Mi"
|
||||
cpu: "25m"
|
||||
limits:
|
||||
memory: "2Gi"
|
||||
cpu: "250m"
|
||||
|
||||
# Spread replicas across different nodes
|
||||
affinity:
|
||||
topologyKey: kubernetes.io/hostname
|
||||
|
||||
storage:
|
||||
size: 5Gi
|
||||
storageClass: rook-ceph-block
|
||||
|
||||
primaryUpdateStrategy: unsupervised
|
||||
|
||||
# PostgreSQL configuration for better performance
|
||||
postgresql:
|
||||
parameters:
|
||||
max_connections: "200"
|
||||
shared_buffers: "512MB"
|
||||
effective_cache_size: "1536MB"
|
||||
maintenance_work_mem: "128MB"
|
||||
checkpoint_completion_target: "0.9"
|
||||
wal_buffers: "16MB"
|
||||
default_statistics_target: "100"
|
||||
random_page_cost: "1.1"
|
||||
effective_io_concurrency: "200"
|
||||
work_mem: "2621kB"
|
||||
min_wal_size: "1GB"
|
||||
max_wal_size: "4GB"
|
||||
|
||||
bootstrap:
|
||||
initdb:
|
||||
database: app
|
||||
owner: app
|
||||
|
||||
monitoring:
|
||||
enablePodMonitor: true
|
||||
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
---
|
||||
apiVersion: monitoring.coreos.com/v1
|
||||
kind: PodMonitor
|
||||
metadata:
|
||||
name: cnpg-postgres
|
||||
namespace: authentik
|
||||
labels:
|
||||
release: prometheus
|
||||
spec:
|
||||
selector:
|
||||
matchLabels:
|
||||
cnpg.io/cluster: pg-authentik
|
||||
podMetricsEndpoints:
|
||||
- port: metrics
|
||||
path: /metrics
|
||||
interval: 30s
|
||||
@@ -0,0 +1,39 @@
|
||||
---
|
||||
apiVersion: generators.external-secrets.io/v1alpha1
|
||||
kind: Password
|
||||
metadata:
|
||||
name: authentik-cnpg-secret
|
||||
namespace: authentik
|
||||
spec:
|
||||
length: 42
|
||||
digits: 5
|
||||
symbols: 5
|
||||
symbolCharacters: "-_$@"
|
||||
noUpper: false
|
||||
allowRepeat: true
|
||||
---
|
||||
apiVersion: external-secrets.io/v1
|
||||
kind: ExternalSecret
|
||||
metadata:
|
||||
name: authentik-cnpg-secret
|
||||
namespace: authentik
|
||||
spec:
|
||||
# how often to rotate the DB password
|
||||
refreshInterval: "24h"
|
||||
target:
|
||||
# This will merge the generated password into the existing pg-authentik-app secret
|
||||
name: pg-authentik-app
|
||||
creationPolicy: Merge
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
cnpg.io/reload: "true"
|
||||
data:
|
||||
# Override the password field with our ESO-generated password
|
||||
password: "{{ .password }}"
|
||||
dataFrom:
|
||||
- sourceRef:
|
||||
generatorRef:
|
||||
apiVersion: generators.external-secrets.io/v1alpha1
|
||||
kind: Password
|
||||
name: authentik-cnpg-secret
|
||||
@@ -0,0 +1,81 @@
|
||||
---
|
||||
# Forward Auth Proxy Provider Blueprint for Authentik
|
||||
#
|
||||
# Replaces oauth2-proxy with Authentik's built-in forward-auth capability.
|
||||
# Istio's ext_authz filter calls Authentik's /outpost.goauthentik.io/auth/nginx
|
||||
# endpoint to authenticate requests to protected services.
|
||||
#
|
||||
# Services protected by this provider:
|
||||
# - Prometheus, Ceph Dashboard, TeslaMate, ESPHome, Frigate, Kiali, Nessus, Netbird
|
||||
#
|
||||
# Services with native OIDC are NOT included here (they handle auth themselves):
|
||||
# - GitLab, ArgoCD, Grafana, n8n, Home Assistant, Rancher, Nextcloud
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: authentik-blueprints-forward-auth
|
||||
namespace: authentik
|
||||
labels:
|
||||
goauthentik.io/blueprint: "true"
|
||||
data:
|
||||
forward-auth.yaml: |-
|
||||
version: 1
|
||||
metadata:
|
||||
name: forward-auth-provider
|
||||
entries:
|
||||
# ================================================================
|
||||
# Proxy Provider - Forward Auth (domain mode) for Istio ext_authz
|
||||
# ================================================================
|
||||
# forward_domain mode handles ALL subdomains of cookie_domain.
|
||||
# The embedded outpost matches any *.kube.huskypup.net request.
|
||||
# Auth session is shared across subdomains via a single cookie.
|
||||
- model: authentik_providers_proxy.proxyprovider
|
||||
id: forward-auth-provider
|
||||
state: present
|
||||
identifiers:
|
||||
name: Forward Auth (Istio)
|
||||
attrs:
|
||||
name: Forward Auth (Istio)
|
||||
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]]
|
||||
mode: forward_domain
|
||||
external_host: "https://auth.kube.huskypup.net"
|
||||
cookie_domain: "kube.huskypup.net"
|
||||
access_token_validity: "hours=1"
|
||||
refresh_token_validity: "days=30"
|
||||
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]]
|
||||
|
||||
# ================================================================
|
||||
# Application - Umbrella app for all forward-auth protected services
|
||||
# ================================================================
|
||||
- model: authentik_core.application
|
||||
id: forward-auth-application
|
||||
state: present
|
||||
identifiers:
|
||||
slug: forward-auth
|
||||
attrs:
|
||||
name: Protected Services (Forward Auth)
|
||||
slug: forward-auth
|
||||
policy_engine_mode: any
|
||||
provider: !KeyOf forward-auth-provider
|
||||
|
||||
# ================================================================
|
||||
# Outpost - Embedded outpost for forward auth
|
||||
# Uses Authentik's built-in outpost (no separate deployment needed)
|
||||
# ================================================================
|
||||
- model: authentik_outposts.outpost
|
||||
id: forward-auth-outpost
|
||||
state: present
|
||||
identifiers:
|
||||
name: "authentik Embedded Outpost"
|
||||
attrs:
|
||||
type: proxy
|
||||
providers:
|
||||
- !KeyOf forward-auth-provider
|
||||
config:
|
||||
authentik_host: "https://auth.kube.huskypup.net/"
|
||||
authentik_host_insecure: true
|
||||
@@ -0,0 +1,53 @@
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: authentik-blueprints-gitlab
|
||||
namespace: authentik
|
||||
labels:
|
||||
goauthentik.io/blueprint: "true"
|
||||
data:
|
||||
gitlab.yaml: |-
|
||||
# yaml-language-server: $schema=https://goauthentik.io/blueprints/schema.json
|
||||
version: 1
|
||||
metadata:
|
||||
name: gitlab-oidc
|
||||
entries:
|
||||
# OAuth2/OIDC Provider for GitLab
|
||||
- model: authentik_providers_oauth2.oauth2provider
|
||||
id: gitlab-provider
|
||||
state: present
|
||||
identifiers:
|
||||
name: GitLab
|
||||
attrs:
|
||||
name: GitLab
|
||||
client_id: 70b9da5c8166cea0ba504a869824020bce6636
|
||||
client_secret: 2e9c0c5b7a8969eb782d08bf1bf3d50ad96f8a73d9c18d1e4141816aebe14a622e8064bf5a5bce835d80e89cdc5f4cc6cf4a8c8234556647dc8884888866bd7d
|
||||
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]]
|
||||
redirect_uris:
|
||||
- url: "https://gitlab.kube.huskypup.net/users/auth/openid_connect/callback"
|
||||
matching_mode: strict
|
||||
enabled: true
|
||||
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]]
|
||||
client_type: confidential
|
||||
access_code_validity: "minutes=10"
|
||||
access_token_validity: "days=7"
|
||||
refresh_token_validity: "days=30"
|
||||
signing_key: !Find [authentik_crypto.certificatekeypair, [name, default]]
|
||||
|
||||
# Application for GitLab
|
||||
- model: authentik_core.application
|
||||
id: gitlab-application
|
||||
state: present
|
||||
identifiers:
|
||||
slug: gitlab
|
||||
attrs:
|
||||
name: GitLab
|
||||
slug: gitlab
|
||||
policy_engine_mode: any
|
||||
provider: !KeyOf gitlab-provider
|
||||
@@ -0,0 +1,60 @@
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: authentik-blueprints-gitlab-saml
|
||||
namespace: authentik
|
||||
labels:
|
||||
goauthentik.io/blueprint: "true"
|
||||
data:
|
||||
gitlab-saml.yaml: |-
|
||||
# yaml-language-server: $schema=https://goauthentik.io/blueprints/schema.json
|
||||
version: 1
|
||||
metadata:
|
||||
name: gitlab-saml
|
||||
entries:
|
||||
# SAML Provider for GitLab
|
||||
- model: authentik_providers_saml.samlprovider
|
||||
id: gitlab-saml-provider
|
||||
state: present
|
||||
identifiers:
|
||||
name: GitLab SAML
|
||||
attrs:
|
||||
name: GitLab SAML
|
||||
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]]
|
||||
|
||||
# Redirect URI from the GitLab SAML docs
|
||||
# https://gitlab.kube.huskypup.net/users/auth/saml/callback
|
||||
acs_url: "https://gitlab.kube.huskypup.net/users/auth/saml/callback"
|
||||
audience: "https://gitlab.kube.huskypup.net"
|
||||
issuer: "https://gitlab.kube.huskypup.net"
|
||||
|
||||
# SAML-specific settings
|
||||
service_provider_slo_url: "https://gitlab.kube.huskypup.net/users/auth/saml/slo"
|
||||
digest_algorithm: "http://www.w3.org/2001/04/xmlenc#sha256"
|
||||
signature_algorithm: "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"
|
||||
require_signing: true
|
||||
|
||||
# Property mappings for SAML attributes
|
||||
property_mappings:
|
||||
- !Find [authentik_providers_saml.samlpropertymapping, [managed, goauthentik.io/providers/saml/name]]
|
||||
- !Find [authentik_providers_saml.samlpropertymapping, [managed, goauthentik.io/providers/saml/email]]
|
||||
- !Find [authentik_providers_saml.samlpropertymapping, [managed, goauthentik.io/providers/saml/username]]
|
||||
|
||||
# Signing certificate
|
||||
signing_key: !Find [authentik_crypto.certificatekeypair, [name, default]]
|
||||
|
||||
# Application for GitLab SAML
|
||||
- model: authentik_core.application
|
||||
id: gitlab-saml-application
|
||||
state: present
|
||||
identifiers:
|
||||
slug: gitlab-saml
|
||||
attrs:
|
||||
name: GitLab SAML
|
||||
slug: gitlab-saml
|
||||
policy_engine_mode: any
|
||||
provider: !KeyOf gitlab-saml-provider
|
||||
launch_url: "https://gitlab.kube.huskypup.net"
|
||||
@@ -0,0 +1,99 @@
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: authentik-blueprints-grafana
|
||||
namespace: authentik
|
||||
labels:
|
||||
goauthentik.io/blueprint: "true"
|
||||
data:
|
||||
grafana.yaml: |-
|
||||
version: 1
|
||||
metadata:
|
||||
name: grafana-oidc
|
||||
entries:
|
||||
# ============================================================================
|
||||
# AUTO-CREATE GRAFANA GROUPS
|
||||
# ============================================================================
|
||||
# These groups control access levels in Grafana via OAuth role mapping:
|
||||
# - Grafana Admins → Admin role (full access)
|
||||
# - Grafana Editors → Editor role (can edit dashboards)
|
||||
# - Grafana Viewers → Viewer role (read-only)
|
||||
#
|
||||
# AUTOMATIC ADMIN ACCESS:
|
||||
# - Anyone in "authentik Admins" automatically gets Grafana Admin access
|
||||
# - No manual configuration needed!
|
||||
# ============================================================================
|
||||
|
||||
- model: authentik_core.group
|
||||
id: grafana-admins-group
|
||||
state: present
|
||||
identifiers:
|
||||
name: Grafana Admins
|
||||
attrs:
|
||||
name: Grafana Admins
|
||||
is_superuser: false
|
||||
# Note: authentik Admins are automatically granted access via role_attribute_path
|
||||
# in Grafana configuration (see grafana/values.yaml)
|
||||
|
||||
- model: authentik_core.group
|
||||
id: grafana-editors-group
|
||||
state: present
|
||||
identifiers:
|
||||
name: Grafana Editors
|
||||
attrs:
|
||||
name: Grafana Editors
|
||||
is_superuser: false
|
||||
|
||||
- model: authentik_core.group
|
||||
id: grafana-viewers-group
|
||||
state: present
|
||||
identifiers:
|
||||
name: Grafana Viewers
|
||||
attrs:
|
||||
name: Grafana Viewers
|
||||
is_superuser: false
|
||||
|
||||
# ============================================================================
|
||||
# GRAFANA OAUTH2 PROVIDER
|
||||
# ============================================================================
|
||||
|
||||
- model: authentik_providers_oauth2.oauth2provider
|
||||
id: grafana-provider
|
||||
state: present
|
||||
identifiers:
|
||||
name: Grafana
|
||||
attrs:
|
||||
name: Grafana
|
||||
client_id: bd03e9139dd2063c6c44c4d2f65f51d69de3ba0b6d6b1b9b41c255d2376d2dcc
|
||||
client_secret: 6b6f2deecfe8fd56cae9c512cc71eedd463d67ff08f24c816b15b15e78ce36bc4f06a2276c5ffe3f67799d935994a32ed32cdc02ec674f279c82d7cfe3ca05d5
|
||||
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]]
|
||||
redirect_uris:
|
||||
- url: "https://grafana.kube.huskypup.net/login/generic_oauth"
|
||||
matching_mode: strict
|
||||
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]]
|
||||
client_type: confidential
|
||||
access_code_validity: "minutes=10"
|
||||
access_token_validity: "hours=1"
|
||||
refresh_token_validity: "days=30"
|
||||
signing_key: !Find [authentik_crypto.certificatekeypair, [name, default]]
|
||||
|
||||
# ============================================================================
|
||||
# GRAFANA APPLICATION
|
||||
# ============================================================================
|
||||
|
||||
- model: authentik_core.application
|
||||
id: grafana-application
|
||||
state: present
|
||||
identifiers:
|
||||
slug: grafana
|
||||
attrs:
|
||||
name: Grafana
|
||||
slug: grafana
|
||||
policy_engine_mode: any
|
||||
provider: !KeyOf grafana-provider
|
||||
@@ -0,0 +1,83 @@
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: authentik-blueprints-guacamole
|
||||
namespace: authentik
|
||||
labels:
|
||||
goauthentik.io/blueprint: "true"
|
||||
data:
|
||||
guacamole.yaml: |-
|
||||
version: 1
|
||||
metadata:
|
||||
name: guacamole-oidc
|
||||
labels:
|
||||
blueprints.goauthentik.io/instantiate: "true"
|
||||
entries:
|
||||
# ============================================================================
|
||||
# GUACAMOLE OAUTH2 PROVIDER
|
||||
# ============================================================================
|
||||
# This creates the OAuth2 provider that Guacamole will use for authentication.
|
||||
# The client_id and client_secret must match what's configured in Guacamole.
|
||||
# ============================================================================
|
||||
|
||||
# ============================================================================
|
||||
# GROUPS SCOPE MAPPING
|
||||
# ============================================================================
|
||||
# Custom scope mapping that includes user's group names in the OIDC token.
|
||||
# ============================================================================
|
||||
|
||||
- model: authentik_providers_oauth2.scopemapping
|
||||
id: guacamole-groups-scope
|
||||
identifiers:
|
||||
managed: goauthentik.io/providers/oauth2/guacamole-groups
|
||||
attrs:
|
||||
name: "Guacamole Groups Scope"
|
||||
scope_name: groups
|
||||
expression: |
|
||||
return {
|
||||
"groups": [group.name for group in request.user.ak_groups.all()],
|
||||
}
|
||||
|
||||
- model: authentik_providers_oauth2.oauth2provider
|
||||
id: guacamole-provider
|
||||
identifiers:
|
||||
name: guacamole
|
||||
attrs:
|
||||
name: Guacamole
|
||||
client_id: a55cbe3c6d2ae30c05c86385802ffcfd76a972c22c8d039f000281d4a149fd44
|
||||
client_secret: 718d4c4816aa68767a6a0da0fa4099d492473c700ba236cbeb64d294762b9548acda7e716ba11b2ad7729d6a1c16c7890b227e3b2dcfc35fd4af1eb0d6662b0f
|
||||
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]]
|
||||
redirect_uris:
|
||||
- url: "https://guacamole.kube.huskypup.net/"
|
||||
matching_mode: strict
|
||||
- url: "https://guacamole.kube.huskypup.net/guacamole/"
|
||||
matching_mode: strict
|
||||
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]]
|
||||
- !KeyOf guacamole-groups-scope
|
||||
client_type: confidential
|
||||
access_code_validity: "minutes=10"
|
||||
access_token_validity: "hours=1"
|
||||
refresh_token_validity: "days=30"
|
||||
signing_key: !Find [authentik_crypto.certificatekeypair, [name, "Lets Encrypt K8s Cert"]]
|
||||
|
||||
# ============================================================================
|
||||
# GUACAMOLE APPLICATION
|
||||
# ============================================================================
|
||||
# This creates the application entry that users will see in Authentik.
|
||||
# ============================================================================
|
||||
|
||||
- model: authentik_core.application
|
||||
id: guacamole-application
|
||||
identifiers:
|
||||
slug: guacamole
|
||||
attrs:
|
||||
name: Guacamole
|
||||
slug: guacamole
|
||||
policy_engine_mode: any
|
||||
provider: !KeyOf guacamole-provider
|
||||
@@ -0,0 +1,68 @@
|
||||
---
|
||||
# Home Assistant OIDC Provider Blueprint for Authentik
|
||||
#
|
||||
# This blueprint creates an OAuth2/OIDC provider in Authentik for Home Assistant
|
||||
# Home Assistant will use the hass-openid custom integration for direct OIDC auth
|
||||
#
|
||||
# AUTOMATIC FEATURES:
|
||||
# - Users authenticate via Authentik OIDC
|
||||
# - User accounts auto-created in Home Assistant on first login
|
||||
# - Usernames sync from Authentik (preferred_username)
|
||||
# - No OAuth2 Proxy needed - direct integration!
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: authentik-blueprints-home-assistant
|
||||
namespace: authentik
|
||||
labels:
|
||||
goauthentik.io/blueprint: "true"
|
||||
data:
|
||||
home-assistant.yaml: |-
|
||||
version: 1
|
||||
metadata:
|
||||
name: home-assistant-oidc
|
||||
entries:
|
||||
# ============================================================================
|
||||
# HOME ASSISTANT OAUTH2 PROVIDER
|
||||
# ============================================================================
|
||||
# Manual client_id and client_secret for full automation (no random generation)
|
||||
|
||||
- model: authentik_providers_oauth2.oauth2provider
|
||||
id: home-assistant-provider
|
||||
state: present
|
||||
identifiers:
|
||||
name: Home Assistant
|
||||
attrs:
|
||||
name: Home Assistant
|
||||
client_id: ha1234567890abcdef1234567890abcdef1234567890abcdef1234567890ab
|
||||
client_secret: ha_secret_1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef12345678
|
||||
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]]
|
||||
redirect_uris:
|
||||
- url: "https://homeassistant.kube.huskypup.net/auth/openid/callback"
|
||||
matching_mode: strict
|
||||
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]]
|
||||
client_type: confidential
|
||||
access_code_validity: "minutes=10"
|
||||
access_token_validity: "hours=1"
|
||||
refresh_token_validity: "days=30"
|
||||
signing_key: !Find [authentik_crypto.certificatekeypair, [name, "authentik Internal JWT Certificate"]]
|
||||
|
||||
# ============================================================================
|
||||
# HOME ASSISTANT APPLICATION
|
||||
# ============================================================================
|
||||
|
||||
- model: authentik_core.application
|
||||
id: home-assistant-application
|
||||
state: present
|
||||
identifiers:
|
||||
slug: home-assistant
|
||||
attrs:
|
||||
name: Home Assistant
|
||||
slug: home-assistant
|
||||
policy_engine_mode: any
|
||||
provider: !KeyOf home-assistant-provider
|
||||
@@ -0,0 +1,20 @@
|
||||
apiVersion: gateway.networking.k8s.io/v1
|
||||
kind: HTTPRoute
|
||||
metadata:
|
||||
name: authentik
|
||||
namespace: authentik
|
||||
spec:
|
||||
parentRefs:
|
||||
- name: edge
|
||||
namespace: gateway
|
||||
sectionName: https
|
||||
hostnames:
|
||||
- auth.kube.huskypup.net
|
||||
rules:
|
||||
- matches:
|
||||
- path:
|
||||
type: PathPrefix
|
||||
value: /
|
||||
backendRefs:
|
||||
- name: authentik-server
|
||||
port: 80
|
||||
@@ -0,0 +1,179 @@
|
||||
# Nginx proxy that rewrites Host header for Authentik ext_authz
|
||||
#
|
||||
# Problem: Envoy's ext_authz HTTP filter forwards the ORIGINAL request's Host
|
||||
# header (e.g., prometheus.kube.huskypup.net) to Authentik. But Authentik's
|
||||
# embedded outpost only serves /outpost.goauthentik.io/auth/nginx on the
|
||||
# brand domain (auth.kube.huskypup.net), returning 404 for other hosts.
|
||||
#
|
||||
# Solution: This lightweight nginx proxy sits between Istio's ext_authz filter
|
||||
# and Authentik. It rewrites the Host header to auth.kube.huskypup.net while
|
||||
# preserving all other headers (X-Forwarded-Host, cookies, etc.) so Authentik
|
||||
# knows the original service being accessed.
|
||||
#
|
||||
# Flow:
|
||||
# 1. Client → Istio ingress gateway (Host: prometheus.kube.huskypup.net)
|
||||
# 2. ext_authz filter → this proxy (Host: prometheus.kube.huskypup.net)
|
||||
# 3. This proxy → Authentik (Host: auth.kube.huskypup.net, X-Forwarded-Host preserved)
|
||||
# 4. Authentik checks auth, returns 200 (allow) or 302 (redirect to login)
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: ext-authz-proxy-config
|
||||
namespace: authentik
|
||||
data:
|
||||
nginx.conf: |
|
||||
load_module modules/ngx_http_js_module.so;
|
||||
|
||||
worker_processes 1;
|
||||
error_log /dev/stderr warn;
|
||||
pid /tmp/nginx.pid;
|
||||
|
||||
events {
|
||||
worker_connections 256;
|
||||
}
|
||||
|
||||
http {
|
||||
access_log /dev/stdout;
|
||||
proxy_temp_path /tmp/proxy_temp;
|
||||
client_body_temp_path /tmp/client_temp;
|
||||
|
||||
js_path /etc/nginx/njs/;
|
||||
js_import cookie from cookie_domain.js;
|
||||
|
||||
server {
|
||||
listen 4180;
|
||||
|
||||
location / {
|
||||
# Rewrite all paths to the exact Authentik traefik handler path.
|
||||
# Envoy ext_authz appends the original request path to pathPrefix,
|
||||
# creating paths like /auth/traefik/ which Authentik's Go router
|
||||
# doesn't match (exact path only, no trailing slash).
|
||||
rewrite ^ /outpost.goauthentik.io/auth/traefik break;
|
||||
proxy_pass http://authentik-server.authentik.svc.cluster.local;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Host auth.kube.huskypup.net;
|
||||
proxy_set_header Connection "";
|
||||
proxy_pass_request_headers on;
|
||||
|
||||
# Add Domain=kube.huskypup.net to Set-Cookie headers from Authentik.
|
||||
# The outpost creates session cookies without Domain attribute, causing
|
||||
# browser to scope them to the original request domain (e.g., frigate.kube.huskypup.net).
|
||||
# The callback goes to auth.kube.huskypup.net, so the cookie must be domain-scoped.
|
||||
js_header_filter cookie.addDomain;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cookie_domain.js: |
|
||||
function addDomain(r) {
|
||||
var cookies = r.headersOut['Set-Cookie'];
|
||||
if (cookies) {
|
||||
if (!Array.isArray(cookies)) {
|
||||
cookies = [cookies];
|
||||
}
|
||||
var modified = cookies.map(function(c) {
|
||||
if (c.indexOf('Domain=') === -1) {
|
||||
return c + '; Domain=kube.huskypup.net';
|
||||
}
|
||||
return c;
|
||||
});
|
||||
r.headersOut['Set-Cookie'] = modified;
|
||||
}
|
||||
}
|
||||
|
||||
export default { addDomain };
|
||||
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: ext-authz-proxy
|
||||
namespace: authentik
|
||||
labels:
|
||||
app: ext-authz-proxy
|
||||
spec:
|
||||
replicas: 2
|
||||
selector:
|
||||
matchLabels:
|
||||
app: ext-authz-proxy
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: ext-authz-proxy
|
||||
spec:
|
||||
automountServiceAccountToken: false
|
||||
containers:
|
||||
- name: nginx
|
||||
image: nginx:1.27-alpine
|
||||
ports:
|
||||
- containerPort: 4180
|
||||
protocol: TCP
|
||||
volumeMounts:
|
||||
- name: config
|
||||
mountPath: /etc/nginx/nginx.conf
|
||||
subPath: nginx.conf
|
||||
readOnly: true
|
||||
- name: njs
|
||||
mountPath: /etc/nginx/njs/cookie_domain.js
|
||||
subPath: cookie_domain.js
|
||||
readOnly: true
|
||||
- name: tmp
|
||||
mountPath: /tmp
|
||||
- name: cache
|
||||
mountPath: /var/cache/nginx
|
||||
resources:
|
||||
requests:
|
||||
cpu: 10m
|
||||
memory: 32Mi
|
||||
limits:
|
||||
cpu: 50m
|
||||
memory: 64Mi
|
||||
securityContext:
|
||||
runAsNonRoot: true
|
||||
runAsUser: 10101
|
||||
runAsGroup: 10101
|
||||
allowPrivilegeEscalation: false
|
||||
readOnlyRootFilesystem: true
|
||||
capabilities:
|
||||
drop:
|
||||
- ALL
|
||||
seccompProfile:
|
||||
type: RuntimeDefault
|
||||
readinessProbe:
|
||||
tcpSocket:
|
||||
port: 4180
|
||||
initialDelaySeconds: 2
|
||||
periodSeconds: 5
|
||||
livenessProbe:
|
||||
tcpSocket:
|
||||
port: 4180
|
||||
initialDelaySeconds: 5
|
||||
periodSeconds: 10
|
||||
volumes:
|
||||
- name: config
|
||||
configMap:
|
||||
name: ext-authz-proxy-config
|
||||
- name: njs
|
||||
configMap:
|
||||
name: ext-authz-proxy-config
|
||||
- name: tmp
|
||||
emptyDir: {}
|
||||
- name: cache
|
||||
emptyDir: {}
|
||||
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: ext-authz-proxy
|
||||
namespace: authentik
|
||||
labels:
|
||||
app: ext-authz-proxy
|
||||
spec:
|
||||
selector:
|
||||
app: ext-authz-proxy
|
||||
ports:
|
||||
- port: 4180
|
||||
targetPort: 4180
|
||||
protocol: TCP
|
||||
@@ -0,0 +1,63 @@
|
||||
apiVersion: networking.istio.io/v1beta1
|
||||
kind: VirtualService
|
||||
metadata:
|
||||
name: authentik
|
||||
namespace: authentik
|
||||
spec:
|
||||
hosts:
|
||||
- auth.kube.huskypup.net
|
||||
gateways:
|
||||
- istio-system/edge
|
||||
http:
|
||||
# Allow NetBird silent auth in an iframe (prompt=none)
|
||||
- match:
|
||||
- uri:
|
||||
prefix: /application/o/authorize/
|
||||
headers:
|
||||
response:
|
||||
remove:
|
||||
- x-frame-options
|
||||
set:
|
||||
content-security-policy: "frame-ancestors https://netbird.kube.huskypup.net"
|
||||
route:
|
||||
- destination:
|
||||
host: authentik-server.authentik.svc.cluster.local
|
||||
port:
|
||||
number: 80
|
||||
|
||||
# Ensure CORS headers are present even on 401 responses
|
||||
- match:
|
||||
- uri:
|
||||
prefix: /application/o/userinfo/
|
||||
- uri:
|
||||
prefix: /application/o/token/
|
||||
headers:
|
||||
response:
|
||||
set:
|
||||
access-control-allow-origin: "https://netbird.kube.huskypup.net"
|
||||
access-control-allow-credentials: "true"
|
||||
access-control-allow-methods: "GET, POST, OPTIONS"
|
||||
access-control-allow-headers: "authorization, content-type"
|
||||
vary: "Origin"
|
||||
route:
|
||||
- destination:
|
||||
host: authentik-server.authentik.svc.cluster.local
|
||||
port:
|
||||
number: 80
|
||||
|
||||
# Forward auth endpoint for Istio ext_authz
|
||||
- match:
|
||||
- uri:
|
||||
prefix: /outpost.goauthentik.io
|
||||
route:
|
||||
- destination:
|
||||
host: authentik-server.authentik.svc.cluster.local
|
||||
port:
|
||||
number: 80
|
||||
|
||||
# All other traffic goes to Authentik
|
||||
- route:
|
||||
- destination:
|
||||
host: authentik-server.authentik.svc.cluster.local
|
||||
port:
|
||||
number: 80
|
||||
@@ -0,0 +1,36 @@
|
||||
apiVersion: batch/v1
|
||||
kind: Job
|
||||
metadata:
|
||||
name: authentik-oauth-sync
|
||||
namespace: authentik
|
||||
annotations:
|
||||
argocd.argoproj.io/hook: PostSync
|
||||
argocd.argoproj.io/hook-delete-policy: BeforeHookCreation
|
||||
argocd.argoproj.io/sync-wave: "1"
|
||||
spec:
|
||||
backoffLimit: 3
|
||||
template:
|
||||
spec:
|
||||
serviceAccountName: argocd-hook-sa
|
||||
containers:
|
||||
- name: oauth-sync
|
||||
image: bitnami/kubectl:1.31
|
||||
command:
|
||||
- /bin/bash
|
||||
- -c
|
||||
- |
|
||||
set -euo pipefail
|
||||
echo "=== Authentik PostSync - OAuth Sync ==="
|
||||
|
||||
echo "Waiting for Authentik server..."
|
||||
kubectl -n authentik rollout status deploy/authentik-server --timeout=600s
|
||||
|
||||
echo "Waiting for Authentik worker..."
|
||||
kubectl -n authentik rollout status deploy/authentik-worker --timeout=300s
|
||||
|
||||
echo "OAuth sync scripts should be run manually or via a separate automation."
|
||||
echo "Scripts are in the scripts/ directory of the Homelabv4 repo."
|
||||
echo "Run: bash scripts/sync-*-oauth.sh"
|
||||
|
||||
echo "=== Authentik PostSync Complete ==="
|
||||
restartPolicy: Never
|
||||
@@ -0,0 +1,48 @@
|
||||
apiVersion: batch/v1
|
||||
kind: Job
|
||||
metadata:
|
||||
name: authentik-presync
|
||||
namespace: authentik
|
||||
annotations:
|
||||
argocd.argoproj.io/hook: PreSync
|
||||
argocd.argoproj.io/hook-delete-policy: BeforeHookCreation
|
||||
spec:
|
||||
backoffLimit: 3
|
||||
template:
|
||||
spec:
|
||||
serviceAccountName: argocd-hook-sa
|
||||
containers:
|
||||
- name: presync
|
||||
image: bitnami/kubectl:1.31
|
||||
command:
|
||||
- /bin/bash
|
||||
- -c
|
||||
- |
|
||||
set -euo pipefail
|
||||
echo "=== Authentik PreSync ==="
|
||||
|
||||
# Wait for CNPG cluster to be ready (applied by ArgoCD as sync-wave resource)
|
||||
echo "Waiting for Authentik PostgreSQL cluster..."
|
||||
for i in $(seq 1 60); do
|
||||
PHASE=$(kubectl -n authentik get clusters.postgresql.cnpg.io pg-authentik -o jsonpath='{.status.phase}' 2>/dev/null || echo "")
|
||||
if [ "$PHASE" = "Cluster in healthy state" ] || [ "$PHASE" = "Healthy" ]; then
|
||||
echo " PostgreSQL cluster ready"
|
||||
break
|
||||
fi
|
||||
echo " waiting for pg-authentik... (attempt $i/60, phase=$PHASE)"
|
||||
sleep 5
|
||||
done
|
||||
|
||||
# Generate Authentik secret key if it doesn't exist
|
||||
if ! kubectl -n authentik get secret authentik >/dev/null 2>&1; then
|
||||
echo "Generating Authentik secret key..."
|
||||
SECRET_KEY=$(openssl rand -hex 50)
|
||||
kubectl -n authentik create secret generic authentik \
|
||||
--from-literal=AUTHENTIK_SECRET_KEY="$SECRET_KEY"
|
||||
echo " Authentik secret key generated"
|
||||
else
|
||||
echo " Authentik secret already exists"
|
||||
fi
|
||||
|
||||
echo "=== Authentik PreSync Complete ==="
|
||||
restartPolicy: Never
|
||||
@@ -0,0 +1,49 @@
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: authentik-blueprints-n8n
|
||||
namespace: authentik
|
||||
labels:
|
||||
goauthentik.io/blueprint: "true"
|
||||
data:
|
||||
n8n.yaml: |-
|
||||
version: 1
|
||||
metadata:
|
||||
name: n8n-oidc
|
||||
entries:
|
||||
- model: authentik_providers_oauth2.oauth2provider
|
||||
id: n8n-provider
|
||||
state: present
|
||||
identifiers:
|
||||
name: n8n
|
||||
attrs:
|
||||
name: n8n
|
||||
client_id: e55cbe3c6d2ae30c05c86385802ffcfd76a972c22c8d039f000281d4a149fd44
|
||||
client_secret: 718d4c4816aa68767a6a0da0fa4099d492473c700ba236cbeb64d294762b9548acda7e716ba11b2ad7729d6a1c16c7890b227e3b2dcfc35fd4af1eb0d6662b0f
|
||||
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]]
|
||||
redirect_uris:
|
||||
- url: "https://n8n.kube.huskypup.net/callback"
|
||||
matching_mode: strict
|
||||
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]]
|
||||
client_type: confidential
|
||||
access_code_validity: "minutes=10"
|
||||
access_token_validity: "hours=1"
|
||||
refresh_token_validity: "days=30"
|
||||
signing_key: !Find [authentik_crypto.certificatekeypair, [name, "authentik Self-signed Certificate"]]
|
||||
|
||||
- model: authentik_core.application
|
||||
id: n8n-application
|
||||
state: present
|
||||
identifiers:
|
||||
slug: n8n
|
||||
attrs:
|
||||
name: n8n
|
||||
slug: n8n
|
||||
policy_engine_mode: any
|
||||
provider: !KeyOf n8n-provider
|
||||
@@ -0,0 +1,93 @@
|
||||
---
|
||||
# Netbird OIDC Provider Blueprint for Authentik
|
||||
# Creates an OAuth2/OIDC provider for Netbird VPN SSO integration
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: authentik-blueprints-netbird
|
||||
namespace: authentik
|
||||
labels:
|
||||
goauthentik.io/blueprint: "true"
|
||||
data:
|
||||
netbird.yaml: |-
|
||||
version: 1
|
||||
metadata:
|
||||
name: netbird-oidc
|
||||
entries:
|
||||
- model: authentik_providers_oauth2.oauth2provider
|
||||
id: netbird-provider
|
||||
state: present
|
||||
identifiers:
|
||||
name: Netbird
|
||||
attrs:
|
||||
name: Netbird
|
||||
# NetBird dashboard uses prompt=none for silent auth; this flow avoids consent UI.
|
||||
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]]
|
||||
redirect_uris:
|
||||
- url: "https://netbird.kube.huskypup.net/.*"
|
||||
matching_mode: regex
|
||||
- url: "http://localhost:53000"
|
||||
matching_mode: strict
|
||||
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]]
|
||||
- !Find [authentik_providers_oauth2.scopemapping, [scope_name, offline_access]]
|
||||
- !Find [authentik_providers_oauth2.scopemapping, [scope_name, "goauthentik.io/api"]]
|
||||
client_type: public
|
||||
include_claims_in_id_token: true
|
||||
sub_mode: user_id
|
||||
access_code_validity: "minutes=10"
|
||||
access_token_validity: "hours=1"
|
||||
refresh_token_validity: "days=30"
|
||||
signing_key: !Find [authentik_crypto.certificatekeypair, [name, authentik Self-signed Certificate]]
|
||||
|
||||
# Create VPN User group (used for non-admin NetBird access)
|
||||
- model: authentik_core.group
|
||||
id: vpn-user-group
|
||||
state: present
|
||||
identifiers:
|
||||
name: VPN User
|
||||
attrs:
|
||||
name: VPN User
|
||||
is_superuser: false
|
||||
|
||||
- model: authentik_core.application
|
||||
id: netbird-application
|
||||
state: present
|
||||
identifiers:
|
||||
slug: netbird
|
||||
attrs:
|
||||
name: Netbird VPN
|
||||
slug: netbird
|
||||
policy_engine_mode: any
|
||||
provider: !KeyOf netbird-provider
|
||||
|
||||
# Restrict NetBird access to authentik Admins and VPN User groups
|
||||
- model: authentik_policies.policybinding
|
||||
state: present
|
||||
identifiers:
|
||||
target: !KeyOf netbird-application
|
||||
group: !Find [authentik_core.group, [name, "authentik Admins"]]
|
||||
attrs:
|
||||
target: !KeyOf netbird-application
|
||||
group: !Find [authentik_core.group, [name, "authentik Admins"]]
|
||||
enabled: true
|
||||
order: 0
|
||||
negate: false
|
||||
timeout: 30
|
||||
|
||||
- model: authentik_policies.policybinding
|
||||
state: present
|
||||
identifiers:
|
||||
target: !KeyOf netbird-application
|
||||
group: !Find [authentik_core.group, [name, "VPN User"]]
|
||||
attrs:
|
||||
target: !KeyOf netbird-application
|
||||
group: !Find [authentik_core.group, [name, "VPN User"]]
|
||||
enabled: true
|
||||
order: 1
|
||||
negate: false
|
||||
timeout: 30
|
||||
@@ -0,0 +1,52 @@
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: authentik-blueprints-nextcloud
|
||||
namespace: authentik
|
||||
labels:
|
||||
goauthentik.io/blueprint: "true"
|
||||
data:
|
||||
nextcloud.yaml: |-
|
||||
version: 1
|
||||
metadata:
|
||||
name: nextcloud-oidc
|
||||
entries:
|
||||
- model: authentik_providers_oauth2.oauth2provider
|
||||
id: nextcloud-provider
|
||||
state: present
|
||||
identifiers:
|
||||
name: Nextcloud
|
||||
attrs:
|
||||
name: Nextcloud
|
||||
client_id: HmTGnUfhCvjFFbUUAne7JLrucNC2X675JicPbEnQ
|
||||
client_secret: qTUf4NYjzUuAqfNV5D7SFPuuhJJwVltU6U3LAuJVy7dddJWeJSv2B4wKaRxbbHqpIiSfYPDaKujhEysKbOWUnf4n9OHPKJ0bu1I2EzkYtChO1Gq4gUv5EHPTzQlMBPnl
|
||||
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]]
|
||||
redirect_uris:
|
||||
- url: "https://nextcloud.kube.huskypup.net/apps/user_oidc/code"
|
||||
matching_mode: strict
|
||||
- url: "http://nextcloud.kube.huskypup.net/apps/user_oidc/code"
|
||||
matching_mode: strict
|
||||
enabled: true
|
||||
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]]
|
||||
client_type: confidential
|
||||
access_code_validity: "minutes=10"
|
||||
access_token_validity: "days=7"
|
||||
refresh_token_validity: "days=30"
|
||||
signing_key: !Find [authentik_crypto.certificatekeypair, [name, "authentik Internal JWT Certificate"]]
|
||||
|
||||
- model: authentik_core.application
|
||||
id: nextcloud-application
|
||||
state: present
|
||||
identifiers:
|
||||
slug: nextcloud
|
||||
attrs:
|
||||
name: Nextcloud
|
||||
slug: nextcloud
|
||||
policy_engine_mode: any
|
||||
provider: !KeyOf nextcloud-provider
|
||||
@@ -0,0 +1,77 @@
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: authentik-blueprints-percona-everest
|
||||
namespace: authentik
|
||||
labels:
|
||||
goauthentik.io/blueprint: "true"
|
||||
data:
|
||||
percona-everest.yaml: |-
|
||||
version: 1
|
||||
metadata:
|
||||
name: percona-everest-oidc
|
||||
labels:
|
||||
blueprints.goauthentik.io/instantiate: "true"
|
||||
entries:
|
||||
# ============================================================================
|
||||
# PERCONA EVEREST OIDC PROVIDER
|
||||
# ============================================================================
|
||||
# Everest uses OIDC with PKCE (public client) for authentication.
|
||||
# The client_id must match server.oidc.clientId in percona-everest/values.yaml.
|
||||
# ============================================================================
|
||||
|
||||
# Custom scope mapping to inject jti claim (required by Everest)
|
||||
- model: authentik_providers_oauth2.scopemapping
|
||||
id: percona-everest-jti-mapping
|
||||
state: present
|
||||
identifiers:
|
||||
managed: goauthentik.io/providers/proxy/scope-percona-everest-jti
|
||||
attrs:
|
||||
name: "Percona Everest JTI Claim"
|
||||
scope_name: "everest-jti"
|
||||
expression: |
|
||||
import uuid
|
||||
return {"jti": str(uuid.uuid4())}
|
||||
|
||||
- model: authentik_providers_oauth2.oauth2provider
|
||||
id: percona-everest-provider
|
||||
state: present
|
||||
identifiers:
|
||||
name: Percona Everest
|
||||
attrs:
|
||||
name: Percona Everest
|
||||
client_id: percona-everest-oidc-client-id-static-2025
|
||||
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]]
|
||||
redirect_uris:
|
||||
- url: "https://everest.kube.huskypup.net/login-callback"
|
||||
matching_mode: strict
|
||||
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]]
|
||||
- !KeyOf percona-everest-jti-mapping
|
||||
include_claims_in_id_token: true
|
||||
client_type: public
|
||||
access_code_validity: "minutes=10"
|
||||
access_token_validity: "hours=1"
|
||||
refresh_token_validity: "days=30"
|
||||
signing_key: !Find [authentik_crypto.certificatekeypair, [name, authentik Self-signed Certificate]]
|
||||
|
||||
# ============================================================================
|
||||
# PERCONA EVEREST APPLICATION
|
||||
# ============================================================================
|
||||
|
||||
- model: authentik_core.application
|
||||
id: percona-everest-application
|
||||
state: present
|
||||
identifiers:
|
||||
slug: percona-everest
|
||||
attrs:
|
||||
name: Percona Everest
|
||||
slug: percona-everest
|
||||
policy_engine_mode: any
|
||||
provider: !KeyOf percona-everest-provider
|
||||
meta_launch_url: "https://everest.kube.huskypup.net"
|
||||
@@ -0,0 +1,23 @@
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: authentik-blueprints-prometheus
|
||||
namespace: authentik
|
||||
labels:
|
||||
goauthentik.io/blueprint: "true"
|
||||
data:
|
||||
prometheus.yaml: |-
|
||||
version: 1
|
||||
metadata:
|
||||
name: prometheus-app
|
||||
entries:
|
||||
- model: authentik_core.application
|
||||
id: prometheus-application
|
||||
state: present
|
||||
identifiers:
|
||||
slug: prometheus
|
||||
attrs:
|
||||
name: Prometheus
|
||||
slug: prometheus
|
||||
policy_engine_mode: any
|
||||
@@ -0,0 +1,54 @@
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: authentik-blueprints-rancher
|
||||
namespace: authentik
|
||||
labels:
|
||||
goauthentik.io/blueprint: "true"
|
||||
data:
|
||||
rancher.yaml: |-
|
||||
# yaml-language-server: $schema=https://goauthentik.io/blueprints/schema.json
|
||||
version: 1
|
||||
metadata:
|
||||
name: rancher-oidc
|
||||
entries:
|
||||
- model: authentik_providers_oauth2.oauth2provider
|
||||
id: rancher-provider
|
||||
state: present
|
||||
identifiers:
|
||||
name: Rancher
|
||||
attrs:
|
||||
name: Rancher
|
||||
client_id: 94a6beeaa91d0d0407cf8af807e8208a611cf3f25ae42161e697a8dccd563449
|
||||
client_secret: 19ebd4545ba74a93c220d4471af634302c5991204cf650cabd522b0864d7617ded2c59b470ab6de7a5801e7de4c84e4b9741b983170815419c9503d55f849794
|
||||
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]]
|
||||
redirect_uris:
|
||||
- url: "https://rancher.kube.huskypup.net/verify-auth"
|
||||
matching_mode: strict
|
||||
- url: "https://rancher.kube.huskypup.net"
|
||||
matching_mode: strict
|
||||
enabled: true
|
||||
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]]
|
||||
client_type: confidential
|
||||
access_code_validity: "minutes=10"
|
||||
access_token_validity: "hours=1"
|
||||
refresh_token_validity: "days=30"
|
||||
signing_key: !Find [authentik_crypto.certificatekeypair, [name, "authentik Internal JWT Certificate"]]
|
||||
|
||||
- model: authentik_core.application
|
||||
id: rancher-application
|
||||
state: present
|
||||
identifiers:
|
||||
slug: rancher
|
||||
attrs:
|
||||
name: Rancher
|
||||
slug: rancher
|
||||
policy_engine_mode: any
|
||||
provider: !KeyOf rancher-provider
|
||||
|
||||
@@ -0,0 +1,177 @@
|
||||
# Authentik configuration
|
||||
authentik:
|
||||
secret_key: env://AUTHENTIK_SECRET_KEY
|
||||
postgresql:
|
||||
host: env://AUTHENTIK_POSTGRESQL__HOST
|
||||
port: 5432
|
||||
name: env://AUTHENTIK_POSTGRESQL__NAME
|
||||
user: env://AUTHENTIK_POSTGRESQL__USER
|
||||
password: env://AUTHENTIK_POSTGRESQL__PASSWORD
|
||||
|
||||
global:
|
||||
envFrom:
|
||||
# First secret: Authentik-specific settings (AUTHENTIK_SECRET_KEY)
|
||||
- secretRef:
|
||||
name: authentik
|
||||
# Second secret: Database credentials from CNPG
|
||||
- secretRef:
|
||||
name: pg-authentik-app
|
||||
prefix: AUTHENTIK_POSTGRESQL__
|
||||
env:
|
||||
# Configure external URL for proper OIDC discovery responses
|
||||
- name: AUTHENTIK_URL
|
||||
value: "https://auth.kube.huskypup.net"
|
||||
# Override to use the correct field names from pg-authentik-app
|
||||
- name: AUTHENTIK_POSTGRESQL__HOST
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: pg-authentik-app
|
||||
key: host
|
||||
- name: AUTHENTIK_POSTGRESQL__NAME
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: pg-authentik-app
|
||||
key: dbname
|
||||
- name: AUTHENTIK_POSTGRESQL__USER
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: pg-authentik-app
|
||||
key: username
|
||||
- name: AUTHENTIK_POSTGRESQL__PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: pg-authentik-app
|
||||
key: password
|
||||
- name: AUTHENTIK_POSTGRESQL__PORT
|
||||
value: "5432"
|
||||
|
||||
# Blueprints - Mount ConfigMaps for auto-discovery
|
||||
blueprints:
|
||||
configMaps:
|
||||
- authentik-blueprints-gitlab
|
||||
- authentik-blueprints-nextcloud
|
||||
- authentik-blueprints-argocd
|
||||
- authentik-blueprints-grafana
|
||||
- authentik-blueprints-forward-auth
|
||||
- authentik-blueprints-prometheus
|
||||
- authentik-blueprints-n8n
|
||||
- authentik-blueprints-ceph
|
||||
- authentik-blueprints-home-assistant
|
||||
- authentik-blueprints-guacamole
|
||||
- authentik-blueprints-percona-everest
|
||||
- authentik-blueprints-rancher
|
||||
- authentik-blueprints-netbird
|
||||
|
||||
# Enable Prometheus metrics
|
||||
server:
|
||||
# Single replica required: the embedded outpost stores forward-auth sessions
|
||||
# in-memory (no Redis). Multiple replicas cause callback failures because
|
||||
# the session created during ext_authz check is only on one pod.
|
||||
replicas: 1
|
||||
|
||||
containerSecurityContext:
|
||||
runAsNonRoot: true
|
||||
allowPrivilegeEscalation: false
|
||||
capabilities:
|
||||
drop:
|
||||
- ALL
|
||||
seccompProfile:
|
||||
type: RuntimeDefault
|
||||
|
||||
metrics:
|
||||
enabled: true
|
||||
serviceMonitor:
|
||||
enabled: true
|
||||
labels:
|
||||
release: prometheus
|
||||
|
||||
# Resource limits to prevent OOM
|
||||
resources:
|
||||
requests:
|
||||
cpu: 50m
|
||||
memory: 512Mi
|
||||
limits:
|
||||
memory: 1Gi
|
||||
|
||||
# Health probes - removed invalid 'enabled' fields
|
||||
startupProbe:
|
||||
initialDelaySeconds: 10
|
||||
periodSeconds: 5
|
||||
timeoutSeconds: 3
|
||||
failureThreshold: 24 # 120 seconds for Authentik startup
|
||||
|
||||
readinessProbe:
|
||||
initialDelaySeconds: 5
|
||||
periodSeconds: 5
|
||||
timeoutSeconds: 3
|
||||
failureThreshold: 2
|
||||
|
||||
livenessProbe:
|
||||
initialDelaySeconds: 10
|
||||
periodSeconds: 10
|
||||
timeoutSeconds: 5
|
||||
failureThreshold: 3
|
||||
|
||||
# Spread across nodes
|
||||
affinity:
|
||||
podAntiAffinity:
|
||||
preferredDuringSchedulingIgnoredDuringExecution:
|
||||
- weight: 100
|
||||
podAffinityTerm:
|
||||
labelSelector:
|
||||
matchLabels:
|
||||
app.kubernetes.io/name: authentik
|
||||
app.kubernetes.io/component: server
|
||||
topologyKey: kubernetes.io/hostname
|
||||
|
||||
worker:
|
||||
containerSecurityContext:
|
||||
runAsNonRoot: true
|
||||
allowPrivilegeEscalation: false
|
||||
capabilities:
|
||||
drop:
|
||||
- ALL
|
||||
seccompProfile:
|
||||
type: RuntimeDefault
|
||||
|
||||
metrics:
|
||||
enabled: true
|
||||
serviceMonitor:
|
||||
enabled: true
|
||||
labels:
|
||||
release: prometheus
|
||||
|
||||
# Resource limits to prevent OOM
|
||||
resources:
|
||||
requests:
|
||||
cpu: 50m
|
||||
memory: 512Mi
|
||||
limits:
|
||||
memory: 1Gi
|
||||
|
||||
# Spread across nodes
|
||||
affinity:
|
||||
podAntiAffinity:
|
||||
preferredDuringSchedulingIgnoredDuringExecution:
|
||||
- weight: 100
|
||||
podAffinityTerm:
|
||||
labelSelector:
|
||||
matchLabels:
|
||||
app.kubernetes.io/name: authentik
|
||||
app.kubernetes.io/component: worker
|
||||
topologyKey: kubernetes.io/hostname
|
||||
|
||||
# Mount cert-manager secret for auto-import of Let's Encrypt cert
|
||||
volumeMounts:
|
||||
- name: certs
|
||||
mountPath: /certs
|
||||
readOnly: true
|
||||
volumes:
|
||||
- name: certs
|
||||
secret:
|
||||
secretName: authentik-tls
|
||||
optional: true
|
||||
|
||||
# Disable bundled Postgres
|
||||
postgresql:
|
||||
enabled: false
|
||||
Reference in New Issue
Block a user