Understanding Role-Based Access Control (RBAC) in Kubernetes

0

 

Role-Based Access Control, usually called RBAC, is one of the most important security mechanisms in Kubernetes. It defines who can do what against which resources inside a cluster.

In practical terms, RBAC answers questions such as:

  • Can this user read Pods in the dev namespace?
  • Can this group update ConfigMaps in production?
  • Can this application read Secrets at runtime?
  • Can this service account create Deployments?
  • Can this administrator manage resources across the entire cluster?

Without clear access control, a Kubernetes cluster quickly becomes too permissive. That might be acceptable in a local learning environment, but it is not acceptable for a serious production cluster.

Why RBAC Matters

Kubernetes is API-driven. When you create a Pod, update a Deployment, read logs, execute a command inside a container, or list Secrets, you are interacting with the Kubernetes API server.

RBAC regulates these interactions. It allows cluster administrators to define fine-grained permissions for different identities:

  • human users;
  • user groups;
  • service accounts used by applications and automation.

The key idea is simple: each identity should only receive the permissions it actually needs. This is usually called the principle of least privilege.

For example, a developer might need permission to read Pods and logs in a development namespace, but not permission to read production Secrets. A monitoring application might need read-only access to Pods across namespaces, but it should not be able to delete Deployments. A CI/CD pipeline might need permission to update Deployments, but only in a specific namespace.

RBAC gives you the building blocks to express these boundaries.

The Core RBAC Objects

Kubernetes RBAC is built around four main API objects:

ObjectScopePurpose
RoleNamespaceDefines permissions inside one namespace.
RoleBindingNamespaceAssigns a Role or ClusterRole to users, groups, or service accounts inside a namespace.
ClusterRoleCluster-wideDefines permissions that are not tied to one namespace.
ClusterRoleBindingCluster-wideAssigns a ClusterRole across the entire cluster.

A common source of confusion is the difference between a role and a binding.

Role or ClusterRole only defines permissions. It does not give those permissions to anyone by itself. A RoleBinding or ClusterRoleBinding connects those permissions to one or more subjects.

In other words:

Role or ClusterRole = what is allowed
RoleBinding or ClusterRoleBinding = who receives it

Subjects: Users, Groups, and Service Accounts

RBAC policies are applied to subjects. A subject can be one of three things.

Users

A user usually represents a human being. For example, alice@example.com or bob could be authenticated users. Kubernetes itself does not manage normal user accounts in the same way that it manages Pods or ConfigMaps. Instead, the API server receives the authenticated username from the configured authentication mechanism, such as a certificate, OIDC provider, or cloud identity integration.

Groups

A group represents a collection of users. For example, a devs group might include Bob and Charlie. Permissions granted to a group are effectively inherited by all users in that group.

This is useful because you usually do not want to manage permissions user by user. It is easier to grant a group read-only access to production than to create the same binding for every individual developer.

Service Accounts

A service account represents an application or workload running inside the cluster. For example, a Pod that needs to call the Kubernetes API should use a service account, not a human user identity.

This is important for automation. A controller, operator, CI/CD agent, monitoring agent, or internal application can receive only the permissions it needs through its service account.

Roles: Permissions Inside a Namespace

Role defines permissions within a specific namespace. It contains one or more rules. Each rule usually contains:

  • apiGroups: the API group of the resource;
  • resources: the resources the rule applies to;
  • verbs: the allowed actions.

Here is a simple read-only Role for Pods in the dev namespace:

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

The empty string in apiGroups: [""] means the core Kubernetes API group. Core resources include objects such as Pods, Services, ConfigMaps, and Secrets.

The verbs describe the allowed operations. Common verbs include:

VerbMeaning
getRead one specific object.
listList multiple objects.
watchWatch changes over time.
createCreate a new object.
updateReplace or update an object.
patchPartially update an object.
deleteDelete an object.

Role is namespaced. If you create a Role in the dev namespace, it does not automatically apply to the prod namespace.

RoleBindings: Assigning a Role

RoleBinding assigns permissions to a subject inside a namespace.

For example, this binding gives Bob the pod-reader role in the dev namespace:

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: bob-pod-reader
  namespace: dev
subjects:
  - kind: User
    name: bob@example.com
    apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: Role
  name: pod-reader
  apiGroup: rbac.authorization.k8s.io

After this binding exists, Bob can read Pods in dev. He cannot automatically read Pods in prod, because the binding is namespaced.

RoleBinding can also refer to a ClusterRole. When this happens, the ClusterRole permissions are granted only inside the namespace of the RoleBinding. This is a useful pattern when you want to define a reusable cluster-wide role, such as view, but grant it namespace by namespace.

ClusterRoles: Permissions Across the Cluster

ClusterRole is similar to a Role, but it is not bound to a single namespace.

You use a ClusterRole when you need to define permissions for:

  • cluster-scoped resources, such as Nodes;
  • non-resource URLs, such as health endpoints;
  • namespaced resources across many or all namespaces.

For example, this ClusterRole allows read-only access to Pods across namespaces when bound with a ClusterRoleBinding:

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

ClusterRole still does not grant access by itself. It only defines the permission set.

ClusterRoleBindings: Assigning Cluster-Wide Permissions

ClusterRoleBinding assigns a ClusterRole across the whole cluster.

For example, this gives Alice cluster-admin permissions:

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: alice-cluster-admin
subjects:
  - kind: User
    name: alice@example.com
    apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: cluster-admin
  apiGroup: rbac.authorization.k8s.io

This is powerful and dangerous. The built-in cluster-admin role gives broad administrative access. It should be used only when truly necessary.

In most cases, prefer a namespace-level RoleBinding over a cluster-wide ClusterRoleBinding. This reduces the blast radius if credentials are leaked or misused.

A Practical RBAC Example

Imagine a cluster with two namespaces:

  • dev;
  • prod.

And three users:

  • Alice;
  • Bob;
  • Charlie.

Bob and Charlie are also members of the devs group.

Now imagine the following RBAC setup:

IdentityBindingEffective Access
AliceClusterRoleBinding to cluster-adminFull cluster administration.
BobRoleBinding to dev-admin in devCan create, read, update, and delete selected resources in dev.
BobGroup membership in devsAlso receives permissions granted to the devs group.
CharlieRoleBinding to dev-readonly in devCan read selected resources in dev.
devs groupRoleBinding to prod-readonly in prodBob and Charlie can read selected production resources.
Application PodServiceAccount bound to dev-readonlyThe Pod can read only the resources needed at runtime.

This demonstrates an important RBAC behavior: permissions are additive.

If Bob receives permissions directly as a user and also through a group, Kubernetes combines those permissions. RBAC does not have explicit deny rules. You restrict access by not granting unnecessary permissions in the first place.

Service Accounts for Pods

When a Pod needs to interact with the Kubernetes API, you should give that Pod a service account with narrowly scoped permissions.

For example, suppose an application in the dev namespace needs to read ConfigMaps at runtime. You could create a service account and bind it to a role that only allows reading ConfigMaps:

apiVersion: v1
kind: ServiceAccount
metadata:
  name: config-reader
  namespace: dev
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: configmap-reader
  namespace: dev
rules:
  - apiGroups: [""]
    resources: ["configmaps"]
    verbs: ["get", "list", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: config-reader-binding
  namespace: dev
subjects:
  - kind: ServiceAccount
    name: config-reader
    namespace: dev
roleRef:
  kind: Role
  name: configmap-reader
  apiGroup: rbac.authorization.k8s.io

Then the Pod can use that service account:

apiVersion: v1
kind: Pod
metadata:
  name: app
  namespace: dev
spec:
  serviceAccountName: config-reader
  containers:
    - name: app
      image: nginx:1.27

This is much safer than running the Pod with a highly privileged default service account.

Be Careful With Secrets and Subresources

Not all read permissions are harmless.

For example, allowing getlist, or watch on Secrets can expose sensitive data. Even list and watch can be dangerous because the returned objects include Secret contents.

You should also pay attention to Kubernetes subresources. Pod logs are represented as pods/log. Executing a command inside a Pod uses the pods/exec subresource. These should be granted explicitly only when required.

Example role that allows reading Pods and Pod logs:

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

Do not grant broad wildcard permissions such as this unless you have a very strong reason:

rules:
  - apiGroups: ["*"]
    resources: ["*"]
    verbs: ["*"]

This kind of rule can accidentally grant access to current and future resources, including custom resources and sensitive subresources.

Checking Permissions With kubectl

Kubernetes gives you a useful command for testing access:

kubectl auth can-i list pods --namespace dev

You can also impersonate a user or service account for testing:

kubectl auth can-i get secrets \
  --namespace prod \
  --as bob@example.com

For a service account, use the full service account username format:

kubectl auth can-i get configmaps \
  --namespace dev \
  --as system:serviceaccount:dev:config-reader

This is very useful when debugging permission problems or verifying that a role is not too permissive.

RBAC Best Practices

Good RBAC design is not only about making access work. It is about making access safe, understandable, and maintainable.

Use these principles as a baseline:

  • Grant the minimum permissions required.
  • Prefer namespace-level RoleBinding objects over cluster-wide ClusterRoleBinding objects.
  • Avoid cluster-admin for normal daily work.
  • Avoid wildcard permissions such as resources: ["*"] and verbs: ["*"].
  • Be careful with Secrets, pods/exec, and other sensitive subresources.
  • Use groups instead of individual user bindings where possible.
  • Give workloads dedicated service accounts instead of relying on the default service account.
  • Periodically review existing roles and bindings.
  • Test permissions with kubectl auth can-i.

Conclusion

RBAC is a must-have for any serious Kubernetes cluster. It gives you a structured way to define access for humans, groups, applications, and automation.

The model is built from a small number of objects:

  • Role defines namespaced permissions;
  • RoleBinding grants namespaced permissions to subjects;
  • ClusterRole defines cluster-wide or reusable permissions;
  • ClusterRoleBinding grants cluster-wide permissions to subjects.

Once you understand how these pieces fit together, Kubernetes access control becomes much easier to reason about. You can give developers access to development resources, limit production access, allow applications to read only what they need, and keep administrative permissions under control.

The goal is not only to make things work. The goal is to make sure the right identity has the right access, in the right namespace, for the right reason.

Sources

  • Kubernetes documentation: Using RBAC Authorization - kubernetes.io/docs/reference/access-authn-authz/rbac/
  • Kubernetes documentation: Role Based Access Control Good Practices - kubernetes.io/docs/concepts/security/rbac-good-practices/
  • Kubernetes documentation: The Kubernetes API - kubernetes.io/docs/concepts/overview/kubernetes-api/

Post a Comment

0 Comments

Post a Comment (0)

#buttons=(Ok, Go it!) #days=(20)

This site uses cookies from Google to deliver its services and analyze traffic. Your IP address and user-agent are shared with Google along with performance and security metrics to ensure quality of service, generate usage statistics, and to detect and address abuse. More Info
Ok, Go it!