From 8f13fdeaf76cf273a1c4072700f127448c572525 Mon Sep 17 00:00:00 2001 From: Viktor Barzin Date: Thu, 4 Jun 2026 12:22:35 +0000 Subject: [PATCH] docs: dashboard SA cluster-read tightened to namespace-list + nodes only [ci skip] Reflect the dashboard-nav-readonly ClusterRole: namespace-owners can list namespaces/nodes (for dashboard nav) but not read other tenants' resources. Co-Authored-By: Claude Opus 4.8 --- .claude/reference/service-catalog.md | 2 +- .claude/skills/add-user/SKILL.md | 3 ++- docs/architecture/authentication.md | 3 ++- docs/architecture/multi-tenancy.md | 3 ++- 4 files changed, 7 insertions(+), 4 deletions(-) diff --git a/.claude/reference/service-catalog.md b/.claude/reference/service-catalog.md index 72d9dfd0..86016d62 100644 --- a/.claude/reference/service-catalog.md +++ b/.claude/reference/service-catalog.md @@ -30,7 +30,7 @@ ## Admin | Service | Description | Stack | |---------|-------------|-------| -| k8s-dashboard | Kubernetes dashboard at `k8s.viktorbarzin.me`. **Forward-auth + auto-injected SA token** (apiserver OIDC blocked, see design §12). nginx token-injector (`dashboard_injector.tf`) maps `X-authentik-username` → the user's `dashboard-` SA token (ns admin + cluster read-only, `rbac/.../dashboard-sa.tf`; admins → cluster-admin SA) and sets `Authorization: Bearer` → no token-paste, dashboard auto-authenticates per user. Forward-auth admits `kubernetes-*` groups for this host (`stacks/authentik/admin-services-restriction.tf`). oauth2-proxy + `k8s-dashboard` OIDC app built but idle. | k8s-dashboard | +| k8s-dashboard | Kubernetes dashboard at `k8s.viktorbarzin.me`. **Forward-auth + auto-injected SA token** (apiserver OIDC blocked, see design §12). nginx token-injector (`dashboard_injector.tf`) maps `X-authentik-username` → the user's `dashboard-` SA token (ns admin + read-only on namespace-list/nodes only via `dashboard-nav-readonly` — no cross-tenant reads, `rbac/.../dashboard-sa.tf`; admins → cluster-admin SA) and sets `Authorization: Bearer` → no token-paste, dashboard auto-authenticates per user. Forward-auth admits `kubernetes-*` groups for this host (`stacks/authentik/admin-services-restriction.tf`). oauth2-proxy + `k8s-dashboard` OIDC app built but idle. | k8s-dashboard | | reverse-proxy | Generic reverse proxy | reverse-proxy | | t3code | Multi-user coding-agent GUI at t3.viktorbarzin.me. `auth=required` (Authentik) → DevVM `t3-dispatch` service (`10.0.10.10:3780`, unprivileged user) maps `X-authentik-username` → that user's own `t3-serve@` instance (file perms enforced by uid; wizard→:3773, emo→:3774; unmapped→403) and **auto-injects the t3 session on first visit** (mints via the root `t3-mint` wrapper, scoped sudoers → `/api/auth/bootstrap` `t3_session` cookie). Source of truth `/etc/ttyd-user-map`; `t3-provision-users` reconcile (systemd timer) turns map entries into `t3-serve@` instances + `dispatch.json`. **Add a user:** one line in `/etc/ttyd-user-map` (must already be an OS account + Authentik identity) → reconcile. DevVM artifacts versioned in `infra/scripts/` (`t3-serve@.service`, `t3-provision-users`, `t3-dispatch/`, `t3-mint`, `sudoers-t3-autopair`, `t3-autoupdate.*`); TF (`stacks/t3code`) owns only the ingress + Endpoints→:3780. **t3 binary tracks `nightly`** via `t3-autoupdate` (daily systemd timer; health-check + auto-rollback on a bad build; restarts only idle instances) — so new models (e.g. Opus 4.8) land as t3 ships them. Native app/app.t3.codes unsupported (cross-origin) — deferred until published. Design: `docs/plans/2026-06-01-t3-auto-provision-*`. | t3code | diff --git a/.claude/skills/add-user/SKILL.md b/.claude/skills/add-user/SKILL.md index 28d1e5b0..e88859af 100644 --- a/.claude/skills/add-user/SKILL.md +++ b/.claude/skills/add-user/SKILL.md @@ -182,7 +182,8 @@ auto-creates a `dashboard-` SA + token for every namespace-owner (`dashboard-sa.tf`), and the **k8s-dashboard** stack's token-injector maps the user's Authentik identity → that token (`dashboard_injector.tf`, auto-derived from `k8s_users`). The new user just logs into `https://k8s.viktorbarzin.me` and -lands in the dashboard scoped to their namespace (`admin` + cluster read-only). +lands in the dashboard scoped to their namespace (`admin` on their namespace + +read-only on the namespace list & nodes for nav — no cross-tenant resource reads). > **Apply order for a new namespace-owner:** after the vault/rbac/woodpecker > applies above, ALSO `cd stacks/k8s-dashboard && ../../scripts/tg apply` so the diff --git a/docs/architecture/authentication.md b/docs/architecture/authentication.md index 7f6fe7b6..e87b586f 100644 --- a/docs/architecture/authentication.md +++ b/docs/architecture/authentication.md @@ -136,7 +136,8 @@ Because OIDC SSO is blocked, the web dashboard at `k8s.viktorbarzin.me` uses a that maps `X-authentik-username` → that user's ServiceAccount token and sets `Authorization: Bearer` before proxying to kong-proxy, so the dashboard auto-authenticates. Namespace-owners → `dashboard-` SA (admin on their - namespace + cluster read-only, `stacks/rbac/modules/rbac/dashboard-sa.tf`), + namespace + read-only on the namespace list & nodes only (dashboard-nav-readonly, + NOT cross-tenant resource reads); `stacks/rbac/modules/rbac/dashboard-sa.tf`), auto-derived from `k8s_users`. Admins → the cluster-admin `kubernetes-dashboard` SA token (admin identities listed explicitly in `dashboard_injector.tf`, since their Authentik login email ≠ their `k8s_users` email). diff --git a/docs/architecture/multi-tenancy.md b/docs/architecture/multi-tenancy.md index 3d84460d..58238122 100644 --- a/docs/architecture/multi-tenancy.md +++ b/docs/architecture/multi-tenancy.md @@ -177,7 +177,8 @@ Namespace-owners just log into `https://k8s.viktorbarzin.me` with their Authenti account and land straight in the dashboard scoped to their namespace — **no token to paste**. A token-injector (`stacks/k8s-dashboard/dashboard_injector.tf`) maps their Authentik identity (`X-authentik-username`) to their `dashboard-` SA -token (`admin` on their namespace + cluster read-only) and injects it as +token (`admin` on their namespace + read-only on the namespace list & nodes +only — they can't read other tenants' resources) and injects it as `Authorization: Bearer`. Forward-auth admits the `kubernetes-*` groups for this host (`stacks/authentik/admin-services-restriction.tf`).