Per-role Kubernetes Access (kube_spec)
By default, anyone with pc kube access to a cluster gets the cluster-wide
read tier (and exec if their role grants kubernetes:execute). A role's
kube_spec narrows that down — confining a role to specific namespaces,
resources, and verbs, with allow/deny rules. This is how you give one team
read-only access to acme-* namespaces while another gets exec into globex-*.
kube_spec is enforced at the in-cluster agent: an out-of-scope request gets a
Kubernetes 403 Forbidden before it reaches the apiserver (and an exec/attach
is denied before any stream opens). Deny always wins.
Authoring a kube_spec in the role editor
Open Settings → Roles, edit a role, and go to the Resources tab:
- Click
+ Add Resource Access→ Kubernetes Access. A collapsible Kubernetes Access block appears (alongside Server Access, if present). - Fill in the Allow (green) and, optionally, Deny (red) sections.
- Save. (System roles are read-only here; edit a custom role instead.)
Each side (Allow / Deny) has these fields:
| Field | Meaning |
|---|---|
| Kubernetes groups | The impersonation tier(s) — a multi-select dropdown of the operator allowlist (PROXIMA_KUBE_ALLOWED_GROUPS, default proxima:kube-readonly / proxima:kube-exec). Verbs are ultimately governed by k8s RBAC via these groups. A custom group appears in the dropdown once an operator adds it. |
| Kubernetes users | Trait templates for the impersonated audit identity (e.g. {{.email}}). Usually leave empty — the caller's email is used by default. |
| Namespaces | Globs the caller may act in (acme-*, default, *). Empty ⇒ no namespaced access. A request with no namespace (cluster-wide kubectl get pods -A) requires *. |
| Cluster labels | Restrict this rule to clusters whose synthesized labels match (env=prod, region=…). Empty ⇒ all clusters the caller can reach. |
| Resource rules | Per {kind, namespace, verbs}: e.g. allow pods get/list/watch but not secrets. kind is free text (CRDs allowed); verbs are a checkbox set (* = all). When empty, resources are governed by the groups (k8s RBAC) only — the v1 behavior. |
YAML mode. The role editor's
</>toggle shows the raw role, includingkube_spec, if you prefer to edit it as JSON.
Allow vs Deny
The effective access is (union of all allow rules) − (union of all deny rules).
Deny always overrides allow — allow: { namespaces: ["*"] } with
deny: { namespaces: ["kube-system"] } grants every namespace except
kube-system. A request must match an allow rule and no deny rule.
The v1 default (no kube_spec)
A role with no kube_spec keeps the original behavior: the read/exec tier
(per kubernetes:read / kubernetes:execute) across all namespaces. So you
can roll out kube_spec role-by-role without a flag day — unscoped roles are
unaffected.
Custom impersonation groups
The Allow/Deny Kubernetes groups field is limited to the operator-configured
allowlist. To use a group beyond proxima:kube-readonly / proxima:kube-exec, an
operator must add it in two places (a closed allowlist on both ends):
- The agent Helm chart value
kubeAccess.impersonateGroups(drives the impersonateClusterRole'sresourceNames— the hard backstop on which groups the agent may ever assert). - The backend env
PROXIMA_KUBE_ALLOWED_GROUPS(the role-authoring validation allowlist).
If a group is missing from either, it can't be used: the role editor rejects it, or
the apiserver 403s the impersonation.
Example
# Acme Engineer — read + exec within acme-* namespaces, never secrets.
kube_spec:
allow:
kubernetes_groups: ["proxima:kube-readonly", "proxima:kube-exec"]
namespaces: ["acme-*"]
deny:
kubernetes_resources:
- kind: secrets
verbs: ["*"]
See also: Overview · Security Model.