The Principle of Least Privilege is one of the longest standing principles of security. People (as well as applications) should only have access to the things they need to do their job, and nothing else. While being overly permissive may make life a bit easier in the short-term, it can easily come back to haunt you long-term, whether due to a malicious attack, misplaced credentials, or even an honest mistake.
In Kubernetes, Role-Based Access Control (RBAC) has been the preferred way of implementing the Principle of Least Privilege since version 1.6. It is easily one of the most important and most used security features of Kubernetes. If you’re not taking full advantage of it, you could end up with a nightmare scenario - a fully compromised Kubernetes cluster.
What is RBAC?
RBAC allows you to declare which parts of the Kubernetes API each user (or service) is allowed to access.
The Kubernetes API deals with dozens of different types of objects. There are Pods for running your workloads, Deployments and StatefulSets for managing Pods, Namespaces for creating logical separation between workloads, and much more. Furthermore, the Kubernetes API can be extended with new object types using CustomResourceDefinitions (CRDs), and common third-party add-ons like Istio and Kubeflow often do.
Not everyone needs to be able to create, retrieve, update, and delete every possible object in the Kubernetes API. By limiting that access, we can strengthen our security profile.
Note that this applies to people (e.g. an engineer running kubectl), to robots (e.g. your CI/CD pipeline), and to in-cluster applications (e.g. the cert-manager operator, which provisions SSL certificates). In each of these cases, RBAC allows us to specify precisely what actions they’re allowed to take in your Kubernetes cluster.
But why is it important?
If we didn’t care about the security of our cluster, we could simply grant cluster-admin access to everyone - this is the Kubernetes equivalent of root. But in doing so, we increase the chances of a major security breach, whether through maliciousness or honest mistakes. There are three main scenarios we want to be mindful of:
- Exploited Applications: Most likely, you’re running some user-facing applications inside your cluster. While we’d like to believe that these applications are bulletproof, we have to assume that they contain vulnerabilities. If an attacker manages to infiltrate the application, we need to ensure that their access stays as constrained as possible. If our compromised application were running as cluster-admin, the attack would quickly spread throughout the cluster. The attacker would be able to view all our Secrets (e.g. API keys and database passwords), exfiltrate data from unrelated applications, and even launch cryptocurrency miners.
- Internal Threats: While it’s important to trust your employees, about one third of data breaches involve internal actors. Employees, contractors, and vendors may be tempted to utilize their credentials for revenge, for personal gain, or even just to satisfy their curiosity. While giving out cluster-admin access to these folks will make your life a bit easier - you won’t have folks constantly asking for expanded access each time their needs change - it greatly expands your potential attack surface.
- Honest Mistakes: Malicious actors aren’t the only thing you need to worry about. Plenty of problems are caused by buggy code or tired engineers making mistakes. More than once I’ve seen someone execute a kubectl command against production when they thought they were in staging (something I’ve even done myself!). With RBAC, you can cut down on accidents by stopping people and applications from doing things that are unrelated to their role.
How do I get started?
You’ll want to familiarize yourself with a few basic concepts in order to start using RBAC in Kubernetes:
- Users and ServiceAccounts
These objects represent the individual actors in a Kubernetes cluster. Users typically represent real people, while ServiceAccounts represent applications and robots.
- Roles and ClusterRoles
These objects represent a list of abilities, typically in a verb/noun format. For instance, a Role might allow you to “get pods” or “create namespaces”. The difference between Roles and ClusterRoles is simple - the permissions in a Role are always scoped to the same Namespace that the Role lives in, whereas ClusterRoles apply to everything in the cluster (cluster-admin, mentioned above, is an example of a ClusterRole).
- RoleBindings and ClusterRoleBindings
These objects attach Roles and ClusterRoles to particular Users and ServiceAccounts. This is how Kubernetes knows which permissions should go with which users. Having the bindings defined separately from the permission lists, while a bit verbose, allows for greater reuse. If you find yourself struggling to put the RBAC APIs into practice, an abstraction like rbac-manager might be able to help.
Using RBAC to secure your cluster
RBAC allows you to pare down an application or user’s access to exactly what they need. This helps limit the blast radius of external threats, mitigate the risk of internal threats, and prevent honest mistakes. If you’re running a k8s cluster, RBAC is one of the first steps you should take to secure it.