Kubernetes RBAC: Asking for Forgiveness or Getting Permission
This blog is dedicated to my Mum. She was a leading psychiatrist who loved learning and traveling. She was a huge inspiration to me. I think she would be proud that I’m pursuing my passion of traveling around the world teaching what I love.
I want to start with a quote attributed to another inspiring woman, Grace Hopper, the founder of computer languages, who said "It is often easier to ask for forgiveness than it is to get permission."
If we explore Grace’s quote in the context of Kubernetes, we will end up with an interesting spin on her words. Wait until the end of the blog to find out! Resist the urge to scroll down. As we’ll see, there are often advantages in fighting our human nature.
Meanwhile, let’s consider permissions in the context of both Linux and Kubernetes.
Permissions in Linux vs. Kubernetes
In Linux, pretty much everything is a file.
It is simple to assign roles and define privileges in Linux. Each Linux file has an owner, a group, and a set of permission flags that tell us who is permitted to read, write, or execute that file. This ownership and permission information is defined as attributes of the file itself, with no additional objects required.
Here is an example of a file in Linux where you can see permissions, owners, and groups.
In Kubernetes, everything is a resource – pods, nodes, services, service accounts, and all the rest. But these resources don’t have ownership or permission attributes. Instead, there are additional levels of abstraction:
- A Role defines rules that specify a set of resources and a set of verbs, which are actions that can be taken on those objects. But they say nothing about who can perform those actions on those objects.
- A RoleBinding links a role to an identity. This might be a user, a group, or a service account. This adds the “who” part.
Roles and RoleBindings apply to a namespace. There are also cluster-wide equivalents called ClusterRoles and ClusterRoleBindings.
Using these abstractions is known as Role Based Access Control (RBAC). These abstractions add flexibility and allow for very granular control of permissions, but they also add complexity. And with complexity, comes entropy.
The Second Law of RBAC
The second law of thermodynamics states that entropy increases over time, and the entropy of RBAC tends to increase over time, as well. I call this phenomenon the second law of RBAC.
Why does this happen? It’s human nature for people to request new permissions when they need the ability to do something. However, they are less likely to ask for the permissions to be taken away when they are no longer needed. RBAC permissions are additive and there is no blocklisting. If you want to remove a permission, you have to identify all the Role + RoleBinding combinations that grant it.
In addition, it’s quite difficult to get an overall view of who has permissions to access different objects in the cluster. Before you know it, there are people (and software components) with far greater levels of access than was originally intended. Loosely defined permissions increase the likelihood that malicious or incompetent actors will do something bad – or even very bad – to your deployment or to its data.
We need to fight our inclination to grant privileges liberally! We also need tools to help us do just that.
Checking Who has Privileges
In Linux, it’s easy to find out who can execute a file by looking at the permissions and ownership attributes of that file. In the example above, only the user liz and any member of the group staff can run it, because execute permission is set for the owner and group, but not for anyone else.
In Kubernetes, the extra abstractions mean there are more steps to the process of finding out who can do what. For instance, you need to take the following steps to find out if a user can create a pod:
- Find all the RoleBindings which reference that user
- Find all the Roles to whom those RoleBindings refer
- Find out if any of those Roles are allowed to create pods
If this sounds like hard work, there is help available. You can get a simple yes or no answer to the question of whether you can create pods with the following command:
|kubectl auth can-i create pods –as=<identity>|
What if you want to identify all of the users who can create pods? This involves a similar set of steps:
- Find all the Roles which can create pods
- Find all the RoleBindings that refer to those Roles
- Find all the subjects referred to by those RoleBindings
We wrote the who-can kubectl plugin, to report who has permission to perform specific actions on certain objects.
The who-can plugin is now available as a kubectl plugin through the krew directory. To install the who-can plugin:
- Go to https://krew.dev and follow the instructions there to install krew.
- Install who-can using kubectl krew install who-can
Permissions or Forgiveness?
We need to fight the tendency to grant too many permissions to too many players, just like you successfully overcame your urge to scroll down to the end of this blog.
Even though you have to jump through a number of hoops to configure specific permissions to different members of your organization in Kubernetes, it is well worth the effort. Even if it’s painful to set up permissions correctly, it will be easier than asking for forgiveness if your cluster gets compromised due to over-generous RBAC.
In this webinar I discuss best practices and permission configuration in Kubernetes. Watch it here