Skip to content

System roles

A kubelatch permission is always the combination of a subject, a cluster, a role and a scope. The six system roles, also called tiers, come with kubelatch: they can't be edited, and all but admin and cluster-admin can be duplicated into a custom role. Here you see what each tier allows, where it can be granted, what it requires and, above all, what it can't guarantee. Roles an administrator composes are in Roles.

The six system roles

Tier What it allows Scope Requires PSA
viewer Read access to what Kubernetes' view role includes: pods, pods/log, workloads, services, configmaps… without secrets; plus the CPU and memory pods use (metrics.k8s.io, what kubectl top pods reads). With * scope, also read access to nodes and their usage, namespaces, persistentvolumes, storageclasses and CRDs. namespace or * No
developer Everything in viewer plus creating, modifying and deleting deployments, statefulsets, daemonsets, replicasets, jobs, cronjobs, pods, configmaps, services, persistentvolumeclaims, ingresses and horizontalpodautoscalers, and scaling deployments, statefulsets and replicasets. namespace Yes
debugger Add-on: exec, attach and port-forward into pods, adding ephemeral containers, and reading pods and their logs. namespace Yes
secrets-reader Add-on: read access (get, list, watch) to secrets. namespace No
admin Kubernetes' admin role in the namespace. namespace Yes
cluster-admin Kubernetes' cluster-admin role across the whole cluster. Expiry required, 8 h maximum. * No

A subject can have several permissions on the same cluster. It's common to combine them: developer on apps plus debugger on apps for someone who needs to get into their pods.

Which tier covers which

Some tiers include others whole. On the same cluster and scope, a permission with the one on the left makes a permission with the ones on the right redundant:

Tier Covers
developer viewer
admin developer, viewer
cluster-admin admin, developer, viewer
viewer, debugger, secrets-reader nothing

debugger and secrets-reader are add-ons: nothing includes them and they include nothing. A custom role declares nothing either way. Every list of permissions uses this table to flag a redundant permission, for example viewer next to developer for the same account on the same namespace (Overlaps). Nothing is revoked on its own: a redundant permission gives nothing more, and it may outlast the one that covers it.

What developer leaves out, and why

developer is not Kubernetes' edit role. edit includes secrets, pods/exec and serviceaccounts/token, which are exactly what a day-to-day working permission shouldn't grant without thinking about it. developer does not have:

  • secrets, serviceaccounts or serviceaccounts/token;
  • the exec, attach, portforward, proxy and ephemeralcontainers subresources of pods;
  • roles, rolebindings, resourcequotas or limitranges.

Those capabilities are split into separate tiers (debugger, secrets-reader, admin) so granting them is an explicit, audited decision.

The namespace is the boundary

Kubernetes says so in its own documentation: the boundaries within a namespace are weak. kubelatch can't change that, and it's worth understanding before granting anything.

Whoever can create pods in a namespace can mount any Secret in that namespace and use any ServiceAccount in that namespace, with its permissions. So:

  • Whoever has developer on a namespace reaches its Secrets and its ServiceAccounts, even though the tier doesn't include secrets. All it takes is deploying a pod that mounts them.
  • secrets-reader and debugger are conveniences, not boundaries. They save you from deploying a pod to read a Secret or to get a shell into another pod, but they don't protect anything developer doesn't already reach.
  • ServiceAccount tokens obtained from a pod don't go through kubelatch. Whatever is done with them ends up in the cluster's native audit log, not kubelatch's. So it's worth keeping that native audit log active with the provider.

The practical consequence: grant developer, debugger and admin only on namespaces whose contents that person may see and touch. Whatever you want kept separate between teams, separate into different namespaces.

Pod Security Admission

Without Pod Security Admission, whoever can create pods can create a privileged one that mounts the node's disk, and from the node reaches the whole cluster. An ephemeral container added with debugger can do the same.

That's why developer, debugger and admin require the namespace to have the pod-security.kubernetes.io/enforce label set to baseline or restricted. kubelatch checks this when granting the permission, by reading the namespace on the cluster.

KUBELATCH_REQUIRE_PSA=false disables the check, and kubelatch warns about it at the top of Permissions and under Notices, the bell in the top bar. It only makes sense if another tool (OPA, Kyverno) enforces the same thing.

Protected namespaces

kube-system, kube-public, kube-node-lease and kubelatch-system don't accept permissions of any role, system or custom. KUBELATCH_PROTECTED_NAMESPACES adds others to the list. Whatever needs doing there is done with native admin access, outside kubelatch.

Allowed scopes

  • * (the whole cluster) is only allowed with viewer and cluster-admin.
  • cluster-admin is only allowed with *.
  • All other tiers can only be granted on a namespace, which must exist on that cluster at the moment of granting.
  • A custom role can be granted on a namespace, and with * only if it can be granted to a whole cluster (Roles).

viewer with * also sees the logs of every namespace, and logs can contain secrets. Grant it knowing that.

cluster-admin as audited emergency access

cluster-admin gives full control of the cluster. kubelatch treats it as emergency access: it requires an expiry date and doesn't allow more than 8 h. Who granted it and to whom is recorded, and every request made with it ends up in the audit log. It's the preferred route for an urgent intervention while kubelatch is running.

How it's materialized on the cluster

The reconciler translates active permissions into standard RBAC on each cluster:

Scope Object it creates Points to Binding subject
Namespace RoleBinding kubelatch-<tier> in that namespace ClusterRole for the tier Group kubelatch:ns:<namespace>:<tier>
* ClusterRoleBinding kubelatch-<tier>-cluster ClusterRole for the tier Group kubelatch:cluster:<tier>

Bindings never name people: they name groups. The proxy uses impersonation to act as each person with the groups from their active permissions, and the API server applies the bindings for those groups (see The journey of a request).

viewer, developer, debugger and secrets-reader are their own aggregated ClusterRoles (kubelatch-<tier>): their rules come from a base ClusterRole (kubelatch-<tier>-base) and from any other ClusterRole with the label kubelatch.io/aggregate-to-<tier>: "true". viewer also collects everything labeled for the standard view role, and developer collects everything from viewer. admin and cluster-admin point directly to the Kubernetes roles of the same name.

To extend a tier with a CRD, create a small ClusterRole with that label on the cluster; kubelatch picks it up without any change on its side.

A binding exists as long as at least one enabled subject has an active permission with that tier and that scope. The reconciler creates it when granted, deletes it when it's no longer needed, and removes expired permissions' bindings in its periodic pass. The proxy stops sending an expired permission's group instantly, without waiting for that pass.

Optional hardening

The chart ships a ValidatingAdmissionPolicy that reserves bindings to kubelatch-* ClusterRoles for the reconciler, so nobody can hand-create one. See Security model.