Skip to main content

How to sudo in Kubernetes

Kubernetes provides two options to escalate permissions temporarily: impersonation headings and the impersonate verb.
Image
Unlocked padlock on a yellow container

Photo by iMattSmart on Unsplash

It's a well-known best practice that IT professionals should use unprivileged user accounts on any system they work on regularly and escalate their privileges only when required. Doing everyday tasks with "superuser" or "administrator" permissions creates the possibility that simple mistakes cause serious damage and risk inadvertently running malware.

Linux sysadmins are used to the sudo command to escalate to root permissions for a single command while logged in as an unprivileged user. When these system administrators become Kubernetes cluster administrators or platform operators, they are uncomfortable using OAuth credentials or a kubeconfig file that grants them unrestricted access to a cluster for performing everyday tasks such as creating a pod.

[ Download now: Advanced Linux commands cheat sheet. ]

Kubernetes does not provide a feature similar to the Linux sudo utility. Instead, it offers two features that allow a user to impersonate another user to perform Kubernetes API requests: impersonation headings and the impersonate verb.

Example scenario with developer and administrator users

My test cluster recognizes two users: admin (a cluster administrator) and developer (has access to namespaces previously created and authorized by a cluster administrator).

That type of setup, which includes multiple users with different access levels, is easy to create with OpenShift but not so easy with vanilla Kubernetes, which leads many Kubernetes users to the bad habit of working all the time with full cluster administrator privileges. Fortunately, the Kube By Example website provides a guided exercise and sample scripts that you can use to create such a setup using minikube. It should not be hard to adapt to other flavors of Kubernetes.

If I log in as developer, I do not have access to cluster-level API resources such as the list of nodes. You can check which user you're currently authenticated as by using the kubectl config command. The user name is the final path component of the current context:

$ kubectl config current-context
dev/api-ocp4-example-com:6443/developer

$ kubectl get node
Error from server (Forbidden): nodes is forbidden: User "developer" cannot list resource "nodes" in API group "" at the cluster scope

If I log in as admin, I have unrestricted access to all API resources in my cluster:

$ kubectl config current-context
dev/api-ocp4-example-com:6443/admin

$ kubectl get node
NAME   	STATUS   ROLES       	AGE   VERSION
master01   Ready	master,worker   32d   v1.24.0+b62823b

My cluster also contains the dev namespace, and the developer user has the "edit" role on it, which should be sufficient to create pods, deployments, secrets, and other common application resources.

[ Learn Kubernetes basics; download the cheat sheet. ]

The following example creates a pod that displays the current time and immediately deletes the pod. The purpose is to check that the developer user can perform development tasks on my test cluster:

$ kubectl config current-context
dev1/api-ocp4-example-com:6443/developer

$ kubectl run now -it --rm --restart Never --image registry.access.redhat.com/ubi9/ubi -- /bin/bash -c date
Wed Dec  7 22:37:46 UTC 2022
pod "now" deleted

To keep this article independent of Kubernetes flavors, I'm not detailing how you authenticate as each user. You could use different kubeconfig files and set the KUBECONFIG variable for each user, or you could use vendor extensions such as the oc login command from OpenShift.

Run commands as a regular user, logged in as an administrator

All Kubernetes API requests accept a series of impersonation headers that enable invoking a request authenticating as one user but authorizing it as a different user. The kubectl command (and, of course, the OpenShift oc command) includes these headers if you specify the --as or --as-group options.

Using these impersonation headers requires special privileges that a regular user would not have by default, so I'll start by showing how a cluster administrator would impersonate a regular user:

$ kubectl config current-context
dev/api-ocp4-example-com:6443/admin

$ kubectl run now -it --rm --restart Never --image registry.access.redhat.com/ubi9/ubi --as developer -- /bin/bash -c date
Wed Dec  7 22:42:48 UTC 2022
pod "now" deleted

$ kubectl get node --as developer
Error from server (Forbidden): nodes is forbidden: User "developer" cannot list resource "nodes" in API group "" at the cluster scope

Notice in the previous output that the admin user can create pods as the developer user but cannot list cluster nodes. And it can create pods only on namespaces that the developer user has access to:

$ kubectl run now -it --rm --restart Never --image registry.access.redhat.com/ubi9/ubi -n default --as developer -- /bin/bash -c date
Error from server (Forbidden): pods is forbidden: User "developer" cannot create resource "pods" in API group "" in the namespace "default"

While impersonating a regular user might prove useful to check that you configured your namespaces with the correct role bindings for your cluster users, it's the opposite of the promise of the title of this article. Stay tuned.

[ Find everything you need to know about Kubernetes. ]

Run commands as an administrator, logged in as a regular user

As you would expect, a regular user cannot impersonate an administrator or any other user:

$ kubectl config current-context
dev1/api-ocp4-example-com:6443/developer

$ kubectl get node --as admin
Error from server (Forbidden): users "admin" is forbidden: User "developer" cannot impersonate resource "users" in API group "" at the cluster scope

You need a custom role to allow a user to impersonate another user. The following sudo-role.yaml file defines a cluster role that allows anyone to impersonate the admin user, which on my test cluster has cluster administrator privileges, and also a cluster role binding that grants that role to the developer user:

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: sudo-admin
rules:
- apiGroups: [""]
  resources: ["users"]
  verbs: ["impersonate"]
  resourceNames: ["admin"]

Here is the related sudo-role-binding.yaml file:

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: sudo-admin-to-developer
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: sudo-admin
subjects:
- apiGroup: rbac.authorization.k8s.io
  kind: User
  name: developer

That cluster role binding may feel odd to you, and you have a good reason for that feeling: There is no "user" API resource type in Kubernetes. The Kubernetes role-based access control (RBAC) controller uses the resource type in the role as the type of subject to match. It could match not only users and groups but also service accounts, user IDs, and other types of entities that your authentication provider might support.

As a cluster administrator, create the cluster role and the cluster role binding:

$ kubectl config current-context
dev/api-ocp4-example-com:6443/admin

$ oc create -f sudo-role.yaml
clusterrole.rbac.authorization.k8s.io/sudo-admin created

$ oc create -f sudo-role-binding.yaml
clusterrolebinding.rbac.authorization.k8s.io/sudo-admin-to-developer created

And switch to the developer user to check that it can now impersonate the admin user:

$ kubectl config current-context
dev1/api-ocp4-example-com:6443/developer

$ kubectl get node --as admin
NAME   	STATUS   ROLES       	AGE   VERSION
master01   Ready	master,worker   32d   v1.24.0+b62823b

Wrap up

If your cluster has a predefined cluster administrator user, such as the system:admin user from OpenShift, you could use that name instead of admin. You would lose no auditability because all Kubernetes API requests are still authenticated as the developer user, no matter which user is being impersonated.

And what if you wish to grant something more than "regular developer" permissions but still less than a full cluster administrator? Just use regular Kubernetes RBAC to create a role that gives only the privileges you wish and assign that role to a user or group. Then create another role to impersonate the user or group with that particular role.

[ Want to test your sysadmin skills? Take a skills assessment today. ]

Topics:   Kubernetes   Security  
Author’s photo

Fernando Lozano

Fernando works on Red Hat's certification training for OpenShift, containers, and DevOps. More about me

Try Red Hat Enterprise Linux

Download it at no charge from the Red Hat Developer program.