In this post we will look at how to configure RBAC (https://kubernetes.io/docs/reference/access-authn-authz/rbac/) for a Kubernetes cluster hosted on Google Cloud Platform. This post assumes that you have at least Editor rights to your GCP project in order to configure IAM, Cloud Storage and Kubernetes Engine. You will also need to have admin access to your Kubernetes Cluster.

RBAC is the second step i.e. Authorization to your Kubernetes cluster. It will allow you to control who can do what in your cluster. However, it doesn’t allow you to define users. Kubernetes does not have users, it allows flexibility to define users and authenticate them against an external system. It does have service accounts which shouldn’t be considered as users. Users are humans who are allowed to interact with Kubernetes systems. Service Accounts can be considered machines or software which is allowed to query and use the Kubernetes API. An example of this could be an automation setup for QA which deploys and tests applications in a QA cluster.

RBAC vs Authentication

As I said earlier, RBAC allows you to control who does what i.e. it’s Authorization. Authentication on the other hand controls access to the cluster. An example of this scenario would be you have a user who is an Internal Auditor who needs to access Kubernetes cluster to check which applications are running and keep an audit of licenses. This user will need only connect privileges to the cluster and will not need any permissions to deploy applications. This in GCP can be done via Authentication itself.

IAM in Google Cloud Platform

IAM is a user management service which controls users access to different Google Cloud services e.g. Cloud SQL, Kubernetes, Google Cloud Run etc. Its a user management module available in GCP and it makes life very easy with its predefined roles. The console looks like the screenshot below.

As you can see there are Members and Roles. GCP has some really good default roles and policies created. To add users through IAM just click the Add button on top. If you AD is connected to your GCP project then you will be able to add them via email addresses. When you add the users you can add them with different Roles. Let’s say for example you want a user to be able to create Deployments and Services in Kubernetes you can assign a Kubernetes Engine Developer Role. To know more about the roles and what they mean you can look at the GCP documentation here – https://cloud.google.com/kubernetes-engine/docs/how-to/iam#predefined

This now means users can connect to your Kubernetes cluster. A user with access to the cluster can run a simple gcloud command to configure they kubernetes config file with the cluster details. Assuming the gcloud init command is run and authentication is completed with the GCP account the user can simply run

gcloud container clusters get-credentials <clustername> --region <region> 

If the project is not configured when gcloud was initialized a –projectid argument can also be provided. Note that these roles allow users to perform actions at a Kubernetes level. They are not fine grained. For example if you want to only allow access to certain namespaces or read access to some namespaces and write to others this cannot be done by IAM.

Enter RBAC

RBAC allows fine grained controls to administrators over and above what IAM allows. I highly recommend reading the RBAC documentation from Kubernetes here https://kubernetes.io/docs/reference/access-authn-authz/rbac/. I’ll explain quickly what objects would be needed for RBAC.

Role

A Role object defines what’s allowed and not allowed. Typically you will not need to create new roles unless you have some really complex use cases. A Role is defined per namespace.

ClusterRole

ClusterRole is a role which is not restricted to a namespace. It also defines permissions just like a role. Kubernetes defines quite a few cluster roles. You can view the roles defined with the command –

kubectl get clusterroles.rbac.authorization.k8s.io

To get details on a particular role you can use

~ -> kubectl get clusterrole admin -o YAML     
aggregationRule:
  clusterRoleSelectors:
  - matchLabels:
      rbac.authorization.k8s.io/aggregate-to-admin: "true"
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  annotations:
    rbac.authorization.kubernetes.io/autoupdate: "true"
  creationTimestamp: "2020-04-09T17:35:34Z"
  labels:
    kubernetes.io/bootstrapping: rbac-defaults
  name: admin
  resourceVersion: "259"
  selfLink: /apis/rbac.authorization.k8s.io/v1/clusterroles/admin
  uid: 72852415-66a6-4144-8bb7-c2d40626c266
rules:
- apiGroups:
  - ""
  resources:
  - pods/attach
  - pods/exec
  - pods/portforward
  - pods/proxy
  - secrets
  - services/proxy
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - ""
  resources:
  - serviceaccounts
  verbs:
  - impersonate
- apiGroups:
  - ""
  resources:
  - pods
  - pods/attach
  - pods/exec
  - pods/portforward
  - pods/proxy
  verbs:
  - create
  - delete
  - deletecollection
  - patch
  - update
- apiGroups:
  - ""
  resources:
  - configmaps
  - endpoints
  - persistentvolumeclaims
  - replicationcontrollers
  - replicationcontrollers/scale
  - secrets
  - serviceaccounts
  - services
  - services/proxy
  verbs:
  - create
  - delete
  - deletecollection
  - patch
  - update
- apiGroups:
  - apps
  resources:
  - daemonsets
  - deployments
  - deployments/rollback
  - deployments/scale
  - replicasets
  - replicasets/scale
  - statefulsets
  - statefulsets/scale
  verbs:
  - create
  - delete
  - deletecollection
  - patch
  - update
- apiGroups:
  - autoscaling
  resources:
  - horizontalpodautoscalers
  verbs:
  - create
  - delete
  - deletecollection
  - patch
  - update
- apiGroups:
  - batch
  resources:
  - cronjobs
  - jobs
  verbs:
  - create
  - delete
  - deletecollection
  - patch
  - update
- apiGroups:
  - extensions
  resources:
  - daemonsets
  - deployments
  - deployments/rollback
  - deployments/scale
  - ingresses
  - networkpolicies
  - replicasets
  - replicasets/scale
  - replicationcontrollers/scale
  verbs:
  - create
  - delete
  - deletecollection
  - patch
  - update
- apiGroups:
  - policy
  resources:
  - poddisruptionbudgets
  verbs:
  - create
  - delete
  - deletecollection
  - patch
  - update
- apiGroups:
  - networking.k8s.io
  resources:
  - ingresses
  - networkpolicies
  verbs:
  - create
  - delete
  - deletecollection
  - patch
  - update
- apiGroups:
  - ""
  resources:
  - configmaps
  - endpoints
  - persistentvolumeclaims
  - persistentvolumeclaims/status
  - pods
  - replicationcontrollers
  - replicationcontrollers/scale
  - serviceaccounts
  - services
  - services/status
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - ""
  resources:
  - bindings
  - events
  - limitranges
  - namespaces/status
  - pods/log
  - pods/status
  - replicationcontrollers/status
  - resourcequotas
  - resourcequotas/status
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - ""
  resources:
  - namespaces
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - apps
  resources:
  - controllerrevisions
  - daemonsets
  - daemonsets/status
  - deployments
  - deployments/scale
  - deployments/status
  - replicasets
  - replicasets/scale
  - replicasets/status
  - statefulsets
  - statefulsets/scale
  - statefulsets/status
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - autoscaling
  resources:
  - horizontalpodautoscalers
  - horizontalpodautoscalers/status
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - batch
  resources:
  - cronjobs
  - cronjobs/status
  - jobs
  - jobs/status
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - extensions
  resources:
  - daemonsets
  - daemonsets/status
  - deployments
  - deployments/scale
  - deployments/status
  - ingresses
  - ingresses/status
  - networkpolicies
  - replicasets
  - replicasets/scale
  - replicasets/status
  - replicationcontrollers/scale
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - policy
  resources:
  - poddisruptionbudgets
  - poddisruptionbudgets/status
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - networking.k8s.io
  resources:
  - ingresses
  - ingresses/status
  - networkpolicies
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - authorization.k8s.io
  resources:
  - localsubjectaccessreviews
  verbs:
  - create
- apiGroups:
  - rbac.authorization.k8s.io
  resources:
  - rolebindings
  - roles
  verbs:
  - create
  - delete
  - deletecollection
  - get
  - list
  - patch
  - update
  - watch

We will be using the cluster-admin role in our example to grant admin access to specific namespaces.

RoleBinding and ClusterRoleBindings

These are bindings or objects created for assigning the role to a user or service account. This is a great way to separate the permission creation from permission assignements. Role and ClusterRole are permissions and the bindings are a way to assign them. For example to grant admin access to users for a demo namespace you can use the following YAML

kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  namespace: demos                     
  name: demos-admin-RoleBinding
subjects:
# Google Cloud user account
- kind: User
  name: [email protected]
- kind: User
  name: [email protected]
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: admin

Note that the binding is done in the roleRef section where we have referenced the pre-created admin role from rbac.authorization.k8s.io. As you can see that the kind is ClusterRole however we are creating a RoleBinding and not a ClusterRoleBinding which will provide access across namespaces.

That’s it. If you know what you want to do then it’s pretty easy ! The only way to understand this well is to try it out.

Recommended Reading