Role Based Access Control in Kubernetes
As we all know role based access control plays a vital role. when we have multiple people using the same resources for different purposes. We need to handle this scenarios by providing the users unique identification mechanism and privileges required for that particular user.
RBAC in kubernetes adheres to least privilege principle.
Need for RBAC
As Kubernetes has tens of resources with many functionalities. Different users use them for different use cases. Unnecessary privileges leads to increasing the attack surface.
Like every other role based access control system kubernetes also deals with authentication and authorization.
Authentication deals with does a specific user, group or a service from a machine can authenticate or access this system.
Authorization deals with does a specific user have an required privileges to perform a particular action on a specific resource or subresource or group of resources.
RBAC mainly deals with three entities
- subject: Users(i.e humans & services)
- verb: Action a subject can perform
- object: Victim for an action from a subject
Can mike(subject) get(verb) pods(object)?
Kubernetes provides following resources to manage RBAC:
- Role
- ClusterRole
- RoleBinding
- ClusterRoleBinding
- ServiceAccount
Role: Roles defines the set of privileges allowed on specific resource by it’s name or on group of resources or set of subresourcesand this is confined to a specific namespace.
ClusterRole: ClusterRole defines the set of privileges allowed on specific resource by it’s name or on group of resources or set of subresources and this is applicable on cluster as a whole.
RoleBinding: Rolebinding binds the user or group or serviceaccount to a role. This makes sure the subject provided in rolebinding has all the privileges provided within a role.
ClusterRoleBinding: ClusterRolebinding binds the user or group or serviceaccount to a role. This makes sure the subject provided in clusterrolebinding has all the privileges provided within a clusterrole.
ServiceAccount: Serviceaccount authorizes account to perform specific action based on the rolebinding or clusterrolebinding it is associated with.
In this blog we will be looking at two ways of creating KUBECONFIG file they are
- Certificate based
- Token based
Certificate based authentication
Generate the private key file.
openssl genrsa -out new-user.key 2048
Create a certificate sign request new-user.csr using the private key you just created (new-user.key in this example). Make sure you specify your username and group in the -subj section (CN is for the username and O for the group). As previously mentioned, we will use new-user as the name and bitnami as the group:
openssl req -new -key employee.key -out new-user.csr -subj "/CN=new-user/O=aqua"
openssl x509 -req -in new-user.csr -CA CA_LOCATION/ca.crt -CAkey CA_LOCATION/ca.key -CAcreateserial -out new-user.crt -days 500
kubectl config set-credentials new-user --client-certificate=/home/new-user/.certs/new-user.crt --client-key=/home/new-user/.certs/new-user.key
kubectl config set-context new-context --cluster=minikube --namespace=test --user=new-user
After running the above steps we have successfully created a user with name as new-user belonging to aqua group. But this user doesn’t have any previleges by defaults nil privileges will be assigned to the user. We need to explicitly grant the access privilges required by the user.
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: test-user-full-access
namespace: test
rules:
- apiGroups: ["", "apps","extensions"]
resources: ["pods","pods/log","deployments"]
#resourceNames: ["nginx-deployment"] #Confines privileges to specified resource name
verbs: ["get","list"]
- apiGroups: ["batch"]
resources:
- jobs
- cronjobs
verbs: ["*"]
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: test-rolebinding
namespace: test
subjects:
- kind: ServiceAccount
name: new-user
namespace: test
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: test-user-full-access
Token based authentication
Token based authentication deals with service account. Firstly we create a service account which has internal RoleBinding or ClusterRoleBinding based on the requirement. And this has a secret token encoded in base64 and also a certificate. We need secret token and certificate to authenticate with cluster. We rovide this values in KUBEONFIG file.
Creating a serviceaccount in test namespace.
apiVersion: v1 kind: ServiceAccount metadata: name: test-user namespace: test
Creating a clusterrole with privileges
kind: ClusterRole apiVersion: rbac.authorization.k8s.io/v1 metadata: name: test-user-full-access rules: - apiGroups: ["", "apps","extensions"] resources: ["pods","pods/log","deployments"] verbs: ["get","list"] - apiGroups: ["batch"] resources: - jobs - cronjobs verbs: ["*"]
Creating a clusterrolebinding by binding a serviceaccount to it.
kind: ClusterRoleBinding apiVersion: rbac.authorization.k8s.io/v1 metadata: name: test-rolebinding subjects: - kind: ServiceAccount name: test-user namespace: test roleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: test-user-full-access
Get the service account secret for the provided namespace
kubectl describe sa test-user -n test
Get the service account token
kubectl get secret test-user-token-xxxxx -n test -o "jsonpath={.data.token}" | base64 -d
Get the certificate authority
kubectl get secret test-user-token-xxxxx -n test -o "jsonpath={.data['ca\.crt']}"
Template for KUBECONFIG file.
Add the kubernetes api endpoint, certificate and token in the below KUBECONFIG file.
apiVersion: v1
clusters:
- cluster:
certificate-authority-data: PLACE CERTIFICATE HERE
server: https://YOUR_KUBERNETES_API_ENDPOINT
name: kind
contexts:
- context:
cluster: kind
namespace: test
user: test-user
name: test
current-context: test
kind: Config
preferences: {}
users:
- name: test-user
user:
client-key-data: PLACE CERTIFICATE HERE
token: PLACE USER TOKEN HERE
We have successfully created a KUBECONFIG file for a new user.
Other way of understanding RBAC is to install helm in your kubernetes cluster
First install helm by following helm official docs https://helm.sh/docs/using_helm/#installing-helm
We are creating ServiceAccount with name tiller
apiVersion: v1
kind: ServiceAccount
metadata:
name: tiller
namespace: kube-system
We are binding the cluster admin privileges tiller service account
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: tiller
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
subjects:
- kind: ServiceAccount
name: tiller
namespace: kube-system
After creating the above ServiceAccount and ClusterRoleBinding
Run the tiller
helm init --service-account tiller
Check the helm installation and validate ServiceAccount by running following command
helm install stable/mysql
By this you have successfully configured helm in your cluster which needs special privileges to communicate with API-SERVER.
Note:
By default when a new namespace is created a default ServiceAccount specific to that namespace is created but this serviceaccount has no authorization privileges all the resources running in this namespace will use the default ServiceAccount, Unless we need any privileges specific to a resource we need to specify it in resource.yaml as mentioned in below example.
apiVersion: v1 kind: Pod metadata: name: nginx-creator namespace: test spec: serviceAccountName: nginx-creator #This resource has special privileges binded in this ServiceAccount containers: - name: nginx-creator image: vineeth97/nginx-pod-creator
We can also bind a ClusterRole to a RoleBinding which provides privileges to subject provided in RoleBinding but the scope is specific to namespace mentioned in the RoleBinding.
Slides prepared for my talk on RBAC can be found here
Cheers!