How Authorization Works in Kubernetes: RBAC
Center of your Kubernetes cluster is an API Server. Which is a core of kubernetes as it provides REST API for managing resources on kubernetes. All the core components like kubelet, scheduler, controller manager etc. uses API Server to get and store data they needs.
RBAC (Role-Based Access Control) is a method of regulating network and computer resources based on the role given to a particular user within an enterprise.
As of 1.8, RBAC mode is stable and backed by the
To enable RBAC, start the apiserver with
To get some hands dirty, I am assuming that you have access to kubernetes cluster. If you don't then create a kind cluster by following their installation guide.
- The RBAC is a way to provide authorization to the API Server. The way RBAC is implemented in kubernetes is through RBAC API which declares four top-level types.
Those types are, as following:
Role and ClusterRole:
- In the RBAC API, a role contains rules that represent a set of permissions. Permissions are purely additive (there are no “deny” rules).
- The only difference between Role and ClusterRole is that Role is defined for a single namespace whereas ClusterRole is a cluster-wide. Role: A Role can only be used to grant access to resources within a single namespace. Here’s an example Role in the
defaultnamespace that can be used to grant read access to pods:
apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: namespace: default name: pod-reader rules: - apiGroups: [""] # "" indicates the core API group resources: ["pods"] verbs: ["get", "watch", "list"]
This is how you can define a Role in YAML. The important part is the rules block. which list all the action that this role can do on resources. Here, resource name is a pods and action will be
["get", "watch", "list"].
The full list of verbs (actions) are:
The available apiGroups and resources can be listed using
kubectl as following:
kubectl api-resources NAME SHORTNAMES APIGROUP NAMESPACED KIND bindings true Binding componentstatuses cs false ComponentStatus configmaps cm true ConfigMap endpoints ep true Endpoints events ev true Event limitranges limits true LimitRange namespaces ns false Namespace nodes no false Node persistentvolumeclaims pvc true PersistentVolumeClaim persistentvolumes pv false PersistentVolume pods po true Pod podtemplates true PodTemplate replicationcontrollers rc true ReplicationController resourcequotas quota true ResourceQuota secrets true Secret serviceaccounts sa true ServiceAccount services svc true Service mutatingwebhookconfigurations admissionregistration.k8s.io false MutatingWebhookConfiguration validatingwebhookconfigurations admissionregistration.k8s.io false ValidatingWebhookConfiguration customresourcedefinitions crd,crds apiextensions.k8s.io false CustomResourceDefinition apiservices apiregistration.k8s.io false APIService controllerrevisions apps true ControllerRevision daemonsets ds apps true DaemonSet deployments deploy apps true Deployment replicasets rs apps true ReplicaSet statefulsets sts apps true StatefulSet tokenreviews authentication.k8s.io false TokenReview localsubjectaccessreviews authorization.k8s.io true LocalSubjectAccessReview selfsubjectaccessreviews authorization.k8s.io false SelfSubjectAccessReview selfsubjectrulesreviews authorization.k8s.io false SelfSubjectRulesReview subjectaccessreviews authorization.k8s.io false SubjectAccessReview horizontalpodautoscalers hpa autoscaling true HorizontalPodAutoscaler cronjobs cj batch true CronJob jobs batch true Job certificatesigningrequests csr certificates.k8s.io false CertificateSigningRequest leases coordination.k8s.io true Lease events ev events.k8s.io true Event daemonsets ds extensions true DaemonSet deployments deploy extensions true Deployment ingresses ing extensions true Ingress networkpolicies netpol extensions true NetworkPolicy podsecuritypolicies psp extensions false PodSecurityPolicy replicasets rs extensions true ReplicaSet ingresses ing networking.k8s.io true Ingress networkpolicies netpol networking.k8s.io true NetworkPolicy runtimeclasses node.k8s.io false RuntimeClass poddisruptionbudgets pdb policy true PodDisruptionBudget podsecuritypolicies psp policy false PodSecurityPolicy clusterrolebindings rbac.authorization.k8s.io false ClusterRoleBinding clusterroles rbac.authorization.k8s.io false ClusterRole rolebindings rbac.authorization.k8s.io true RoleBinding roles rbac.authorization.k8s.io true Role priorityclasses pc scheduling.k8s.io false PriorityClass csidrivers storage.k8s.io false CSIDriver csinodes storage.k8s.io false CSINode storageclasses sc storage.k8s.io false StorageClass volumeattachments storage.k8s.io false VolumeAttachment
Here, NAME is a name of the resource and APIGROUP is a group in which this resources are grouped. The empty string
" " in APIGROUP means that those resources are grouped into CORE API group. i.e. nodes, pods are core resources.
A ClusterRole can be used to grant the same permissions as a Role, but because they are cluster-scoped, they can also be used to grant access to:
- cluster-scoped resources (like nodes)
- non-resource endpoints (like “/healthz”)
- namespaced resources (like pods) across all namespaces (needed to run kubectl get pods --all-namespaces, for example)
The following ClusterRole can be used to grant read access to secrets in any particular namespace, or across all namespaces (depending on how it is bound):
apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: # "namespace" omitted since ClusterRoles are not namespaced name: secret-reader rules: - apiGroups: [""] resources: ["secrets"] verbs: ["get", "watch", "list"]
- Service Account Provides identity to API Server. Using service account you can Authenticate to being granted to access apiserver.
- When you create Service Account using kubectl or describing YAML you are generating token which will be used to authenticate you to API Server.
apiVersion: v1 kind: ServiceAccount metadata: name: kube-urvil OR kubectl create sa kube-urvil
- RoleBinding And ClusterRoleBinding are, where the set of rules which are described in a Role or ClusterRole is mapped to the Service Account. This is where authorization and authentication meets the common ground.
RoleBinding And ClusterRoleBinding
- A role binding grants the permissions defined in a role to a user or set of users. It holds a list of subjects (users, groups, or service accounts), and a reference to the role being granted. Permissions can be granted within a namespace with a RoleBinding, or cluster-wide with a ClusterRoleBinding.
- A RoleBinding may reference a Role in the same namespace. The following RoleBinding grants the “pod-reader” role to the service-account “kube-urvil” within the “default” namespace. This allows “kube-urvil” to read pods in the “default” namespace.
- roleRef is how you will actually create the binding. The kind will be either Role or ClusterRole, and the name will reference the name of the specific Role or ClusterRole you want. In the example below, this RoleBinding is using roleRef to bind the service-account “kube-urvil” to the Role created above named pod-reader.
apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: read-pods namespace: default subjects: - kind: ServiceAccount name: kube-urvil # Name is case sensitive namespace: default roleRef: kind: Role #this must be Role or ClusterRole name: pod-reader apiGroup: rbac.authorization.k8s.io
- Finally, a ClusterRoleBinding may be used to grant permission at the cluster level and in all namespaces. The following ClusterRoleBinding allows any user in the group “manager” to read secrets in any namespace.
apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: read-secrets-global subjects: - kind: Group name: manager # Name is case sensitive apiGroup: rbac.authorization.k8s.io roleRef: kind: ClusterRole name: secret-reader apiGroup: rbac.authorization.k8s.io
Putting All Together with a real use-case:
Let's assume that we have hired new an engineer, which is new to kubernetes and want to play around with it's API. As a cluster admin you want to give it a permission to create Pods and Services inside namespace called
kubectl create ns kube-user
First Step will be, describe a Role:
cat <<EOF | kubectl apply -f - apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: namespace: kube-user name: newbie-role rules: - apiGroups: [""] # "" indicates the core API group resources: ["pods","services"] verbs: ["*"] EOF
Then create a service account for that new engineer:
cat <<EOF | kubectl apply -f - apiVersion: v1 kind: ServiceAccount metadata: name: kube-user-new-hired namespace: kube-user EOF
Final, Step would we to tide Role with ServiceAccount together using rolebinding:
cat <<EOF | kubectl apply -f - apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: newbie-rolebinding namespace: kube-user subjects: - kind: ServiceAccount name: kube-user-new-hired namespace: kube-user roleRef: kind: Role name: newbie-role apiGroup: rbac.authorization.k8s.io EOF
We, can check that all permissions are correctly applied to given service-account using
kubectl auth can-i --list --as=system:serviceaccount:kube-user:kube-user-new-hired -n kube-user # --as=system:serviceaccount:<namespace>:<serviceaccountname>
This will list all the permissions that this service-account have in the given namespace.
Resources Non-Resource URLs Resource Names Verbs pods   [*] services   [*] selfsubjectaccessreviews.authorization.k8s.io   [create] selfsubjectrulesreviews.authorization.k8s.io   [create] [/api/*]  [get] [/api]  [get] [/apis/*]  [get] [/apis]  [get] [/healthz]  [get] [/healthz]  [get] [/openapi/*]  [get] [/openapi]  [get] [/version/]  [get] [/version/]  [get] [/version]  [get] [/version]  [get]
That's it for now. We have created a Role and Service Account and connected both with RoleBinding.