From e4c3fbbbbbfd2b097cef920ff21a22f547698397 Mon Sep 17 00:00:00 2001 From: Viktor Barzin Date: Thu, 4 Jun 2026 07:46:09 +0000 Subject: [PATCH] feat(authentik): adopt admin-services-restriction policy; admit kubernetes-* groups to k8s dashboard MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Namespace-owners (e.g. gheorghe) were blocked at forward-auth — k8s.viktorbarzin.me was Home-Server-Admins-only. Carve-out: the dashboard host now also admits kubernetes-admins/power-users/namespace-owners so they can reach the login page; per-namespace access is still enforced by the pasted SA token (dashboard-sa.tf). All other admin-only hosts unchanged. Policy adopted from UI into TF via import. Co-Authored-By: Claude Opus 4.8 --- .../authentik/admin-services-restriction.tf | 64 +++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 stacks/authentik/admin-services-restriction.tf diff --git a/stacks/authentik/admin-services-restriction.tf b/stacks/authentik/admin-services-restriction.tf new file mode 100644 index 00000000..e17c8d06 --- /dev/null +++ b/stacks/authentik/admin-services-restriction.tf @@ -0,0 +1,64 @@ +# Catch-all forward-auth restriction: gate the admin-only hostnames to the +# "Home Server Admins" group. Bound to the "Domain wide catch all" application +# (binding stays UI-managed; only the expression is adopted here). +# +# Adopted into Terraform 2026-06-04 to add a carve-out: the Kubernetes Dashboard +# (k8s.viktorbarzin.me) ALSO admits the kubernetes-* RBAC groups, so +# namespace-owners (e.g. gheorghe) can reach the dashboard login page. The +# dashboard itself enforces per-namespace access via the pasted ServiceAccount +# token (stacks/rbac/modules/rbac/dashboard-sa.tf) — this policy only controls +# who reaches the page. All other admin-only hosts remain Home-Server-Admins-only. +import { + to = authentik_policy_expression.admin_services_restriction + id = "07a11b85-8f37-4844-aebb-ac9c112ec87c" +} + +resource "authentik_policy_expression" "admin_services_restriction" { + name = "admin-services-restriction" + expression = trimspace(<<-EOT + ADMIN_ONLY_HOSTS = { + "terminal.viktorbarzin.me", + "frigate.viktorbarzin.me", + "netbox.viktorbarzin.me", + "trading.viktorbarzin.me", + "speedtest.viktorbarzin.me", + "meshcentral.viktorbarzin.me", + "k8s.viktorbarzin.me", + "dashy.viktorbarzin.me", + "prowlarr.viktorbarzin.me", + "qbittorrent.viktorbarzin.me", + "listenarr.viktorbarzin.me", + "shlink.viktorbarzin.me", + "openclaw.viktorbarzin.me", + "openlobster.viktorbarzin.me", + "wealthfolio.viktorbarzin.me", + } + + ADMIN_GROUP = "Home Server Admins" + + # The K8s Dashboard additionally admits the Kubernetes RBAC groups. Access + # to the page is not the security boundary — the pasted ServiceAccount token + # is (per-namespace admin + cluster read-only). See dashboard-sa.tf. + K8S_DASHBOARD_HOST = "k8s.viktorbarzin.me" + K8S_DASHBOARD_GROUPS = [ + "Home Server Admins", + "kubernetes-admins", + "kubernetes-power-users", + "kubernetes-namespace-owners", + ] + + host = request.context.get("host", "") + + # Not an admin-only host: allow any authenticated user. + if host not in ADMIN_ONLY_HOSTS: + return True + + # K8s Dashboard: allow admins OR any Kubernetes RBAC group. + if host == K8S_DASHBOARD_HOST: + return any(ak_is_group_member(request.user, name=g) for g in K8S_DASHBOARD_GROUPS) + + # Every other admin-only host: Home Server Admins only. + return ak_is_group_member(request.user, name=ADMIN_GROUP) + EOT + ) +}