RBAC [Role-Based Access Control] is a feature-driven method of permission enforcement with restricted access to Kubernetes resources based on the role that the user holds. A security design that restricts sensitive operations that can eventually reduce the offensive attack surface in case an account is compromised.
Last time, I went through my office’s Kubernetes documentation about mentioning development cluster has some custom add-ons operating on the specified namespace. It was basically for R&D purposes. I was curious to inspect what it does and general overview internally.
Tried to list out the available pods on that specific namespace using the below commands.
kubectl get pod -n x-namespace
Output was unexpected as I wasn’t able to view the running pods available on that specific namespace and permission got denied. That’s how I met with RBAC during my hit and trial process to inspect the R&D add-ons running on the development cluster. This was the real use case of RBAC. RBAC is being implemented on the OS, DBMS, Network, and much more.
Lesson to be learned: Always follow the least privilege principle for any system access.
RBAC allows you to control what users are allowed to do and access within your cluster. Kube server API is the front end of the control plane whereas API communicates and interacts with the system to perform a function. RBAC collects those function requests into the API groups that communicate with the API server of certain roles to the API endpoint. For the use case in your team, you can simply use RBAC to allow the developer/observability team to read logs from the kubernetes pod but not to make any changes on k8s resources.
This article walks through the concepts that are at the core of Kubernetes RBAC and demonstrates how to use Kubernetes RBAC with implementation.
Pre-requisites
- Insights about basic Kubernetes components
- Setup already any kubernetes cluster and kubectl
Design
In this article, we will walk through the concepts of kubernetes RBAC, and demonstrate the kubernetes RBAC implementation which is shown in the figure below.
RBAC Objects
Terminologies
- Subjects: Set of users and process that wants to access the kubernetes API.
- Resources: Set of kubernetes API objects available in the cluster.
- Verbs: Set of operations that can be executed to the above resources.
I would say, RBAC is a form of identity and access management (IAM) that involves a set of permissions or templates that determines who (subjects) can execute what (verbs), and where (namespaces or cluster).
Roles
- Defines what can be done to kubernetes resources within a specific namespace.
- It would be set to the default namespace if none was specified for the namespace.
- For the role to be applied cluster-wide, we have an equivalent object called ClusterRole.
- ClusterRole is also non-namespaced and doesn’t bound with the namespace.
- After creating the role, you assign it to a user or group of users by creating RoleBinding.
Create a namespace as backend.
kubectl create ns backend
Filter out the namespace to check whether the backend namespace exists or not.
kubectl get ns -A | grep backend
Create an RBAC role named log-reader that can read secrets in a specific namespace as a backend.
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: backend
name: log-reader
rules:
- API groups: [""]
resources: ["secrets"]
verbs: ["get", "watch", "list"]
kubectl apply -f role.yaml
kubectl get role -A | grep secrets-reader
Use a Role to define a role within a namespace or use a ClusterRole to define cluster-wide.
RoleBinding
- RoleBinding grants permissions within a specific namespace.
- ClusterRoleBinding grants access cluster-wide and to multiple namespaces.
- After creating it, you can’t change the Role that it refers to.
- You need to remove the binding object to change the roleRef.
- You can specify more than one subject too,
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: secrets-reader
namespace: backend
subjects:
- kind: User
name: john
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role
name: secrets-reader
apiGroup: rbac.authorization.k8s.io
kubectl create -f role-binding.yaml
Here is an example of a RoleBinding that grants the “secrets-reader” Role to the user “john” which is case sensitive within the “backend” namespace. This allows “john” to retrieve secrets in the “backend” namespace. roleRef:
specifies the binding to a Role with the kind as Role
type with name as secrets-reader
.
Verify
Let’s check the Roles and RoleBinding associated with it and verify.
kubectl get roles -n backend
kubectl get rolebinding -n backend
kubectl describe rolebinding bind-secrets-reader -n backend
Create a secret named csaju.
echo -n "csaju" > secret.txt
kubectl create secret generic xd -n backend --from-file=./secret.txt
kubectl get secrets -n backend
kubectl get secrets/xd -n backend -o json="{.data}"
Here we created a secret named xd and fetch the value which is encoded in base64.
{"secret.txt":"Y3NhanU="}
Decode the value to verify our secret content.
echo "Y3NhanU=" | base64 -D
As we have created Role and RoleBinding, chance the current kubernetes context with its associated mapped users.
Assumption: here I have already created context as dev with user john.
kubectl config get-contexts
kubectl --context=dev get secrets -n backend
Try out getting the pods where you will get errors regarding permission.
kubectl get pods -n backend
Optional
You can create users in many ways. You can either create certificates for the human user or create a service account for system one. The creation of a user also depends on the public cloud vendor. Those are generally done by an external provider via OIDC. For the on-premise or on your local cluster, you can also try out the below instructions.
- Create user CSR
openssl genrsa -out john.key 2048
openssl req -new -key john.key -out user1.csr
- Approve CSR
openssl x509 -req -in john.csr -CA /etc/kubernetes/pki/ca.crt -CAkey /etc/kubernetes/pki/ca.key -CAcreateserial -out john.crt -days 500
kubectl config view
kubectl config set-credentials john --client-certificate=/root/john.crt --client-key=john.key
kubectl config set-context read-secret --cluster=kubernetes --namespace=backend --user=john
Good Practises for RBAC
- Remove unused roles and RoleBinding that can clutter your cluster and cause confusion.
- Often review your RBAC roles: Policies need to be often audited, so you can remain aware of who can do what inside your cluster.
- Assign permissions at the namespace level on the cluster
- Avoid providing wildcard permission
- Don’t add users easily without verifying to the system: masters group
Conclusion
That’s a wrap! Hope this was helpful to you about RBAC in kubernetes. Until the next incoming blog, happy learning!
Thank you so much for reading and I’d love to hear any feedback you have, please ping me up on Twitter.