feat(k8s-dashboard): auto-inject per-user SA token (no token-paste)

nginx token-injector behind the existing forward-auth: maps X-authentik-username
(the user's email, injected by Authentik) -> that user's ServiceAccount token ->
sets Authorization: Bearer -> kong-proxy. Dashboard auto-authenticates; users
never see the token prompt. Mirrors the t3-dispatch pattern. Token map lives in a
Secret (namespace-owners' cluster-read covers configmaps, not secrets). Verified:
gheorghe->vabbit81 pods 200 + kube-system 200 (cluster-read); viktor->nodes 200
(admin); unmapped->401. namespace-owners auto-derived from k8s_users; admins
hardcoded (their Authentik identity != k8s_users email).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Viktor Barzin 2026-06-04 08:04:23 +00:00
parent 467eb7d7ee
commit d649f4f287
2 changed files with 195 additions and 5 deletions

View file

@ -91,15 +91,19 @@ resource "helm_release" "kubernetes-dashboard" {
module "ingress" {
source = "../../modules/kubernetes/ingress_factory"
namespace = kubernetes_namespace.k8s-dashboard.metadata[0].name
name = "kubernetes-dashboard"
service_name = "kubernetes-dashboard-kong-proxy"
namespace = kubernetes_namespace.k8s-dashboard.metadata[0].name
name = "kubernetes-dashboard"
# Route through the token-injector: Authentik forward-auth (auth=required) gates
# access AND injects X-authentik-username; the injector maps that to the user's
# ServiceAccount token and sets Authorization: Bearer so the dashboard skips its
# token-paste login. See dashboard_injector.tf.
service_name = "dashboard-token-injector"
host = "k8s"
dns_type = "proxied"
tls_secret_name = var.tls_secret_name
auth = "required"
backend_protocol = "HTTPS"
port = 443
backend_protocol = "HTTP"
port = 80
extra_annotations = {
"gethomepage.dev/enabled" = "true"
"gethomepage.dev/name" = "Kubernetes Dashboard"