Role-based access control (RBAC) is a mechanism for defining the actions that user accounts can perform within your Kubernetes cluster. Enabling RBAC reduces the risk associated with credential theft and account takeover. Issuing each user with the minimum set of permissions they require prevents accounts from becoming over privileged.
Most popular Kubernetes distributions start with a single user account that’s granted superuser access to the cluster. Authenticating as this account lets you perform any action but can pose a substantial security risk.
In this article, we’ll show how to enable and configure the Kubernetes RBAC API so you can precisely define user capabilities. it’s common for some users to only create and list Pods while administrators get to delete items too. You can set up and enforce these policies using the RBAC system.
Enabling RBAC in Kubernetes
RBAC is an optional Kubernetes feature but most major distributions ship with it turned on by default, including those from managed cloud providers. You can check whether RBAC’s available in your cluster by running the following command with Kubectl:
$ kubectl api-versions | grep rbac.authorization.k8s rbac.authorization.k8s.io/v1
The command should emit rbac.authorization.k8s.io/v1
as its output if RBAC is enabled. RBAC is turned off if the command doesn’t produce any output. You can activate it by starting the Kubernetes API server with the --authorization-mode=RBAC
flag:
$ kube-apiserver --authorization-mode=RBAC
Refer to the documentation for your Kubernetes distribution if you’re unsure how to customize the API server’s startup arguments.
Kubernetes RBAC Objects
The Kubernetes RBAC implementation revolves around four different object types. You can manage these objects using Kubectl, similarly to other Kubernetes resources like Pods, Deployments, and ConfigMaps.
- Role – A role is a set of access control rules that define actions which users can perform.
- RoleBinding – A “binding” is a link between a role and one or more subjects, which can be users or service accounts. The binding permits the subjects to perform any of the actions included in the targeted role.
Roles and RoleBindings are namespaced objects. They must exist within a particular namespace and they control access to other objects within it. RBAC is applied to cluster-level resources – such as Nodes and Namespaces themselves – using ClusterRoles and ClusterRoleBindings. These work similarly to Roles and RoleBindings but target non-namespaced objects.
Creating a Service Account
A Kubernetes service account is a kind of user that’s managed by the Kubernetes API. Each service account has a unique token that’s used as its credentials. You can’t add normal users via the Kubernetes API so we’ll use a service account for this tutorial.
Use Kubectl to create a new service account:
$ kubectl create serviceaccount demo
This produces a new account called demo
. Next you need to retrieve the token that you’ll use to authenticate as this account. First find the name of the secret that stores the token:
$ kubectl describe serviceaccount demo Name: demo Namespace: default Labels:Annotations: Image pull secrets: Mountable secrets: demo-token-w543b Tokens: demo-token-w543b Events:
This service account’s token is stored in the secret called demo-token-w543b
. You can retrieve the token by getting the secret’s value with this command:
$ TOKEN=$(kubectl describe secret demo-token-w543b | grep token: | awk '{print $2}')
The token’s now stored in the TOKEN
variable in your shell. You can use this variable to add a new Kubectl context that will let you authenticate as your service account:
$ kubectl config set-credentials demo --token=$TOKEN User "demo" set. $ kubectl config set-context demo --cluster=default --user=demo Context "demo" created.
You should change the value of the --cluster
flag to match the name of your active Kubectl cluster connection. This is usually default
or the name of your currently selected context. You can check the selected context by running kubectl config current-context
.
Switch to your new context to authenticate as your demo
service account. Note down the name of your currently selected context first, so you can switch back to your superuser account later on.
$ kubectl config current-context default $ kubectl config use-context demo Switched to context "demo".
Kubectl commands will now authenticate as the demo
service account. Try to retrieve the list of Pods in your cluster:
$ kubectl get pods Error from server (Forbidden): pods is forbidden: User "system:serviceaccount:default:demo" cannot list resource "pods" in API group "" in the namespace "default"
The operation has been forbidden because the demo
service account lacks a role that lets it access Pods.
Adding a Role
Roles are created in the same way as any other Kubernetes object. You write a YAML file that defines the role and the permissions it provides. Each role contains one or more rules that permit specific actions to be performed against a set of resources. Here’s a simple role that allows a user to retrieve details of existing Pods:
apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: namespace: default name: demo-role rules: - apiGroups: [""] resources: ["pods"] verbs: ["get", "list"]
The get
and list
verbs applied to the pods
resource means you’ll be able to run commands like get pod
and describe pod
. Trying to create a new Pod, or delete an existing one, will be forbidden because the create
and delete
verbs are omitted from the role.
Switch back to your original Kubectl context so you can add the role to your cluster using your administrative account:
$ kubectl config use-context default Switched to context "default".
Now add the role:
$ kubectl apply -f role.yaml role.rbac.authorization.k8s.io/demo-role created
Binding Roles to Users and Service Accounts
Now you can associate your role with your demo
service account by creating a new RoleBinding. Create the following YAML file to define your binding:
apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: namespace: default name: demo-role-binding subjects: - kind: ServiceAccount name: demo apiGroup: "" roleRef: kind: Role name: demo-role apiGroup: ""
RoleBindings need to include one or more subjects that identify the users and service accounts targeted by the binding. The roleRef
field refers to the role you want to assign to each of those users.
The Role and RoleBinding must exist in the same namespace. Use a ClusterRole and ClusterRoleBinding instead for non-namespaced resources.
Next run kubectl apply
to add the RoleBinding to your cluster. It will take effect immediately, granting the demo
service account the capabilities declared in the demo-role
Role:
$ kubectl apply -f role-binding.yaml rolebinding.rbac.authorization.k8s.io/demo-role-binding created
Testing Your RBAC Rule
Test your simple RBAC implementation by switching back to the new Kubectl context you created for the demo
account:
$ kubectl config use-context demo Switched to context "demo".
Now repeat the get pods
command from earlier:
$ kubectl get pods No resources found in default namespace.
This time the command has succeeded. The demo
service account is now permitted to retrieve Pod lists because it’s bound to the demo-role
Role. You’ll still see a Forbidden error if you try to create a new Pod because that operation’s not included in any role bound to the account:
$ kubectl run nginx --image=nginx Error from server (Forbidden): pods is forbidden: User "system:serviceaccount:default:demo" cannot create resource "pods" in API group "" in the namespace "default"
You can resolve this by assigning the user another role that includes the create
verb for the pods
resource. Alternatively, you can edit your existing role’s YAML file and apply the modified version to your cluster:
apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: namespace: default name: demo-role rules: - apiGroups: [""] resources: ["pods"] verbs: ["create", "get", "list"]
You can also add additional rules to your role to create different combinations of resource groups and permitted actions.
Summary
RBAC allows you to define the software capabilities available to individual user accounts. The Kubernetes RBAC system provides highly precise controls for limiting the types of resource that accounts can access, and the actions they’re allowed to perform.
Adopting RBAC tightens the security around your cluster and creates a less risky operating environment. However you still need to keep best practices in mind to avoid introducing new problems. You should regularly audit your cluster to identify over-privileged accounts and clean up redundant roles. This will help prevent confusion and allow you to get a clear picture of the actions that can be taken by each account.
Effective RBAC implementations should be based on the smallest possible number of roles, with each role having the minimum set of actions needed for its specific area of functionality. Assigning too many privileges to each account negates the benefits of RBAC so it’s worth taking time to plan each user’s requirements before you start creating roles and bindings.