RBAC cheatsheet.
Core resources
- Role: permissions in a namespace.
- ClusterRole: cluster-wide.
- RoleBinding: assign Role to subjects in a namespace.
- ClusterRoleBinding: assign ClusterRole cluster-wide.
- ServiceAccount: identity for pods.
ServiceAccount
apiVersion: v1
kind: ServiceAccount
metadata: { name: deployer, namespace: prod }
Use in pod:
spec:
serviceAccountName: deployer
Token mounted at /var/run/secrets/kubernetes.io/serviceaccount/token.
Role
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata: { namespace: prod, name: pod-reader }
rules:
- apiGroups: [""]
resources: [pods, pods/log]
verbs: [get, list, watch]
- apiGroups: [apps]
resources: [deployments]
verbs: [get, list]
RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata: { name: deployer-can-read, namespace: prod }
subjects:
- kind: ServiceAccount
name: deployer
namespace: prod
- kind: User
name: [email protected]
- kind: Group
name: developers
roleRef:
kind: Role
name: pod-reader
apiGroup: rbac.authorization.k8s.io
ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata: { name: view-everything }
rules:
- apiGroups: ["*"]
resources: ["*"]
verbs: [get, list, watch]
ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata: { name: alice-admin }
subjects:
- kind: User
name: [email protected]
roleRef:
kind: ClusterRole
name: cluster-admin
apiGroup: rbac.authorization.k8s.io
Verbs
get, list, watch
create, update, patch
delete, deletecollection
* (all)
Resource names
rules:
- apiGroups: [""]
resources: [pods]
resourceNames: [web, api] # only these specific pods
verbs: [get]
Subresources
resources: [pods, pods/log, pods/exec, pods/portforward]
pods/exec is needed for kubectl exec.
Built-in roles
cluster-admin: superuser.admin: full admin in namespace.edit: edit but not RBAC.view: read-only.
kubectl get clusterroles
Check permissions
kubectl auth can-i create deployments
kubectl auth can-i create deployments --namespace=prod
kubectl auth can-i '*' '*' --all-namespaces
# As another user
kubectl auth can-i list pods --as=[email protected]
kubectl auth can-i list pods --as=system:serviceaccount:prod:deployer
Pods using SA
kubectl get pods -o jsonpath='{.items[*].spec.serviceAccountName}'
Bind SA to Role concisely
kubectl create rolebinding deployer-reads \
--role=pod-reader \
--serviceaccount=prod:deployer \
-n prod
API access from pod
Pod can talk to K8s API using its SA token:
TOKEN=$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)
CA=/var/run/secrets/kubernetes.io/serviceaccount/ca.crt
curl --cacert $CA -H "Authorization: Bearer $TOKEN" \
https://kubernetes.default.svc/api/v1/namespaces/prod/pods
Aggregated ClusterRoles
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: my-aggregated
aggregationRule:
clusterRoleSelectors:
- matchLabels: { rbac.example.com/aggregate-to-my: "true" }
rules: [] # filled by aggregation
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: my-component
labels: { rbac.example.com/aggregate-to-my: "true" }
rules:
- apiGroups: [example.com]
resources: [things]
verbs: [get, list]
Composable role definitions.
Impersonation
kubectl --as=[email protected] get pods
kubectl --as=system:serviceaccount:prod:deployer get pods
kubectl --as-group=developers get pods
Useful for testing RBAC.
Audit logs
# /etc/kubernetes/audit-policy.yaml
apiVersion: audit.k8s.io/v1
kind: Policy
rules:
- level: Metadata
resources:
- group: ""
resources: [secrets]
- level: RequestResponse
resources:
- group: "rbac.authorization.k8s.io"
Audit logs show who did what. Critical for compliance.
OIDC / SSO
Cluster connects to OIDC provider (Google, GitHub, Okta, Dex):
# kube-apiserver flags
--oidc-issuer-url=https://accounts.google.com
--oidc-client-id=...
--oidc-username-claim=email
--oidc-groups-claim=groups
Users authenticate via OIDC; RBAC matches by username/group claims.
Cloud-managed: EKS uses IAM, GKE uses Google, AKS uses Entra.
Principle of least privilege
Per-service ServiceAccounts:
# Don't use the `default` SA
serviceAccountName: web
Grant only what’s needed:
rules:
- apiGroups: [""]
resources: [configmaps]
resourceNames: [app-config]
verbs: [get, watch]
Common mistakes
- Granting
cluster-admincasually. - Using
defaultSA everywhere. - Wildcards (
*) in rules. - ClusterRoleBinding when RoleBinding suffices.
- Forgetting subresources (
pods/log,pods/exec).
Read this next
If you want my RBAC presets per role, they’re at rajpoot.dev .
Building something AI-, backend-, or data-heavy and want a second pair of eyes? I do consulting and freelance work — see my projects and ways to reach me at rajpoot.dev .