The story so far is that Alice has hired Ann and given her access as a reader. Now Bob wants the same for his team. Bob is also looking to up Alice in her game. He thinks of a way to make it easy for any tech lead in the org to create identical Roles which apply to different namespaces.

For example, both Bob and Chandan (another tech lead) have new-hires Bart and Charlie respectively. Bob wants both Bart and Charlie to have the same permissions as Ann without creating separate Roles. Keeping things DRY to avoid human error and ensure uniformity.

ClusterRole

A ClusterRole is a Role without a Namespace restriction. This is the reader role we made for Ann. Lets convert this to a ClusterRole

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: alices-team
  name: reader
rules:
- apiGroups: [""]
  resources: ["pods", "pods/log"]
  verbs: ["get", "list", "watch"]

All you need to do is change the Kind and remove the namespace.

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: reader
rules:
- apiGroups: [""]
  resources: ["pods", "pods/log"]
  verbs: ["get", "list", "watch"]

Lets create this

$ kubectl apply -f reader-clusterrole.yml                                                                                                               
clusterrole.rbac.authorization.k8s.io/reader created                                                                                                                                                         

Lets see if its there

$ kubectl get ClusterRoles -n alices-team                                                                                                               
NAME                                                          AGE                                                                                                                                   
admin                                                         15d                                                                                                                                   
cluster-admin                                                 15d                                                                                                                                   
edit                                                          15d                                                                                                                                   
reader                                                        3m44s                                                                                                                                 

RoleBinding for a ClusterRole

lets delete the old RoleBinding we created.

$ kubectl delete RoleBindings anns-role -n alices-team
rolebinding.rbac.authorization.k8s.io "anns-role" deleted

Now Ann should not be able to view any pods in namespace alices-team

$ kubectl config use-context ann
Switched to context "ann".

$ kubectl get pods -n alices-team
Error from server (Forbidden): pods is forbidden: User "ann" cannot list resource "pods" in API group "" in the namespace "alices-team"

Create the RoleBinding

In the RoleBinding we need to specify the namespace.

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: anns-role
  namespace: alices-team
subjects:
- kind: Group
  name: alice # Name is case sensitive
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole 
  name: reader 
  apiGroup: rbac.authorization.k8s.io

Note the kind is ClusterRole. Also note that the namespace is specified as alices-team. Lets apply this and see if it works.

$ kubectl config use-context ann
Switched to context "ann".

$ kubectl get pods -n alices-team
NAME    READY   STATUS    RESTARTS   AGE
alice   1/1     Running   0          32s

$ kubectl get pods -n bobs-team
Error from server (Forbidden): pods is forbidden: User "ann" cannot list resource "pods" in API group "" in the namespace "bobs-team"

ClusterRoleBinding

What if we wanted Ann to have access across all namespaces ? In such a case we would need a ClusterRoleBinding. Just as a ClusterRole is a Role without a namespace, a ClusterRoleBinding is a RoleBinding without a namespace.

This is our present RoleBinding.

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: anns-role
  namespace: alices-team
subjects:
- kind: Group
  name: alice
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole 
  name: reader 
  apiGroup: rbac.authorization.k8s.io

The ClusterRoleBinding would be

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: anns-role
subjects:
- kind: Group
  name: alice
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole 
  name: reader 
  apiGroup: rbac.authorization.k8s.io

Note the missing namespace under metadata.

Lets delete the RoleBinding and apply the new ClusterRoleBinding.

$ kubectl delete rolebindings anns-role -n alices-team                                                                                                        
rolebinding.rbac.authorization.k8s.io "anns-role" deleted                                                                                                                                                    

$ kubectl apply -f GroupClusterRoleBinding.yml
clusterrolebinding.rbac.authorization.k8s.io/anns-role created

$ kubectl config use-context ann
Switched to context "ann".

$ kubectl get pods --all-namespaces
NAMESPACE     NAME                          READY   STATUS    RESTARTS   AGE
alices-team   alice                         1/1     Running   0          38m
bobs-team     job1-847956d49f-spm28         1/1     Running   1          17h
default       centos-pod                    1/1     Running   8          12d
default       junk-pod                      1/1     Running   8          12d
default       ubuntu-pod                    1/1     Running   8          12d
kube-system   coredns-6955765f44-7hjbw      1/1     Running   13         15d
kube-system   coredns-6955765f44-j8tzv      1/1     Running   13         15d
kube-system   etcd-m01                      1/1     Running   13         15d
kube-system   kube-apiserver-m01            1/1     Running   14         15d
kube-system   kube-controller-manager-m01   1/1     Running   13         15d
kube-system   kube-proxy-9d2sw              1/1     Running   13         15d
kube-system   kube-scheduler-m01            1/1     Running   13         15d
kube-system   storage-provisioner           1/1     Running   22         15d
 

Now Ann can read anything she ever wants to!

Learnings

ClusterRoles are Roles without a namespace restriction

ClusterRoleBindings are RoleBindings without a namespace restriction.

You can use a ClusterRole with a RoleBinding to create a single Role which can be used in different namespaces. This is useful when you need the same permissions in different namespaces.

DRY can avoid human error biting you later, not to mention reduce the number of chores you need to do!

Always think in groups. Groups allow you to convert O(n) chores to once-only tasks. As you scale thinking in Groups is key.

Conclusion

This brings us to the end of Role Based Access Control for Kubernetes. While you would not normally do these things by hand as we did, its important to understand that these things are happening in the background of any service provider.

Its also important to thing in Groups as much as possible and avoid dealing with Individuals in the group. Ideally, you should be able to put engineers into Groups and then the authentication system should just deal with Groups.

In the next post we will go back to our Pod creation and one of the things we need to decide is, who is allowed to deploy to the cluster ? Anyone ? Someone ? NoOne ?.