Understanding RBAC: A Pillar of Kubernetes Security

Understanding RBAC: A Pillar of Kubernetes Security

As organizations adopt Kubernetes to manage their containerized applications, the need for robust security mechanisms has become more critical than ever. One of the foundational components of Kubernetes security is Role-Based Access Control (RBAC). This article delves into what RBAC is, how it works, and why it is indispensable for securing Kubernetes clusters.

What is RBAC?

Role-Based Access Control (RBAC) is a method of regulating access to resources based on the roles of individual users within an organization. In Kubernetes, RBAC is used to define what actions users or service accounts can perform on specific resources in the cluster. It provides a fine-grained control mechanism, ensuring that only authorized entities can access or modify resources.

How it works?

In Kubernetes, there are two types of accounts

  • User Account

  • Service Account

User account: User accounts are used to log into a Kubernetes cluster and manipulate resources therein. Each user account is associated with a unique set of credentials, which are used to authenticate the service’s requests.

Service Account: Kubernetes Service Accounts are specialised accounts used by applications and services running on Kubernetes to interact with the Kubernetes API.

Here are the simple terms to understand user & service accounts:

  • User Account: Represents a person accessing the cluster (e.g., via kubectl).

  • Service Account: Represents an application or pod accessing the cluster.

  • User Authentication: Managed externally (e.g., OIDC, certificates).

  • Service Account Authentication: Managed by Kubernetes with tokens.

  • User Scope: Cluster-wide.

  • Service Account Scope: Usually tied to a namespace.

Which account type should you use?

Use a User Account: When a human needs to interact with the Kubernetes cluster, such as developers, admins, or operators using tools like kubectl.

Use a Service Account: When an application or workload running inside the cluster needs to access Kubernetes resources programmatically.

Ex: A pod might use a service account to access ConfigMaps or Secrets within a specific namespace.

Lets do some hands on:

Lets create a user, But Kubernetes API will not allow us to create user directly. so there are multiple ways to create user

  • client certificates

  • bearer tokens

  • authenticating proxy

  • HTTP basic auth.

I will choose client certificate to create a user which is very easy to create.

This certificates are used to create users. When a user perform any command like kubectl get po then K8's API will authenticate and authorize the request.

authentication: permission to login.

authorization: permission to work on resources.

Steps to create certificate:

  • lets create a folder:

      mkdir mustafa-user && cd mustafa-user
    
  • Generate a key using openssl :

      openssl genrsa -out mustafa.key 2048
    
  • Generate a Client Sign Request (CSR) :

      openssl req -new -key mustafa.key -out mustafa.csr -subj "/CN=mustafa/O=group1"
    
  • Generate the certificate (CRT):

      openssl x509 -req -in mustafa.csr -CA ~/.minikube/ca.crt -CAkey ~/.minikube/ca.key -CAcreateserial -out mustafa.crt -days 500
    

Steps to create user.

  • lets create a user:

      kubectl config set-credentials mustafa --client-certificate=mustafa.crt --client-key=mustafa.key
    

Till now we created user and certificates, but we didn’t add that user to our cluster. Lets do it!

  • Set a context entry in kubeconfig:

      kubectl config set-context my-context --cluster=minikube --user=mustafa
    

Context is used to switch the users in K8s cluster. Because in K8s we cant switch using users, we will add users to context and we will use context to switch b/w users.

  • To see the user:

      kubectl config view
    
  • Switch to devops user:

      kubectl config use-context my-context
    
  • Now lets check to create some resources

    •   kubectl get po
      
    •   kubectl run pod-1 --image=nginx
      
    •   kubectl create ns dev
      
  • ok! thats cool, thats won’t work, just come back to minikube config and perform same commands, that will work. (kubectl config use-context minikube)

  • because we created user and attached that user to cluster. But we didn’t mention permissions for that user. minikube context is a admin user which will have all permissions by default

  • so lets create a role and attach that role to user.

There are four components to RBAC in Kubernetes:

  • roles

  • Cluster roles

  • role bindings

  • ClusterRolesBinding

  1. Roles are the basic building blocks of RBAC. A role defines a set of permissions for a user or group. For example, you might create a role called “admin” that gives the user or group full access to all resources in the cluster.

(or)

Role is a set of permissions that define what actions (verbs) are allowed on specific resources (API groups and resources) within a particular Namespace.

Roles are Namespace-scoped, meaning they apply only to resources within that Namespace.

  1. ClusterRoles are special roles that apply to all users in the cluster. For example, you might create a ClusterRole called “cluster-admin” that gives the user or group full access to all resources in the cluster. These are not Namespace-specific. They define permissions for cluster-wide resources.

  2. Role bindings connect users/groups to roles. For example, you might bind the “admin” role to the “admin” user. This would give the “admin” user all the permissions defined in the “admin” role.

    It grants the permissions to particular namespaces only.

  3. ClusterRoleBindings similar to RoleBindings, ClusterRoleBindings associate ClusterRoles with users/groups across the entire cluster.

    These are not Namespace-specific. They grants the permissions for cluster-wide resources.

Lets create a namespace called dev :

kubectl create ns dev

Now lets create a role that gives permissions to K8s resources

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

apply it:

kubectl create -f role.yml

Imperative way :

kubectl create role admin --verb=get,list,watch,create,update,delete --resource=pods,deployments -n dev

Check it :

kubectl get role -n dev

Let me tell you the differences between get, list and watch

  • get:

    • Purpose: Allows you to retrieve a single resource or a specific instance of a resource.

    • Ex: kubectl get pod pod-name

  • list:

    • Purpose: Allows you to retrieve a list of resources, such as all pods in a namespace.

    • Ex: kubectl get pods

  • watch:

    • Purpose: Allows you to continuously monitor and receive updates when the state of a resource changes.

    • Ex: kubectl get pods --watch

Now attach this dev-role to user (Role binding):

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: dev-role-binding
  namespace: dev
subjects:
- kind: User
  name: mustafa
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: Role
  name: dev-role
  apiGroup: rbac.authorization.k8s.io

apply it:

kubectl create -f rolebinding.yml

Imperative way :

kubectl create rolebinding role-binding-name --role=role-name --user=user-name

we can also check with the permissions :

check it:

kubectl get rolebinding -n dev

To check the permissions:

kubectl auth can-i delete pod --as mustafa

So far we added role and attached that role to user (role binding), Now when we go to dev namespace and login as devops user, we will able to work with pods and deployments only.

Switch to dev ns:

kubectl config set-context --current --namespace=dev

Login as devops user using context :

kubectl config use-context my-context

make sure to check check the configs before going to test the role

kubectl config view --minify

Now we can able to list or get the pods

Note: for only one namespace (dev).

Mustafa user cant get any resources from any other namespaces because we used rolebinding.

If mustafa want to access the resources from all namespaces we can use clusterrolebinding

Working on Cluster Role:

First lets change the context to minikube and go to default namespace

change the contex:

kubectl config use-context minikube

change the default namespace:

kubectl config set-context --current --namespace=default

Lets create cluster role:

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: mustafa-cluster-role
rules:
- apiGroups: [""]
  resources: ["pods", "deployments"]
  verbs: ["get", "watch", "list", "create"]
- apiGroups: [""]
  resources: ["services"]
  verbs: ["get", "watch", "list", "create", "delete"

apply it:

kubectl create -f clusterrole.yml

Imperative way :

kubectl create clusterrole my-cluster-role --verb=get,list,create,update,delete --resource=pods,services

Check it :

kubectl get clusterrole

Lets create cluster role binding:

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: cluster-role-binding
subjects:
- kind: User
  name: mustafa
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: mustafa-cluster-role
  apiGroup: rbac.authorization.k8s.io

After creating the clusterrole and attached that role to cluster role binding, its time to check weather mustafa user can have access to work with resources in all namespaces or not.

Best Practices for RBAC Implementation

  1. Follow the Principle of Least Privilege: Grant users only the permissions they absolutely need.

  2. Use Namespaces: Leverage namespaces to scope access controls effectively.

  3. Audit and Monitor: Regularly audit RBAC policies and monitor access logs to identify potential vulnerabilities.

  4. Automate Policy Management: Use tools like Helm or Kubernetes operators to automate and enforce RBAC policies.

  5. Regular Reviews: Periodically review and update roles and bindings to adapt to changing requirements.

Common Mistakes to Avoid

  • Over-Permissioning Users: Assigning overly broad permissions, such as granting admin roles to non-administrative users.

  • Ignoring Service Accounts: Neglecting to secure service accounts can lead to unintended access.

  • Unmonitored RoleBindings: Failing to track and monitor RoleBindings and ClusterRoleBindings.

Conclusion

RBAC is a cornerstone of Kubernetes security, providing the control needed to safeguard resources in a multi-user environment. By implementing RBAC effectively and adhering to best practices, you can significantly enhance the security posture of your Kubernetes clusters.

Ready to implement RBAC in your Kubernetes setup? Let me know your thoughts or questions in the comments below!

If you love stories that inspire learning, growth, and productivity, consider subscribing for more! If this article added value to your journey, your support would mean the world to me — only if it’s within your means. Let’s stay connected on LinkedIn too. Thank you for reading!