CKA — Testing RBAC

6 minute read

CKA Exam Domain

Cluster Architecture, Installation & Configuration — 25%

Setting up RBAC is only half the job — you need to verify that permissions work as expected. On the CKA exam, you’ll be asked to test whether a user or ServiceAccount has specific permissions. This is where kubectl auth can-i becomes your best friend.

kubectl auth can-i

The kubectl auth can-i command checks whether a specific action is allowed. It’s the fastest way to test RBAC permissions.

Test Your Own Permissions

# Can I create Pods?
kubectl auth can-i create pods
# yes

# Can I delete Nodes?
kubectl auth can-i delete nodes
# yes (if you're cluster-admin)

# Can I do everything on everything?
kubectl auth can-i '*' '*'
# yes (cluster-admin) or no

Test as Another User

Use --as to impersonate another user and test their permissions:

# Can jane create Pods?
kubectl auth can-i create pods --as jane
# no

# Can jane create Pods in the dev namespace?
kubectl auth can-i create pods --as jane -n dev
# yes (if she has a RoleBinding there)

# Can jane list Pods in production?
kubectl auth can-i list pods --as jane -n production
# no

Test as a ServiceAccount

ServiceAccount impersonation uses the format system:serviceaccount:<namespace>:<name>:

# Can the my-sa ServiceAccount in dev namespace list Pods?
kubectl auth can-i list pods --as system:serviceaccount:dev:my-sa
# yes/no

# Can it create Deployments?
kubectl auth can-i create deployments --as system:serviceaccount:dev:my-sa -n dev
# yes/no

# Can it access Secrets?
kubectl auth can-i get secrets --as system:serviceaccount:dev:my-sa -n dev
# no (hopefully!)

List All Allowed Actions

Use --list to see everything a user or SA is allowed to do:

# What can I do in the dev namespace?
kubectl auth can-i --list -n dev

# What can jane do in the dev namespace?
kubectl auth can-i --list --as jane -n dev

# What can a ServiceAccount do?
kubectl auth can-i --list --as system:serviceaccount:dev:my-sa -n dev

Output looks like:

Resources                                       Non-Resource URLs   Resource Names   Verbs
pods                                            []                  []               [get list watch]
pods/exec                                       []                  []               [create]
services                                        []                  []               [get list]

Exam tip: kubectl auth can-i --list gives you a complete picture of permissions — very useful for debugging.

Impersonation

The --as and --as-group flags let you impersonate users and groups for testing.

Impersonate a User

# Run any kubectl command as another user
kubectl get pods --as jane -n dev
kubectl get nodes --as jane  # Will fail if jane can't list nodes

Impersonate a Group

# Test what the "developers" group can do
kubectl auth can-i create pods --as jane --as-group developers -n dev
kubectl get pods --as jane --as-group developers -n dev

Impersonate a ServiceAccount

# Run a command as a ServiceAccount
kubectl get pods --as system:serviceaccount:dev:my-sa -n dev

Important: To impersonate, YOU need the impersonate permission. Cluster admins have this by default. Regular users don’t.

The impersonate permission looks like:

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: impersonator
rules:
- apiGroups: [""]
  resources: ["users", "groups", "serviceaccounts"]
  verbs: ["impersonate"]

Debugging Permission Denied

When you get a “forbidden” error, here’s what to check:

Common Error Messages

Error 1: User cannot perform action

Error from server (Forbidden): pods is forbidden: User "jane" cannot list resource "pods" in API group "" in the namespace "production"

This tells you:

  • Who: jane
  • What: list pods
  • Where: production namespace

Error 2: ServiceAccount cannot perform action

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

Debugging Checklist

When permissions aren’t working, check these in order:

1. Does the Role/ClusterRole exist?

kubectl get roles -n dev
kubectl get clusterroles | grep my-role

2. Does the Role have the correct verbs and resources?

kubectl describe role pod-reader -n dev

3. Does a RoleBinding/ClusterRoleBinding exist?

kubectl get rolebindings -n dev
kubectl get clusterrolebindings | grep my-binding

4. Does the binding reference the correct Role?

kubectl describe rolebinding my-binding -n dev
# Check the "Role" section

5. Does the binding reference the correct subject?

kubectl describe rolebinding my-binding -n dev
# Check the "Subjects" section — name, kind, namespace must match

6. Are you in the right namespace?

# A RoleBinding in "dev" doesn't grant access in "staging"
kubectl auth can-i list pods --as jane -n dev      # yes
kubectl auth can-i list pods --as jane -n staging   # no

Audit Logging for RBAC

Kubernetes audit logging can track API requests, including who made them and whether they were allowed or denied. This helps with RBAC debugging in production clusters.

Audit Policy Overview

An audit policy defines what gets logged:

apiVersion: audit.k8s.io/v1
kind: Policy
rules:
- level: RequestResponse
  resources:
  - group: ""
    resources: ["secrets", "configmaps"]
- level: Metadata
  resources:
  - group: "rbac.authorization.k8s.io"
    resources: ["roles", "rolebindings", "clusterroles", "clusterrolebindings"]

Audit levels:

  • None — Don’t log
  • Metadata — Log request metadata (user, timestamp, resource) but not body
  • Request — Log metadata + request body
  • RequestResponse — Log metadata + request + response bodies

CKA note: You probably won’t need to configure audit logging on the exam, but understanding what it does helps with debugging questions.

RBAC Troubleshooting Decision Tree

When you hit a “forbidden” error, follow this tree:

Error: "forbidden"
│
├── Check: Does a RoleBinding/ClusterRoleBinding exist?
│   ├── NO → Create the binding
│   └── YES ↓
│
├── Check: Does the binding reference the correct Role/ClusterRole?
│   ├── NO → Delete and recreate the binding (roleRef is immutable)
│   └── YES ↓
│
├── Check: Does the Role have the correct verbs?
│   ├── NO → Edit the Role to add missing verbs
│   └── YES ↓
│
├── Check: Does the Role have the correct resources?
│   ├── NO → Edit the Role to add missing resources
│   └── YES ↓
│
├── Check: Does the Role have the correct apiGroup?
│   ├── NO → Fix the apiGroup (use kubectl api-resources to find it)
│   └── YES ↓
│
├── Check: Is the namespace correct?
│   ├── NO → Create binding in the correct namespace
│   └── YES ↓
│
└── Check: Does the subject (user/SA) match exactly?
    ├── NO → Fix the subject name/namespace in the binding
    └── YES → Check if another policy (PodSecurityPolicy, OPA) is blocking

Pro tip: 90% of RBAC issues are either a missing binding or a wrong namespace.

Practice Questions

Q1. Check if user alice can delete Pods in the production namespace.

Show Answer
kubectl auth can-i delete pods --as alice -n production

Q2. List all permissions that ServiceAccount monitor-sa in namespace monitoring has.

Show Answer
kubectl auth can-i --list --as system:serviceaccount:monitoring:monitor-sa -n monitoring

Q3. User bob gets “forbidden” when trying to list Pods in namespace dev. The Role pod-reader exists with get/list/watch on Pods. What could be wrong?

Show Answer

Most likely causes:

  1. No RoleBinding exists — Check: kubectl get rolebindings -n dev
  2. RoleBinding exists but references wrong user — Check: kubectl describe rolebinding <name> -n dev and verify the subject name is bob
  3. RoleBinding exists but references wrong Role — Check the roleRef field
  4. RoleBinding is in a different namespace — A RoleBinding in staging doesn’t grant access in dev

Debug:

kubectl get rolebindings -n dev
kubectl describe rolebinding <binding-name> -n dev

Q4. How do you test permissions as a ServiceAccount named deployer in namespace ci?

Show Answer
kubectl auth can-i create deployments --as system:serviceaccount:ci:deployer -n ci

The format is: system:serviceaccount:<namespace>:<name>

You can also run actual commands:

kubectl get pods --as system:serviceaccount:ci:deployer -n ci

Q5. You created a Role and RoleBinding, but kubectl auth can-i still returns “no.” The Role has the correct verbs and resources. What should you check next?

Show Answer

Check these:

  1. apiGroup mismatch — Is the resource in the correct API group? Deployments are in apps, not "".
    kubectl api-resources | grep deployments
    
  2. Subject name mismatch — Does the subject in the RoleBinding exactly match the user/SA name?
    kubectl describe rolebinding <name> -n <namespace>
    
  3. Namespace mismatch — Is the auth can-i command testing the same namespace where the RoleBinding exists?

  4. ServiceAccount namespace — If binding to a SA, did you include the SA’s namespace in the subjects?

Updated: