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 rbac.authorization.k8s.io/v1
API.
To enable RBAC, start the apiserver with --authorization-mode=RBAC
.
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
- ClusterRole
- RoleBinding
- ClusterRoleBinding
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
default
namespace 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:
- get
- list
- update
- patch
- create
- watch
- delete
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:
- 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 kube-user
.
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
as:
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.
Resources: