How To Bind Kubernetes Service Account with ClusterRole

Reading Time: 5 minutes

Hi Readers In this blog we will see How To Bind Kubernetes Service Account with ClusterRole.So In this blog, we will first create a service account and after that, we will create a cluster role in which we will specify resources of Kubernetes and set of permission on the resources that will authorize the service account to access those resources.

Understanding Authentication

API server can be configured with one or more authentication plugins (and the same is true for authorization plugins). When a request is received by the API server, it goes through the list of authentication plugins, so they can each examine the request and try to determine who’s sending the
request. The API server stops invoking the remaining authentication plugins and continues onto the authorization phase.
Several authentication plugins are available. They obtain the identity of the client
using the following methods:

  • From the client certificate
  • From an authentication token passed in an HTTP header
  • Basic HTTP authentication
  • Others

Service Account

ServiceAccounts are nothing more than a way for an application running inside a
pod to authenticate itself with the API server.

You’ve already learned that the API server requires clients to authenticate themselves before they’re allowed to perform operations on the server. And you’ve already seen how pods can authenticate by sending the contents of the file /var/run/secrets/kubernetes.io/serviceaccount/token , which is mounted into each container’s filesystem through a secret volume. To authenticate with the API server, we use the ServiceAccount token mounted into the pod.

Every pod is associate with a Service Account, which represents the identity of the app running in the pod. The token file holds the ServiceAccount’s authentication token. When an app uses this token to connect to the API server, the authentication plugin authenticates the Service Account and passes the ServiceAccount’s username back to the API server core. Service Account usernames are look like this:

system:serviceaccount:<namespace>:<service account name>

Create Service Account

We’ve said every namespace contains its own default ServiceAccount, but additional ones can be create if necessary. But why should you bother with creating Service Accounts instead of using the default one for all your pods?

The obvious reason is cluster security. Pods that don’t need to read any cluster metadata should run under a constrained account that doesn’t allow them to retrieve
or modify any resources deployed in the cluster. Pods that need to retrieve resource metadata should run under a ServiceAccount that only allows reading those objects metadata, whereas pods that need to modify those objects should run under their own ServiceAccount allowing modifications of API objects

We can create a service account using kubectl command directly or we can use the YAML manifest file also.

$ kubectl create serviceaccount <serviceaccount_name>

Using YAML file

apiVersion: v1
kind: ServiceAccount
metadata:
  labels:
    app.kubernetes.io/name: cluster-role
  name: cluster-role
  namespace: default
$ kubectl apply -f <name_of_yaml_file>

When you create a service account a custom token secret is build and associate with the
ServiceAccount. If you look at the Secret’s data kubectl describe secret cluster-role-token-cbphz, you’ll see it contains the same items (the CA certificate, namespace, and token) as the default, ServiceAccount’s token does (the token itself will obviously be
different), as shown in the below image.

ClusterRole

A ClusterRole is a cluster-level resource for allowing access to non-namespace resources or non-resource URLs or used as a common role to be bound inside individual namespaces, saving you from having to redefine the same role in each of them.

As mentioned, a ClusterRole can be use to allow access to cluster-level resources. Let’s look at how to allow your pod to access resources in your cluster.

Create ClusterRole

$ kubectl create clusterrole <name_of_clusterrole> --verb=get,list --resource=<resources_name>

Using YAML manifest

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  labels:
    app.kubernetes.io/name: dashboard-cluster-role
  name: cluster-role
rules:
- apiGroups: 
  - ""
  - extentions
  resources: ["*"]
  verbs:
  - get
  - list
  - watch
  - create
  - update
  - patch
$kubectl apply -f <.yml>
clusterrole.rbac.authorization.k8s.io/cluster-role create

Binding ClusterRole with Service Account

You need to bind the ClusterRole to your ServiceAccount to allow it to access resources. ClusterRoles can be bound to subjects with regular RoleBindings, so you’ll create a RoleBinding now:

$ kubectl create clusterrolebinding reader-pod-admin- \
  --clusterrole=<cluster-role_name>  \
  --serviceaccount=<namespace>:<serviceAccount_name>
clusterrolebinding.rbac.authorization.k8s.io/reader-pod-admin- created

Now this service account will be able to access the resources and can perform the action that is defined in the cluster role.

As mentioned, a ClusterRole can be used to allow access to cluster-level resources. Let’s look at how to allow your pod to list pods in your cluster.

Now we will create a pod using the service account and will try to list the pod in the cluster.

Pod With A Custom ServiceAccount

Now We will deploy a pod using the same service account and check whether this service account is allowed to perform operations on the Kubernetes cluster or not.

apiVersion: v1
kind: Pod
metadata:
  name: dashboard-cluster-role-pod
spec:
  serviceAccountName: cluster-role   ## as created above
  containers:
  - name: main
    image: ubuntu:latest
    command: ["sleep", "999"]

As You can see in above pod manifest I have mentioned same serviceaccount that I have bind with the clusterrole.

Deploy the pod using command kubectl create -f <name-of-yaml-file>

As you can see that the pod has beed successfully deployed and running (k is alias of kubectl).Now we will exec into the pod and will perform curl operation.One thing to notice here that the Kubernetes API service address is available to Pods through environment variables as you can see in below image:

Pods also typically have the Kubernetes CA cert and Service Account secret materials mounted at /var/run/secrets/kubernetes.io/serviceaccount/.

Now we will use curl command to list the pods through Kubernetes api end point:

curl https://${KUBERNETES_SERVICE_HOST}:${KUBERNETES_SERVICE_PORT}/apis/apps/v1 \
  --cacert /var/run/secrets/kubernetes.io/serviceaccount/ca.crt \
  --header "Authorization: Bearer $(cat /var/run/secrets/kubernetes.io/serviceaccount/token)"

Conclusion:

As you can see we are able to list the pods. I hope you liked this blog if you have any suggestions please do let me know.This is how we bind the serviceaccount with clusterrole using clusterrole binding.

References:

https://kubernetes.io/docs/reference/access-authn-authz/rbac/

Written by 

Jubair Ahmad is a Software Consultant (DevOps)at Knoldus.Inc.He loves learning new technology and also have interest in playing cricket.