RBAC Basics
Lab scenario
~30 min
ci-role.yaml
Terminal window Terminal window
RBAC is the front door of cluster security. Get it right and everything else — audit, secrets, policies — gets easier. Get it wrong and a compromised pod owns your cluster.
Mental model
Section titled “Mental model”- Role / ClusterRole — a set of verbs on resources. No principal attached.
- RoleBinding / ClusterRoleBinding — glues a Role to a subject (user, group, or ServiceAccount).
- Namespace-scoped vs cluster-scoped —
Rolelives in one namespace;ClusterRoleis cluster-wide.
Lab: least-privilege deployer
Section titled “Lab: least-privilege deployer”We’ll create a ServiceAccount that can deploy to payments namespace and nothing else.
Directoryrbac/
- 00-namespace.yaml
- 01-serviceaccount.yaml
- 02-role.yaml
- 03-rolebinding.yaml
-
Create the namespace
rbac/00-namespace.yaml apiVersion: v1kind: Namespacemetadata:name: paymentslabels:team: payments -
Create the ServiceAccount
rbac/01-serviceaccount.yaml apiVersion: v1kind: ServiceAccountmetadata:name: deployernamespace: payments -
Define the Role
rbac/02-role.yaml apiVersion: rbac.authorization.k8s.io/v1kind: Rolemetadata:name: deployernamespace: paymentsrules:- apiGroups: ["apps"]resources: ["deployments", "statefulsets"]verbs: ["get", "list", "watch", "create", "update", "patch"]- apiGroups: [""]resources: ["configmaps", "secrets"]verbs: ["get", "list", "create", "update"] -
Bind the Role
rbac/03-rolebinding.yaml apiVersion: rbac.authorization.k8s.io/v1kind: RoleBindingmetadata:name: deployernamespace: paymentssubjects:- kind: ServiceAccountname: deployernamespace: paymentsroleRef:kind: Rolename: deployerapiGroup: rbac.authorization.k8s.io -
Apply and verify
Terminal window kubectl apply -f rbac/kubectl auth can-i create deployments \--as=system:serviceaccount:payments:deployer \--namespace=payments# → yeskubectl auth can-i delete pods \--as=system:serviceaccount:payments:deployer \--namespace=payments# → no
Diff: from “cluster-admin lite” to least-privilege
Section titled “Diff: from “cluster-admin lite” to least-privilege”A common anti-pattern: giving a CI/CD SA cluster-admin because “it’s easier”. Here’s the fix in context.
apiVersion: rbac.authorization.k8s.io/v1kind: ClusterRoleBindingmetadata: name: ci-deployer- roleRef: { kind: ClusterRole, name: cluster-admin, apiGroup: rbac.authorization.k8s.io }+ roleRef:+ kind: ClusterRole+ name: ci-deployer+ apiGroup: rbac.authorization.k8s.io+ # ClusterRole scoped to `apps` and `batch` only — see previous file+ # Bound per-namespace via a RoleBinding, not cluster-wide.subjects: - kind: ServiceAccount name: ci namespace: ci-systemAuditing existing bindings
Section titled “Auditing existing bindings”# who can do what in a namespacekubectl auth can-i --list --namespace=payments \ --as=system:serviceaccount:payments:deployer
# all bindings referencing a service accountkubectl get rolebindings,clusterrolebindings -A -o json \ | jq '.items[] | select(.subjects[]?.name == "deployer") | .metadata'# https://github.com/FairwindsOps/rbac-lookuprbac-lookup deployer --output wide