Kubernetes RBAC – Hands-On Labs and Command Guide

Companion guide for Kubernetes RBAC: Foundations to Essentials (50 slides). Updated 12 November 2026. Examples follow Kubernetes v1.37 API documentation.

Execution status: Commands and YAML have been checked against the official Kubernetes documentation and reviewed for internal consistency. They have not been executed against your specific cluster. Run these labs in a disposable Kubernetes environment, never unreviewed in production.

Prerequisites and safety

  • A working Kubernetes cluster (self-managed Kubernetes is fine; no EKS, AKS, or GKE required).
  • An administrator kubeconfig that can create Namespaces, Roles, RoleBindings, ClusterRoles, ClusterRoleBindings, and CertificateSigningRequests.
  • kubectl, openssl, base64, and a POSIX shell such as Bash.
  • For the human-certificate lab, the Kubernetes control plane must have a working signer for kubernetes.io/kube-apiserver-client. Approval does not force a signer to issue a certificate.
  • kubectl auth can-i --as=... impersonation requires appropriate administrative impersonation permission.
  • Do not commit, email, screen-record, or share a private key or bearer token.
  • Do not send learners a copy of an administrator kubeconfig. Set up separate, restricted learner credentials when needed.

Verify cluster access

kubectl config current-context
kubectl cluster-info
kubectl version --client
kubectl api-resources --api-group=rbac.authorization.k8s.io
kubectl api-resources --namespaced=false

Lab 0 – Create a safe namespace

kubectl create namespace rbac-lab
kubectl -n rbac-lab get pods

Lab 1 – Human user access with Role and RoleBinding

Goal: The named user mia may read Pods in rbac-lab, but may not read Secrets or read Pods in default.

This lab uses a User identity string with administrator impersonation. Kubernetes has no User API object, so there is no kubectl create user step.

Create a Role

kubectl -n rbac-lab create role pod-reader \
  --verb=get,list,watch \
  --resource=pods
kubectl -n rbac-lab describe role pod-reader

Bind the user

kubectl -n rbac-lab create rolebinding mia-read \
  --role=pod-reader \
  --user=mia
kubectl -n rbac-lab describe rolebinding mia-read

Verify three behaviors

# Expected: yes
kubectl auth can-i list pods -n rbac-lab --as=mia

# Expected: no
kubectl auth can-i get secrets -n rbac-lab --as=mia

# Expected: no
kubectl auth can-i list pods -n default --as=mia

The expected results assume a clean training cluster without extra grants for the test identity, and an administrator authorized to impersonate users.

Equivalent declarative manifest

Save as rbac-mia.yaml:

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: pod-reader
  namespace: rbac-lab
rules:
  - apiGroups: [""]
    resources: ["pods"]
    verbs: ["get", "list", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: mia-read
  namespace: rbac-lab
subjects:
  - kind: User
    name: mia
    apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: Role
  name: pod-reader
  apiGroup: rbac.authorization.k8s.io
kubectl diff -f rbac-mia.yaml
kubectl apply -f rbac-mia.yaml

Lab 2 – Real human certificate and group-based access

Goal: Issue a short-duration client certificate for username alice, with group team-dev; before binding the group, Pod access fails; after binding, Pod access succeeds.

Important distinction: alice.csr is a PKCS#10 file created by OpenSSL. A Kubernetes CertificateSigningRequest is an API object containing the base64-encoded request.

1. Generate the private key and certificate request

Run on a trusted workstation. Use a private lab directory.

umask 077
openssl genrsa -out alice.key 3072
openssl req -new -key alice.key -out alice.csr \
  -subj "/CN=alice/O=team-dev"
openssl req -in alice.csr -noout -subject

Expected identity: CN=alice maps to username alice and O=team-dev maps to group team-dev when using this Kubernetes X.509 authentication mechanism.

2. Create the Kubernetes CSR object

Run with credentials allowed to create CertificateSigningRequests.

CSR_B64=$(base64 < alice.csr | tr -d '\n')
cat <<EOF | kubectl apply -f -
apiVersion: certificates.k8s.io/v1
kind: CertificateSigningRequest
metadata:
  name: alice-rbac-lab
spec:
  request: ${CSR_B64}
  signerName: kubernetes.io/kube-apiserver-client
  expirationSeconds: 86400
  usages: ["client auth"]
EOF

This requests one day of validity. The final duration is determined by the issuer’s configuration.

3. Review, approve, and wait for actual issuance

An administrator must verify the requested subject and signer before approval.

kubectl get csr alice-rbac-lab
kubectl get csr alice-rbac-lab -o yaml
kubectl certificate approve alice-rbac-lab
kubectl get csr alice-rbac-lab -o yaml

Do not proceed just because it is Approved. Check .status.certificate is populated. The cluster signer might not be configured. A signer must issue the certificate after approval.

kubectl get csr alice-rbac-lab \
  -o jsonpath='{.status.certificate}' | base64 -d > alice.crt
openssl x509 -in alice.crt -noout -subject -dates

On systems where base64 -d is unavailable, use the equivalent decode option (some BSD tools support -D).

Approving CertificateSigningRequests requires specific permissions beyond simple CSR listing: update on certificatesigningrequests/approval, and approve on the requested signers signer; grant these only to approved certificate authorities/administrators. Refer to the official CSR authorization documentation.

4. Add a user context, without switching the active context

These commands add an alice user context to the current workstation’s kubeconfig, using its existing trusted cluster entry. Never distribute that kubeconfig if it also contains administrator credentials.

CLUSTER=$(kubectl config view --minify \
  -o jsonpath='{.contexts[0].context.cluster}')

kubectl config set-credentials alice \
  --client-certificate=alice.crt \
  --client-key=alice.key \
  --embed-certs=true

kubectl config set-context alice-rbac-lab \
  --cluster="$CLUSTER" \
  --user=alice \
  --namespace=rbac-lab

kubectl --context=alice-rbac-lab auth whoami
kubectl --context=alice-rbac-lab -n rbac-lab get pods

Initially, the last command should produce a Forbidden result because group team-dev is not bound yet. If the identity is not recognized, verify the certificate’s issuer, validity, and subject before changing RBAC.

5. Bind the group and verify the permission

kubectl -n rbac-lab create rolebinding team-dev-read \
  --role=pod-reader \
  --group=team-dev

# Expected: success (a zero-row result is still success)
kubectl --context=alice-rbac-lab -n rbac-lab get pods

# Expected: Forbidden
kubectl --context=alice-rbac-lab -n rbac-lab get secrets

Lab 3 – ServiceAccount identity for an application

Goal: An application ServiceAccount may read ConfigMaps in rbac-lab but not Secrets.

1. Create a ServiceAccount and one ConfigMap

kubectl -n rbac-lab create serviceaccount audit-bot
kubectl -n rbac-lab create configmap demo-config \
  --from-literal=mode=training
kubectl -n rbac-lab get serviceaccounts

The authenticated Kubernetes username for this account is system:serviceaccount:rbac-lab:audit-bot.

2. Define permissions and bind them

kubectl -n rbac-lab create role configmap-reader \
  --verb=get,list \
  --resource=configmaps
kubectl -n rbac-lab create rolebinding audit-config-read \
  --role=configmap-reader \
  --serviceaccount=rbac-lab:audit-bot

3. Create a Pod using that ServiceAccount

Save as sa-demo-pod.yaml:

apiVersion: v1
kind: Pod
metadata:
  name: sa-demo
  namespace: rbac-lab
spec:
  serviceAccountName: audit-bot
  containers:
    - name: app
      image: busybox:1.36
      command: ["sleep", "3600"]
kubectl apply -f sa-demo-pod.yaml
kubectl -n rbac-lab get pod sa-demo
kubectl -n rbac-lab get pod sa-demo -o jsonpath='{.spec.serviceAccountName}'

The Pod image is public but requires outbound registry access to pull. RBAC verification below does not depend on installing kubectl inside the Pod.

4. Verify with admin impersonation

# Expected: yes
kubectl auth can-i list configmaps -n rbac-lab \
  --as=system:serviceaccount:rbac-lab:audit-bot

# Expected: no
kubectl auth can-i get secrets -n rbac-lab \
  --as=system:serviceaccount:rbac-lab:audit-bot

5. Tokens and Pod hardening

# Prints a sensitive short-lived token: never use on a public projector
kubectl -n rbac-lab create token audit-bot --duration=10m

Modern Kubernetes Pods generally use projected, bounded ServiceAccount tokens. If a Pod does not need Kubernetes API access, opt out of automatic token mounting:

spec:
  automountServiceAccountToken: false

Lab 4 – ClusterRole, ClusterRoleBinding, and namespaced reuse

1. Cluster-wide read of Nodes

kubectl create clusterrole lab-node-reader \
  --verb=get,list,watch \
  --resource=nodes

kubectl create clusterrolebinding lab-ops-node-read \
  --clusterrole=lab-node-reader \
  --group=ops-readers

# Expected: yes, on a clean cluster with admin impersonation permission
kubectl auth can-i list nodes \
  --as=pat --as-group=ops-readers

2. Reuse a ClusterRole within just one namespace

kubectl -n rbac-lab create rolebinding qa-view \
  --clusterrole=view --group=qa-team

# Expected: yes
kubectl auth can-i list pods -n rbac-lab \
  --as=lea --as-group=qa-team

# Expected: no
kubectl auth can-i list pods -n default \
  --as=lea --as-group=qa-team

A RoleBinding can reference a ClusterRole, but access is still restricted to that namespace. A ClusterRoleBinding may refer only to a ClusterRole.

Reference: common RBAC rules

A. Read Pod logs (different from permission to read Pods)

rules:
  - apiGroups: [""]
    resources: ["pods/log"]
    verbs: ["get"]

B. Get only a particular ConfigMap

rules:
  - apiGroups: [""]
    resources: ["configmaps"]
    resourceNames: ["demo-config"]
    verbs: ["get"]

resourceNames does not constrain top-level create or deletecollection; list and watch restricted by resourceNames require a matching metadata.name field selector.

C. Read a custom resource (example; requires a matching CRD)

rules:
  - apiGroups: ["example.com"]
    resources: ["widgets"]
    verbs: ["get", "list"]

D. Read a non-resource API path (ClusterRole only)

rules:
  - nonResourceURLs: ["/healthz"]
    verbs: ["get"]

Command summary

PurposeCommand
Show active identitykubectl auth whoami
List API resourceskubectl api-resources -o wide
List namespace Roles / bindingskubectl get roles,rolebindings -n rbac-lab
List cluster-scoped roles / bindingskubectl get clusterroles,clusterrolebindings
Describe a Rolekubectl describe role pod-reader -n rbac-lab
Test read permissionkubectl auth can-i list pods -n rbac-lab
Test as another userkubectl auth can-i list pods -n rbac-lab --as=mia
See the CSR requestkubectl get csr alice-rbac-lab -o yaml
Approve a reviewed CSRkubectl certificate approve alice-rbac-lab
Request a short-lived SA tokenkubectl -n rbac-lab create token audit-bot --duration=10m

Troubleshooting

  • 401 Unauthorized: invalid, missing, or expired credentials; verify certificate trust, token, or kubeconfig selection.
  • 403 Forbidden: commonly insufficient authorization, but admission policy can also reject a request. Check the entire error.
  • --as is rejected: your invoking identity may lack impersonation permission.
  • Unexpected yes: inspect all applicable bindings, default access, and additional authorizers.
  • Approved CSR without certificate: a matching signer might not be configured or willing/able to sign.
  • Group test fails: verify CN/O in certificate and kubectl --context=alice-rbac-lab auth whoami.
  • Pod is Pending / ImagePullBackOff: inspect cluster scheduling and image pull separately from RBAC.
  • A RoleBinding cannot find a Role: verify name, namespace, roleRef.kind, and API group.
  • roleRef cannot be changed: delete and recreate the binding as appropriate, after reviewing downstream access changes.

Cleanup

Run as the administrator after finishing all labs and confirming the resource names belong only to these labs.

kubectl delete namespace rbac-lab
kubectl delete clusterrolebinding lab-ops-node-read
kubectl delete clusterrole lab-node-reader
kubectl delete csr alice-rbac-lab

# Optional cleanup for the local lab kubeconfig (be mindful of its contents)
kubectl config delete-context alice-rbac-lab
kubectl config delete-user alice

# Remove local training-only credentials when no longer needed:
rm -f alice.key alice.csr alice.crt

Instructor quiz – with answers

  1. How can we allow a group to list Pods only in rbac-lab? A Role with a RoleBinding to Group; or view ClusterRole with a RoleBinding in rbac-lab.
  2. Can we create a human user with kubectl create user? No. A normal user identity comes from an authenticator such as client cert or OIDC.
  3. Can ClusterRoleBinding point to Role? No; only to ClusterRole.
  4. What does certificate CN mean? What does O mean? Username and group for Kubernetes X.509 authentication.
  5. Does creating a ServiceAccount grant permissions? No, bind a Role or ClusterRole as needed.
  6. What is the difference between get and list? One named object vs collection of objects.
  7. Does approval guarantee that a CSR has an issued certificate? No, a configured signer must issue it.
  8. Why should edit be considered high privilege? It grants access to Secrets and the ability to run Pods using namespace ServiceAccounts.

Official references

Related Posts

AWS CodeCommit – Complete Step-by-Step Tutorial

Beginner to Advanced | macOS, Linux, Git, SSH, IAM, CodeBuild This master tutorial covers the complete AWS CodeCommit workflow, from creating your first repository to managing source…

Read More

AWS Developer Services: Console Lab Guide

title AWS Developer Services: Gold-Standard Console Lab Guide subtitle CodeCommit • CodeArtifact • CodeBuild • CodeDeploy • CodePipeline author Instructor Edition | Browser-Only Labs date 10 November…

Read More

Oracle Cloud Always Free VPS — Complete Step-by-Step Tutorial

Beginner to Advanced | Updated: November 2, 2026 | Verified against official Oracle Cloud Infrastructure documentation This guide walks you through logging in to Oracle Cloud, configuring…

Read More

Microsoft Sentinel Intermediate: One Complete End-to-End Hands-On Lab – Part – 3

Module 2: Intermediate | Day 3 only | Complete instructor-and-learner manual Edition: 1 November 2026Course: Microsoft Sentinel Technical Training — 5-day progressive curriculumThis document: Day 3 only; prerequisite: successful completion of Foundations…

Read More

Microsoft Sentinel Advance: One Complete End-to-End Hands-On Lab – Part – 4

Module 3: Advanced | Day 4 only | Detection Engineering, Threat Hunting and SOAR Curriculum version: 1 November 2026Course: Five-day progressive Microsoft Sentinel technical trainingThis manual: Day 4 only — syllabus competencies A01–A14Prerequisite: Demonstrated…

Read More

Microsoft Sentinel Advance: One Complete End-to-End Hands-On Lab – Part – 5

Module 3: Advanced | Day 5 only | Enterprise Architecture, Data Lake, DevSecOps and SOC Governance Edition: 1 November 2026Training path: Day 5 of the five-day progressive Microsoft Sentinel programThis manual: Day…

Read More