Skip to content

Kubernetes RBAC Forbidden Access Fix

DodaTech Updated 2026-06-24 3 min read

In this tutorial, you'll learn about Kubernetes RBAC Forbidden Access Fix. We cover key concepts, practical examples, and best practices.

The Problem

A user, service account, or pod gets a Forbidden error:

Error from server (Forbidden): pods is forbidden: User "system:serviceaccount:default:my-sa" cannot list resource "pods" in API group "" in the namespace "default"

Or from within a pod:

$ kubectl get pods
Error from server (Forbidden): pods is forbidden

Kubernetes RBAC denies the request because no Role or ClusterRole grants the required permission to the user or service account.

Quick Fix

Step 1: Identify the subject and the missing permission

The error message tells you exactly what is missing:

User "system:serviceaccount:default:my-sa"
cannot list resource "pods"
in API group ""
  • Subject: my-sa in namespace default
  • Verb: list
  • Resource: pods
  • API group: "" (core group)

Step 2: Check current RBAC bindings

kubectl get rolebindings,clusterrolebindings -A | grep my-sa

If nothing matches, the subject has no bindings.

Step 3: Create the necessary Role and RoleBinding

WRONG -- no binding exists for the service account:

kubectl get pods --as=system:serviceaccount:default:my-sa
# Error from server (Forbidden): pods is forbidden

RIGHT -- create a Role with the required permissions:

kubectl create role pod-reader --verb=get,list,watch --resource=pods

kubectl create rolebinding pod-reader-binding \
  --role=pod-reader \
  --serviceaccount=default:my-sa

Now test again:

kubectl get pods --as=system:serviceaccount:default:my-sa
# Success

Step 4: Use ClusterRole for cluster-scoped permissions

If the subject needs permissions across all namespaces:

kubectl create clusterrole pod-reader --verb=get,list,watch --resource=pods

kubectl create clusterrolebinding pod-reader-binding \
  --clusterrole=pod-reader \
  --serviceaccount=default:my-sa

Step 5: Check for AggregateRoles

Some ClusterRoles aggregate sub-roles. If a custom role is not showing up, it may need a label:

kubectl describe clusterrole admin
AggregationRule:
  ClusterRoleSelectors:
    matchLabels:
      rbac.authorization.k8s.io/aggregate-to-admin: "true"

Add the matching label to your ClusterRole:

metadata:
  labels:
    rbac.authorization.k8s.io/aggregate-to-admin: "true"

Step 6: Verify permissions with kubectl auth can-i

kubectl auth can-i list pods --as=system:serviceaccount:default:my-sa
kubectl auth can-i create deployments --as=system:serviceaccount:default:my-sa
yes
no

This is faster than trial-and-error. Use it in scripts to validate permissions before running commands.

Use DodaTech's RBAC Analyzer to visualize role bindings, identify missing permissions, and simulate access before applying RBAC changes.

Prevention

  • Follow the principle of least privilege: grant only the minimum required permissions.
  • Use kubectl auth can-i in CI/CD to validate permissions before deployments.
  • Use Kubernetes audit logs to detect Forbidden errors.
  • Name RoleBindings clearly to indicate which subject and role they bind.
  • Avoid using cluster-admin for application service accounts.

Common Mistakes with rbac forbidden

  1. Forgetting deriving (Show, Eq) on custom data types needed for debugging
  2. Placing the wildcard pattern first in case expressions, making all subsequent patterns unreachable
  3. Using head and tail instead of pattern matching, causing runtime errors on empty lists

These mistakes appear frequently in real-world K8S code. DodaTech's contributors have identified these patterns through analysis of open-source projects and production systems.

Practice Exercise

Write a pure function that safely divides two integers using Maybe, then test it with edge cases like division by zero and negative numbers.

This exercise reinforces the concepts covered in this guide. Try implementing it before checking online solutions.

FAQ

### What is the difference between Role and ClusterRole?

A Role grants permissions within a single namespace. A ClusterRole grants permissions cluster-wide (across all namespaces) and also applies to cluster-scoped resources like nodes and namespaces themselves.

Why does my pod get Forbidden when running kubectl from inside?

By default, pods run with the default service account, which has no permissions. Create a dedicated service account, bind a Role to it, and set spec.serviceAccountName in your pod spec to use it.

How do I make kubectl auth can-i work for a service account?

Use the --as flag with the full username format: system:serviceaccount:<namespace>:<sa-name>. For example: kubectl auth can-i get pods --as=system:serviceaccount:default:my-sa.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro