Understanding RBAC in Kubernetes
Understand how RBAC (Role Based Access Control) works in Kubernetes. Implement RBAC and make sure things are working as expected.
Table of contents
RBAC overview
RBAC or Role Based Access Control is one way of implementing access control in Kubernetes. RBAC can be scoped either to a specific namespace or the whole cluster.
Namespace scoped RBAC
The RBAC rules are scoped to a specific Kubernetes namespace and apply only for resources belonging to that namespace. We use this for instance when we want to give a user or service account permissions to do something on some resources only inside a specific namespace. To implement namespace scoped RBAC, we use the Role and RoleBinding resources.
The Role and RoleBinding resources have to be created inside the namespace we want to limit RBAC in.
The Role resource defines the permissions. For instance, the permission to list pods. The RoleBinding resource associate permissions to a user, a group or a service account. The associated user, group or service account will then be granted permissions defined inside the Role resource and therefore be authorized to perform the associated actions inside a specific namespace.
Cluster scoped RBAC
The RBAC rules are not limited to specific namespaces and apply to the whole Kubernetes cluster. We use this for instance when we want to give a user, service account... permissions to do something on some resources inside the entire cluster. To implement cluster scoped RBAC, we use the ClusterRole and ClusterRoleBinding resources.
The ClusterRole resource defines the permissions. For instance, the permission to list pods. The ClusterRoleBinding resource associate permissions to a user, a group or a service account. The associated user, group or service account will then be granted permissions defined inside the ClusterRole resource and therefore be authorized to perform the associated actions at the cluster level.
Implementing RBAC
Role or ClusterRole resources
Here is a sample Role or ClusterRole resource manifest :
kind: Role # or ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: podsReader
namespace: mynamespace # only for Role resource
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "list", "watch"]
This sample can be used to create a Role or ClusterRole resource by simply setting the appropriate kind (Role or ClusterRole) and not using metadata.namespace for ClusterRole resource as that resource can't be put into namespaces.
The rules section is the most interesting one because that's where we define the permissions. We need the following elements to define the permissions :
- apiGroups : a list of API groups of the resources we want to set access control for, for instance apps, batch... Next paragraph describes how to easily find this information for specific resources
- resources : a list of resources types we want to set access control for (deployments, secrets, pods...)
- verbs : actions that can be performed on the resources. We can find a list of available verbs, their descriptions and HTTP verbs equivalent here
To show a list of resources supported by our Kubernetes cluster and the associated apiGroups, we can use the kubectl api-resources
command. Here is an example :
$ kubectl api-resources
NAME SHORTNAMES APIVERSION NAMESPACED KIND
(...)
namespaces ns v1 false Namespace
nodes no v1 false Node
persistentvolumeclaims pvc v1 true PersistentVolumeClaim
persistentvolumes pv v1 false PersistentVolume
pods po v1 true Pod
(...)
controllerrevisions apps/v1 true ControllerRevision
daemonsets ds apps/v1 true DaemonSet
deployments deploy apps/v1 true Deployment
replicasets rs apps/v1 true ReplicaSet
statefulsets sts apps/v1 true StatefulSet
(...)
The NAME column indicates the name of the resources supported by our Kubernetes cluster. The APIVERSION column is composed of the apiGroups followed by a version after the slash separator. For the deployments resource for instance, the apiGroups value is apps.
Sometimes the apiGroups value is not present inside the APIVERSION column. This is the case for instance for the pods resource. This means that the resource belong to the core API group and the value to use for apiGroups in our Role/ClusterRole resource definition is ""
, as shown in the previous Role/ClusterRole sample resource manifest.
RoleBinding or ClusterRoleBinding resources
Here is a sample RoleBinding or ClusterRoleBinding resource manifest :
kind: RoleBinding # or ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: podsReader
namespace: mynamespace # only for RoleBinding resource
subjects:
- kind: ServiceAccount # or User or Group
name: myserviceaccount
namespace: mynamespace
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role # or ClusterRole
name: podsReader
This sample can be used to create a RoleBinding or ClusterRoleBinding resource by simply setting the appropriate kind (RoleBinding or ClusterRoleBinding) and not using metadata.namespace for ClusterRoleBinding resource as that resource can't be put into namespaces.
It associates an existing Role or ClusterRole resource to an existing service account, in order to grant the service account, permissions defined inside the Role or ClusterRole resource.
Here is an explanation of the contents of subjects and roleRef fields :
- subjects : define the subject(s) on which to bound a specific Role or ClusterRole resource
- kind : the type of the subject. Can be
User
,Group
orServiceAccount
- name : the name of the subject (a User name, Group name or ServiceAccount name)
- namespace : the namespace where to find the subject (only for ServiceAccount Kind)
- kind : the type of the subject. Can be
- roleRef : the Role or ClusterRole that will be bound to the subject
- apiGroup : most of the time
rbac.authorization.k8s.io
- kind : the type of the role reference. Can be
Role
orClusterRole
- name : the name of the
Role
orClusterRole
that will be bound to the subject
- apiGroup : most of the time
Testing RBAC using impersonation
Once we have configured RBAC to authorize access to specific Kubernetes resources for some users, groups or service accounts, the next thing to do is to test that everything is working as expected.
Having a way to do so whithout asking users to perform specific actions or setting up pods with specific service accounts to verify the access is more convenient. This is where Kubernetes impersonation feature comes in.
Thanks to Kubernetes impersonation feature, we can take the identity of another user, a group or a service account to perform specific actions (list pods inside a specific namespace for instance) and therefore make sure RBAC is properly configured.
The user we perform actions as can be a real user from an identity provider system (GCP IAM user for instance) or a non existing/virtual one. The user taking identity of another user (real or fake/virtual user), a group or a service account, first have to be authorized to do so with a ClusterRole and associated ClusterRoleBinding as follows :
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: impersonation
rules:
- apiGroups: [""] # the core API group
resources: ["user"] # or group or serviceaccount
# Users, groups or serviceaccount name(s)
resourceNames: ["user-to-impersonate@mycompany.com"]
verbs: ["impersonate"]
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: impersonation
subjects:
- kind: User # or Group or ServiceAccount
name: user-that-impersonate@mycompany.com
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: impersonation
User and group resources, most of the time are custom resources available only when we use Managed Kubernetes service from Cloud Providers like GCP, AWS... and correspond to users and groups available inside the IAM (Identity and Access Management) service they provide for users, groups and services access management.
The previous sample manifest allows the user identified by user-that-impersonate@mycompany.com
email address to take the identity of the user identified by user-to-impersonate@mycompany.com
email address. We can use the same sample manifest to also authorize impersonation of a group or service account.
Then, user-that-impersonate@mycompany.com
can configure RBAC for user-to-impersonate@mycompany.com
and test the configuration by taking the identity of user-to-impersonate@mycompany.com
using the following kubectl
commands :
# Run a Kubectl command as another user (--as) or group (--as-group)
$ kubectl --as user-to-impersonate@mycompany.com get pods -n frontend
# Test if a specific Kubectl command will work... whithout actually running it
kubectl auth can-i get pods -n frontend
# Same thing by taking another user account identity
kubectl auth can-i get pods -n frontend --as user-to-impersonate@mycompany.com
That's all. We now have the essentials knowledges required to understand, implement and test RBAC in Kubernetes.