Role recipes¶
The six system roles cover most of a team's week. Four needs come up often and fall between them: a developer who writes Secrets, a bot that deploys with Helm, third-party custom resources, and kubectl debug in a namespace with Pod Security. Here is the role for each, what it doesn't give, and what stays with cluster-admin.
The recipes name capabilities by identifier, which Search capabilities in the builder also finds. How to build and grant a role is in Manage roles; what each capability allows and what kubelatch always refuses, in Roles. Custom roles are a Pro feature; where Free has a way, each recipe says so.
A developer who also writes Secrets¶
When: someone with developer creates or updates their application's Secrets (kubectl create secret, or a kubectl apply that carries one). developer doesn't write Secrets, and secrets-reader only reads them.
The role: in the builder, Start from developer and add:
secrets.write, to create, change and delete them;secrets.read, becausekubectl applyandkubectl editread the object before writing it.
The copy keeps the capabilities developer shows, namespace.read included, but not the CRDs labelled for the tier on each cluster (Duplicate a role).
Keep Namespaces under Where it applies. The role is Sensitive, and Look twice says why: "Writing Secrets can replace the credentials other workloads use." It requires Pod Security, as developer does.
What it adds: little that the person couldn't reach already. Whoever deploys pods in a namespace can mount its Secrets (The namespace is the boundary). What's new is overwriting a Secret that another workload reads. A viewer of the namespace sees no Secret, but reads every ConfigMap whole, values included: a credential belongs in a Secret even when a ConfigMap would be easier to write.
In Free: the system role that writes Secrets is admin.
A bot that deploys with Helm¶
When: a CI bot (Users and bots, CI: trust rules) runs helm upgrade --install in its namespace.
Helm keeps each release in a Secret of that namespace, so the bot needs to read and write Secrets as well as whatever the chart holds. Two ways:
adminon its namespace. Kubernetes'adminrole covers what a chart usually puts in a namespace, its Roles and RoleBindings included. The cost: the bot can bind roles inside the namespace. It requires Pod Security.-
A custom role, when the chart brings no RBAC: writing Roles and RoleBindings is always refused in a custom role. Tick the write capabilities for what the chart holds, and the read capability each one presumes (the builder offers to add it):
Write Read secrets.write(Helm's releases, and the chart's Secrets)secrets.readconfig.writeconfig.readworkloads.deployworkloads.readnetwork.writenetwork.readstorage.writestorage.readpolicy.write(PodDisruptionBudgets)namespace.readnetworkpolicies.writenetwork.readautoscaling.write, if the chart has HorizontalPodAutoscalersworkloads.readA ServiceAccount in the chart needs an advanced rule: core group,
serviceaccounts, Read and Write (Helm reads every object before creating or upgrading it). The role is Sensitive and requires Pod Security.
HELM_DRIVER=configmap isn't the answer, though for a chart without Secrets it would fit in developer: the release then lives in a ConfigMap, and any viewer of the namespace reads it, with the rendered manifest and the chart's Secrets in it.
What neither gives: anything outside the namespace. A chart that installs CRDs or ClusterRoles is a platform install. --create-namespace fails too, since neither role creates namespaces: create the namespace beforehand, with its Pod Security label, and grant the bot on it.
Third-party custom resources¶
When: the people deploying a namespace also create the resources of an operator installed in the cluster: a cert-manager Certificate, a KEDA ScaledObject, an Argo Rollouts Rollout. There's no capability for custom resources. Two ways:
-
A labelled ClusterRole on the cluster, which works in Free: a ClusterRole with the label
kubelatch.io/aggregate-to-developer: "true"adds its rules todeveloperon that cluster, for everyone who holds it there (Add CRDs to a tier):apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: certificates-developer labels: kubelatch.io/aggregate-to-developer: "true" rules: - apiGroups: ["cert-manager.io"] resources: ["certificates"] verbs: ["get", "list", "watch", "create", "update", "patch", "delete"] -
An advanced rule in a custom role (Pro), for some people only: API group
cert-manager.io, Resourcescertificates, Verbs Read and Write. A group outside Kubernetes marks the role Sensitive. A custom role doesn't pick up labelled ClusterRoles, so the rule is the only way into it.
The caveat: kubelatch doesn't know what a custom resource does. Creating an Argo Workflow runs code, because its controller creates the pods: a rule that writes it is a permission to deploy. kubelatch can't tell that it needs Pod Security (What kubelatch can't know), so grant it only on namespaces that enforce it. Through the label it's never an issue: developer already requires it.
kubectl debug under Pod Security¶
When: someone with debugger adds a debugging container to a running pod, and the namespace enforces Pod Security baseline or restricted, as it must for debugger to be granted there (Pod Security Admission).
The role: debugger as it is. What fails is the debugging container: kubectl's default profile, general, gives it the SYS_PTRACE capability, which baseline refuses. Ask for a profile the namespace admits:
kubectl debug -it web-7f9c --image=busybox --target=app --profile=baseline
In a restricted namespace, use --profile=restricted, with an image that doesn't run as root.
What it doesn't give: SYS_PTRACE, so no strace or gdb on the target's processes. kubectl debug --copy-to creates a new pod, which is developer, not debugger. Debugging a node (kubectl debug node/…) runs a pod in the node's namespaces with its filesystem mounted, which Pod Security refuses wherever debugger can be granted: it stays with cluster-admin.
What stays with cluster-admin¶
kubectl cordon, uncordon and drain, taints and node labels, creating namespaces and approving certificate requests have no system role or capability: they act on the whole cluster, and a custom role granted to a whole cluster only reads. Writing namespaces and approving certificates are always refused. For them there's cluster-admin, with its 8 h and its audit (Grant emergency access with cluster-admin); namespaces are better created by whatever provisions the platform. Reading the cluster is different: a custom role granted to a whole cluster can carry nodes.read and cluster.inspect.
Before deciding that people need a node role, count the refusals they really hit: in Audit, the Denied result filtered by Verb and Resource (nodes, for example) says which 403s come up, and how often (Search cluster requests).