{"id":1282,"date":"2026-11-12T07:24:31","date_gmt":"2026-11-12T07:24:31","guid":{"rendered":"https:\/\/www.devopsschool.com\/tutorials\/?p=1282"},"modified":"2026-11-12T07:24:32","modified_gmt":"2026-11-12T07:24:32","slug":"kubernetes-rbac-hands-on-labs-and-command-guide","status":"publish","type":"post","link":"https:\/\/www.devopsschool.com\/tutorials\/kubernetes-rbac-hands-on-labs-and-command-guide\/","title":{"rendered":"Kubernetes RBAC &#8211; Hands-On Labs and Command Guide"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">Companion guide for&nbsp;<strong>Kubernetes RBAC: Foundations to Essentials (50 slides)<\/strong>. Updated 12 November 2026. Examples follow Kubernetes v1.37 API documentation.<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p class=\"wp-block-paragraph\"><strong>Execution status:<\/strong>&nbsp;Commands and YAML have been checked against the official Kubernetes documentation and reviewed for internal consistency. They have&nbsp;<strong>not<\/strong>&nbsp;been executed against your specific cluster. Run these labs in a disposable Kubernetes environment, never unreviewed in production.<\/p>\n<\/blockquote>\n\n\n\n<h2 class=\"wp-block-heading\">Prerequisites and safety<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li>A working Kubernetes cluster (self-managed Kubernetes is fine; no EKS, AKS, or GKE required).<\/li>\n\n\n\n<li>An administrator kubeconfig that can create Namespaces, Roles, RoleBindings, ClusterRoles, ClusterRoleBindings, and CertificateSigningRequests.<\/li>\n\n\n\n<li><code>kubectl<\/code>,\u00a0<code>openssl<\/code>,\u00a0<code>base64<\/code>, and a POSIX shell such as Bash.<\/li>\n\n\n\n<li>For the human-certificate lab, the Kubernetes control plane must have a working signer for\u00a0<code>kubernetes.io\/kube-apiserver-client<\/code>. Approval does not force a signer to issue a certificate.<\/li>\n\n\n\n<li><code>kubectl auth can-i --as=...<\/code>\u00a0impersonation requires appropriate administrative impersonation permission.<\/li>\n\n\n\n<li>Do not commit, email, screen-record, or share a private key or bearer token.<\/li>\n\n\n\n<li>Do not send learners a copy of an administrator kubeconfig. Set up separate, restricted learner credentials when needed.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Verify cluster access<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>kubectl config current-context\nkubectl cluster-info\nkubectl version --client\nkubectl api-resources --api-group=rbac.authorization.k8s.io\nkubectl api-resources --namespaced=false\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Lab 0 &#8211; Create a safe namespace<\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code>kubectl create namespace rbac-lab\nkubectl -n rbac-lab get pods\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Lab 1 &#8211; Human user access with Role and RoleBinding<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Goal:<\/strong>&nbsp;The named user&nbsp;<code>mia<\/code>&nbsp;may read Pods in&nbsp;<code>rbac-lab<\/code>, but may not read Secrets or read Pods in&nbsp;<code>default<\/code>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">This lab uses a User&nbsp;<strong>identity string<\/strong>&nbsp;with administrator impersonation. Kubernetes has no&nbsp;<code>User<\/code>&nbsp;API object, so there is no&nbsp;<code>kubectl create user<\/code>&nbsp;step.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Create a Role<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>kubectl -n rbac-lab create role pod-reader \\\n  --verb=get,list,watch \\\n  --resource=pods\nkubectl -n rbac-lab describe role pod-reader\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Bind the user<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>kubectl -n rbac-lab create rolebinding mia-read \\\n  --role=pod-reader \\\n  --user=mia\nkubectl -n rbac-lab describe rolebinding mia-read\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Verify three behaviors<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code><em># Expected: yes<\/em>\nkubectl auth can-i list pods -n rbac-lab --as=mia\n\n<em># Expected: no<\/em>\nkubectl auth can-i get secrets -n rbac-lab --as=mia\n\n<em># Expected: no<\/em>\nkubectl auth can-i list pods -n default --as=mia\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The expected results assume a clean training cluster without extra grants for the test identity, and an administrator authorized to impersonate users.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Equivalent declarative manifest<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Save as&nbsp;<code>rbac-mia.yaml<\/code>:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>apiVersion: rbac.authorization.k8s.io\/v1\nkind: Role\nmetadata:\n  name: pod-reader\n  namespace: rbac-lab\nrules:\n  - apiGroups: &#91;\"\"]\n    resources: &#91;\"pods\"]\n    verbs: &#91;\"get\", \"list\", \"watch\"]\n---\napiVersion: rbac.authorization.k8s.io\/v1\nkind: RoleBinding\nmetadata:\n  name: mia-read\n  namespace: rbac-lab\nsubjects:\n  - kind: User\n    name: mia\n    apiGroup: rbac.authorization.k8s.io\nroleRef:\n  kind: Role\n  name: pod-reader\n  apiGroup: rbac.authorization.k8s.io\n<\/code><\/pre>\n\n\n\n<pre class=\"wp-block-code\"><code>kubectl diff -f rbac-mia.yaml\nkubectl apply -f rbac-mia.yaml\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Lab 2 &#8211; Real human certificate and group-based access<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Goal:<\/strong>&nbsp;Issue a short-duration client certificate for username&nbsp;<code>alice<\/code>, with group&nbsp;<code>team-dev<\/code>; before binding the group, Pod access fails; after binding, Pod access succeeds.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Important distinction:<\/strong>&nbsp;<code>alice.csr<\/code>&nbsp;is a PKCS#10 file created by OpenSSL. A Kubernetes&nbsp;<code>CertificateSigningRequest<\/code>&nbsp;is an API object containing the base64-encoded request.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">1. Generate the private key and certificate request<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Run on a trusted workstation. Use a private lab directory.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>umask 077\nopenssl genrsa -out alice.key 3072\nopenssl req -new -key alice.key -out alice.csr \\\n  -subj \"\/CN=alice\/O=team-dev\"\nopenssl req -in alice.csr -noout -subject\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Expected identity:&nbsp;<code>CN=alice<\/code>&nbsp;maps to username&nbsp;<code>alice<\/code>&nbsp;and&nbsp;<code>O=team-dev<\/code>&nbsp;maps to group&nbsp;<code>team-dev<\/code>&nbsp;when using this Kubernetes X.509 authentication mechanism.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">2. Create the Kubernetes CSR object<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Run with credentials allowed to create CertificateSigningRequests.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>CSR_B64=$(base64 &lt; alice.csr | tr -d '\\n')\ncat &lt;&lt;EOF | kubectl apply -f -\napiVersion: certificates.k8s.io\/v1\nkind: CertificateSigningRequest\nmetadata:\n  name: alice-rbac-lab\nspec:\n  request: ${CSR_B64}\n  signerName: kubernetes.io\/kube-apiserver-client\n  expirationSeconds: 86400\n  usages: &#91;\"client auth\"]\nEOF\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">This requests one day of validity. The final duration is determined by the issuer&#8217;s configuration.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">3. Review, approve, and wait for actual issuance<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">An administrator must verify the requested subject and signer before approval.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>kubectl get csr alice-rbac-lab\nkubectl get csr alice-rbac-lab -o yaml\nkubectl certificate approve alice-rbac-lab\nkubectl get csr alice-rbac-lab -o yaml\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Do&nbsp;<strong>not<\/strong>&nbsp;proceed just because it is&nbsp;<code>Approved<\/code>. Check&nbsp;<code>.status.certificate<\/code>&nbsp;is populated. The cluster signer might not be configured. A signer must issue the certificate after approval.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>kubectl get csr alice-rbac-lab \\\n  -o jsonpath='{.status.certificate}' | base64 -d &gt; alice.crt\nopenssl x509 -in alice.crt -noout -subject -dates\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">On systems where&nbsp;<code>base64 -d<\/code>&nbsp;is unavailable, use the equivalent decode option (some BSD tools support&nbsp;<code>-D<\/code>).<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Approving CertificateSigningRequests requires specific permissions beyond simple CSR listing:&nbsp;<code>update<\/code>&nbsp;on&nbsp;<code>certificatesigningrequests\/approval<\/code>, and&nbsp;<code>approve<\/code>&nbsp;on the requested&nbsp;<code>signers<\/code>&nbsp;signer; grant these only to approved certificate authorities\/administrators. Refer to the official CSR authorization documentation.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">4. Add a user context, without switching the active context<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">These commands add an&nbsp;<code>alice<\/code>&nbsp;user context to&nbsp;<strong>the current workstation&#8217;s kubeconfig<\/strong>, using its existing trusted cluster entry.&nbsp;<strong>Never distribute that kubeconfig if it also contains administrator credentials.<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>CLUSTER=$(kubectl config view --minify \\\n  -o jsonpath='{.contexts&#91;0].context.cluster}')\n\nkubectl config set-credentials alice \\\n  --client-certificate=alice.crt \\\n  --client-key=alice.key \\\n  --embed-certs=true\n\nkubectl config set-context alice-rbac-lab \\\n  --cluster=\"$CLUSTER\" \\\n  --user=alice \\\n  --namespace=rbac-lab\n\nkubectl --context=alice-rbac-lab auth whoami\nkubectl --context=alice-rbac-lab -n rbac-lab get pods\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Initially, the last command should produce a&nbsp;<code>Forbidden<\/code>&nbsp;result because group&nbsp;<code>team-dev<\/code>&nbsp;is not bound yet. If the identity is not recognized, verify the certificate&#8217;s issuer, validity, and subject before changing RBAC.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">5. Bind the group and verify the permission<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>kubectl -n rbac-lab create rolebinding team-dev-read \\\n  --role=pod-reader \\\n  --group=team-dev\n\n<em># Expected: success (a zero-row result is still success)<\/em>\nkubectl --context=alice-rbac-lab -n rbac-lab get pods\n\n<em># Expected: Forbidden<\/em>\nkubectl --context=alice-rbac-lab -n rbac-lab get secrets\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Lab 3 &#8211; ServiceAccount identity for an application<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Goal:<\/strong>&nbsp;An application ServiceAccount may read ConfigMaps in&nbsp;<code>rbac-lab<\/code>&nbsp;but not Secrets.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">1. Create a ServiceAccount and one ConfigMap<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>kubectl -n rbac-lab create serviceaccount audit-bot\nkubectl -n rbac-lab create configmap demo-config \\\n  --from-literal=mode=training\nkubectl -n rbac-lab get serviceaccounts\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The authenticated Kubernetes username for this account is&nbsp;<code>system:serviceaccount:rbac-lab:audit-bot<\/code>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">2. Define permissions and bind them<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>kubectl -n rbac-lab create role configmap-reader \\\n  --verb=get,list \\\n  --resource=configmaps\nkubectl -n rbac-lab create rolebinding audit-config-read \\\n  --role=configmap-reader \\\n  --serviceaccount=rbac-lab:audit-bot\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">3. Create a Pod using that ServiceAccount<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Save as&nbsp;<code>sa-demo-pod.yaml<\/code>:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>apiVersion: v1\nkind: Pod\nmetadata:\n  name: sa-demo\n  namespace: rbac-lab\nspec:\n  serviceAccountName: audit-bot\n  containers:\n    - name: app\n      image: busybox:1.36\n      command: &#91;\"sleep\", \"3600\"]\n<\/code><\/pre>\n\n\n\n<pre class=\"wp-block-code\"><code>kubectl apply -f sa-demo-pod.yaml\nkubectl -n rbac-lab get pod sa-demo\nkubectl -n rbac-lab get pod sa-demo -o jsonpath='{.spec.serviceAccountName}'\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The Pod image is public but requires outbound registry access to pull. RBAC verification below does not depend on installing&nbsp;<code>kubectl<\/code>&nbsp;inside the Pod.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">4. Verify with admin impersonation<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code><em># Expected: yes<\/em>\nkubectl auth can-i list configmaps -n rbac-lab \\\n  --as=system:serviceaccount:rbac-lab:audit-bot\n\n<em># Expected: no<\/em>\nkubectl auth can-i get secrets -n rbac-lab \\\n  --as=system:serviceaccount:rbac-lab:audit-bot\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">5. Tokens and Pod hardening<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code><em># Prints a sensitive short-lived token: never use on a public projector<\/em>\nkubectl -n rbac-lab create token audit-bot --duration=10m\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Modern Kubernetes Pods generally use projected, bounded ServiceAccount tokens. If a Pod does not need Kubernetes API access, opt out of automatic token mounting:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>spec:\n  automountServiceAccountToken: false\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Lab 4 &#8211; ClusterRole, ClusterRoleBinding, and namespaced reuse<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">1. Cluster-wide read of Nodes<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>kubectl create clusterrole lab-node-reader \\\n  --verb=get,list,watch \\\n  --resource=nodes\n\nkubectl create clusterrolebinding lab-ops-node-read \\\n  --clusterrole=lab-node-reader \\\n  --group=ops-readers\n\n<em># Expected: yes, on a clean cluster with admin impersonation permission<\/em>\nkubectl auth can-i list nodes \\\n  --as=pat --as-group=ops-readers\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">2. Reuse a ClusterRole within just one namespace<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>kubectl -n rbac-lab create rolebinding qa-view \\\n  --clusterrole=view --group=qa-team\n\n<em># Expected: yes<\/em>\nkubectl auth can-i list pods -n rbac-lab \\\n  --as=lea --as-group=qa-team\n\n<em># Expected: no<\/em>\nkubectl auth can-i list pods -n default \\\n  --as=lea --as-group=qa-team\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">A&nbsp;<code>RoleBinding<\/code>&nbsp;can reference a&nbsp;<code>ClusterRole<\/code>, but access is still restricted to that namespace. A&nbsp;<code>ClusterRoleBinding<\/code>&nbsp;may refer&nbsp;<strong>only<\/strong>&nbsp;to a&nbsp;<code>ClusterRole<\/code>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Reference: common RBAC rules<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">A. Read Pod logs (different from permission to read Pods)<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>rules:\n  - apiGroups: &#91;\"\"]\n    resources: &#91;\"pods\/log\"]\n    verbs: &#91;\"get\"]\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">B. Get only a particular ConfigMap<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>rules:\n  - apiGroups: &#91;\"\"]\n    resources: &#91;\"configmaps\"]\n    resourceNames: &#91;\"demo-config\"]\n    verbs: &#91;\"get\"]\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\"><code>resourceNames<\/code>&nbsp;does not constrain top-level&nbsp;<code>create<\/code>&nbsp;or&nbsp;<code>deletecollection<\/code>;&nbsp;<code>list<\/code>&nbsp;and&nbsp;<code>watch<\/code>&nbsp;restricted by&nbsp;<code>resourceNames<\/code>&nbsp;require a matching&nbsp;<code>metadata.name<\/code>&nbsp;field selector.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">C. Read a custom resource (example; requires a matching CRD)<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>rules:\n  - apiGroups: &#91;\"example.com\"]\n    resources: &#91;\"widgets\"]\n    verbs: &#91;\"get\", \"list\"]\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">D. Read a non-resource API path (ClusterRole only)<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>rules:\n  - nonResourceURLs: &#91;\"\/healthz\"]\n    verbs: &#91;\"get\"]\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Command summary<\/h2>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th class=\"has-text-align-left\" data-align=\"left\">Purpose<\/th><th class=\"has-text-align-left\" data-align=\"left\">Command<\/th><\/tr><\/thead><tbody><tr><td>Show active identity<\/td><td><code>kubectl auth whoami<\/code><\/td><\/tr><tr><td>List API resources<\/td><td><code>kubectl api-resources -o wide<\/code><\/td><\/tr><tr><td>List namespace Roles \/ bindings<\/td><td><code>kubectl get roles,rolebindings -n rbac-lab<\/code><\/td><\/tr><tr><td>List cluster-scoped roles \/ bindings<\/td><td><code>kubectl get clusterroles,clusterrolebindings<\/code><\/td><\/tr><tr><td>Describe a Role<\/td><td><code>kubectl describe role pod-reader -n rbac-lab<\/code><\/td><\/tr><tr><td>Test read permission<\/td><td><code>kubectl auth can-i list pods -n rbac-lab<\/code><\/td><\/tr><tr><td>Test as another user<\/td><td><code>kubectl auth can-i list pods -n rbac-lab --as=mia<\/code><\/td><\/tr><tr><td>See the CSR request<\/td><td><code>kubectl get csr alice-rbac-lab -o yaml<\/code><\/td><\/tr><tr><td>Approve a reviewed CSR<\/td><td><code>kubectl certificate approve alice-rbac-lab<\/code><\/td><\/tr><tr><td>Request a short-lived SA token<\/td><td><code>kubectl -n rbac-lab create token audit-bot --duration=10m<\/code><\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Troubleshooting<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>401 Unauthorized:<\/strong>\u00a0invalid, missing, or expired credentials; verify certificate trust, token, or kubeconfig selection.<\/li>\n\n\n\n<li><strong>403 Forbidden:<\/strong>\u00a0commonly insufficient authorization, but admission policy can also reject a request. Check the entire error.<\/li>\n\n\n\n<li><strong><code>--as<\/code>\u00a0is rejected:<\/strong>\u00a0your invoking identity may lack impersonation permission.<\/li>\n\n\n\n<li><strong>Unexpected\u00a0<code>yes<\/code>:<\/strong>\u00a0inspect all applicable bindings, default access, and additional authorizers.<\/li>\n\n\n\n<li><strong><code>Approved<\/code>\u00a0CSR without certificate:<\/strong>\u00a0a matching signer might not be configured or willing\/able to sign.<\/li>\n\n\n\n<li><strong>Group test fails:<\/strong>\u00a0verify CN\/O in certificate and\u00a0<code>kubectl --context=alice-rbac-lab auth whoami<\/code>.<\/li>\n\n\n\n<li><strong>Pod is Pending \/ ImagePullBackOff:<\/strong>\u00a0inspect cluster scheduling and image pull separately from RBAC.<\/li>\n\n\n\n<li><strong>A RoleBinding cannot find a Role:<\/strong>\u00a0verify name, namespace,\u00a0<code>roleRef.kind<\/code>, and API group.<\/li>\n\n\n\n<li><strong><code>roleRef<\/code>\u00a0cannot be changed:<\/strong>\u00a0delete and recreate the binding as appropriate, after reviewing downstream access changes.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Cleanup<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Run as the administrator&nbsp;<strong>after<\/strong>&nbsp;finishing all labs and confirming the resource names belong only to these labs.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>kubectl delete namespace rbac-lab\nkubectl delete clusterrolebinding lab-ops-node-read\nkubectl delete clusterrole lab-node-reader\nkubectl delete csr alice-rbac-lab\n\n<em># Optional cleanup for the local lab kubeconfig (be mindful of its contents)<\/em>\nkubectl config delete-context alice-rbac-lab\nkubectl config delete-user alice\n\n<em># Remove local training-only credentials when no longer needed:<\/em>\nrm -f alice.key alice.csr alice.crt\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Instructor quiz &#8211; with answers<\/h2>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>How can we allow a group to list Pods only in\u00a0<code>rbac-lab<\/code>?<\/strong>\u00a0A Role with a RoleBinding to Group; or\u00a0<code>view<\/code>\u00a0ClusterRole with a RoleBinding in\u00a0<code>rbac-lab<\/code>.<\/li>\n\n\n\n<li><strong>Can we create a human user with\u00a0<code>kubectl create user<\/code>?<\/strong>\u00a0No. A normal user identity comes from an authenticator such as client cert or OIDC.<\/li>\n\n\n\n<li><strong>Can\u00a0<code>ClusterRoleBinding<\/code>\u00a0point to\u00a0<code>Role<\/code>?<\/strong>\u00a0No; only to\u00a0<code>ClusterRole<\/code>.<\/li>\n\n\n\n<li><strong>What does certificate\u00a0<code>CN<\/code>\u00a0mean? What does\u00a0<code>O<\/code>\u00a0mean?<\/strong>\u00a0Username and group for Kubernetes X.509 authentication.<\/li>\n\n\n\n<li><strong>Does creating a ServiceAccount grant permissions?<\/strong>\u00a0No, bind a Role or ClusterRole as needed.<\/li>\n\n\n\n<li><strong>What is the difference between\u00a0<code>get<\/code>\u00a0and\u00a0<code>list<\/code>?<\/strong>\u00a0One named object vs collection of objects.<\/li>\n\n\n\n<li><strong>Does approval guarantee that a CSR has an issued certificate?<\/strong>\u00a0No, a configured signer must issue it.<\/li>\n\n\n\n<li><strong>Why should\u00a0<code>edit<\/code>\u00a0be considered high privilege?<\/strong>\u00a0It grants access to Secrets and the ability to run Pods using namespace ServiceAccounts.<\/li>\n<\/ol>\n\n\n\n<h2 class=\"wp-block-heading\">Official references<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Kubernetes releases:\u00a0<a href=\"https:\/\/kubernetes.io\/releases\/\">https:\/\/kubernetes.io\/releases\/<\/a><\/li>\n\n\n\n<li>RBAC authorization:\u00a0<a href=\"https:\/\/kubernetes.io\/docs\/reference\/access-authn-authz\/rbac\/\">https:\/\/kubernetes.io\/docs\/reference\/access-authn-authz\/rbac\/<\/a><\/li>\n\n\n\n<li>Authentication:\u00a0<a href=\"https:\/\/kubernetes.io\/docs\/reference\/access-authn-authz\/authentication\/\">https:\/\/kubernetes.io\/docs\/reference\/access-authn-authz\/authentication\/<\/a><\/li>\n\n\n\n<li>Authorization:\u00a0<a href=\"https:\/\/kubernetes.io\/docs\/reference\/access-authn-authz\/authorization\/\">https:\/\/kubernetes.io\/docs\/reference\/access-authn-authz\/authorization\/<\/a><\/li>\n\n\n\n<li>CertificateSigningRequest API:\u00a0<a href=\"https:\/\/kubernetes.io\/docs\/reference\/access-authn-authz\/certificate-signing-requests\/\">https:\/\/kubernetes.io\/docs\/reference\/access-authn-authz\/certificate-signing-requests\/<\/a><\/li>\n\n\n\n<li>Client certificate step-by-step:\u00a0<a href=\"https:\/\/kubernetes.io\/docs\/tasks\/tls\/certificate-issue-client-csr\/\">https:\/\/kubernetes.io\/docs\/tasks\/tls\/certificate-issue-client-csr\/<\/a><\/li>\n\n\n\n<li>ServiceAccounts:\u00a0<a href=\"https:\/\/kubernetes.io\/docs\/tasks\/configure-pod-container\/configure-service-account\/\">https:\/\/kubernetes.io\/docs\/tasks\/configure-pod-container\/configure-service-account\/<\/a><\/li>\n\n\n\n<li><code>kubectl auth can-i<\/code>:\u00a0<a href=\"https:\/\/kubernetes.io\/docs\/reference\/kubectl\/generated\/kubectl_auth\/kubectl_auth_can-i\/\">https:\/\/kubernetes.io\/docs\/reference\/kubectl\/generated\/kubectl_auth\/kubectl_auth_can-i\/<\/a><\/li>\n\n\n\n<li>Original tutorial flow:\u00a0<a href=\"https:\/\/www.devopsschool.com\/blog\/understanding-authentication-authorization-in-kubernetes\/\">https:\/\/www.devopsschool.com\/blog\/understanding-authentication-authorization-in-kubernetes\/<\/a><\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>Companion guide for&nbsp;Kubernetes RBAC: Foundations to Essentials (50 slides). Updated 12 November 2026. Examples follow Kubernetes v1.37 API documentation. Execution status:&nbsp;Commands and YAML have been checked against&#8230; <\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-1282","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/www.devopsschool.com\/tutorials\/wp-json\/wp\/v2\/posts\/1282","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.devopsschool.com\/tutorials\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.devopsschool.com\/tutorials\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.devopsschool.com\/tutorials\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.devopsschool.com\/tutorials\/wp-json\/wp\/v2\/comments?post=1282"}],"version-history":[{"count":1,"href":"https:\/\/www.devopsschool.com\/tutorials\/wp-json\/wp\/v2\/posts\/1282\/revisions"}],"predecessor-version":[{"id":1283,"href":"https:\/\/www.devopsschool.com\/tutorials\/wp-json\/wp\/v2\/posts\/1282\/revisions\/1283"}],"wp:attachment":[{"href":"https:\/\/www.devopsschool.com\/tutorials\/wp-json\/wp\/v2\/media?parent=1282"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.devopsschool.com\/tutorials\/wp-json\/wp\/v2\/categories?post=1282"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.devopsschool.com\/tutorials\/wp-json\/wp\/v2\/tags?post=1282"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}