RBAC: roles, bindings and service accounts

Who may do what in a cluster: Roles list allowed actions, bindings hand them out, and kubectl auth can-i proves it.

40 min 3 hands-on tasksArchitecture · 25% of the exam

Key ideas in this lesson · tap one for a simple explanation

What you will be able to do

  • Create a ServiceAccount, a Role and a RoleBinding with kubectl in under two minutes.
  • Choose between a Role and a ClusterRole, and between a RoleBinding and a ClusterRoleBinding.
  • Write rules with the right API group, plural resource names and subresources such as pods/log.
  • Check access with kubectl auth can-i, issue a short-lived token, and take back access that is too broad.

(role-based access control) decides who may do what in a cluster. May your Django app's read ? May the user maya delete Pods? RBAC answers these questions. On the exam it is one of the surest sources of points, because most tasks take three short commands.

The grader does not read your . It asks the whether someone may do something, the same way kubectl auth can-i does. So a rule that looks right but names the wrong API group still fails.

Four objects with look-alike names

RBAC uses four objects. Learn them in pairs: a role says what is allowed, and a binding says who gets it. A role does nothing until a binding hands it out.

ObjectWhat it isWhere its rules apply
RoleA list of allowed actionsOne
ClusterRoleThe same, but it belongs to no namespaceWherever a binding uses it, including cluster-wide objects such as
RoleBindingGives a Role or a ClusterRole to someoneOnly in the binding's own namespace
ClusterRoleBindingGives a ClusterRole to someoneEvery namespace, plus cluster-wide objects
How a binding grants access

Subject

a user, a group or a service account

maya

RoleBinding

gives the role to the subject

Role

a named list of rules

config-editor

Rules

verbs on resources

get, list on configmaps

The binding joins who (the subject) to what (the role). The role holds the rules: which actions on which objects.

  • Subjects are who gets access. A user is a person, such as maya. A group is a set of users, such as platform-oncall. A is an identity for a program that runs in a Pod. Users and groups are not objects you create in the cluster.
  • Permissions only add up. A subject gets the rules of every binding that names it. There are no deny rules, so to take access away you delete or narrow a binding.
  • A RoleBinding may point at a ClusterRole. The rules then apply only in the binding's namespace, and rules about cluster-wide objects such as nodes give nothing. This lets you reuse one ClusterRole, such as edit, in many namespaces.
  • A ClusterRoleBinding can only point at a ClusterRole, never at a Role.

Writing a rule

A rule has three parts: the API group, the resources and the verbs (the actions). Here is a Role with two rules, and a RoleBinding that gives it to all three kinds of subject:

A Role and a RoleBinding with all three subject kinds
# To try it: kubectl create namespace arx-rbac-demo first, then kubectl apply -f this file
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: config-editor
  namespace: arx-rbac-demo
rules:
  - apiGroups: [""]                   # "" is the core group: pods, services, configmaps, secrets
    resources: ["configmaps"]
    verbs: ["get", "list", "watch"]
  - apiGroups: ["apps"]
    resources: ["deployments", "deployments/scale"]
    verbs: ["get", "patch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: config-editor
  namespace: arx-rbac-demo
roleRef:                              # cannot be changed: to point elsewhere, delete and recreate the binding
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: config-editor
subjects:
  - kind: ServiceAccount              # no apiGroup; always give its namespace
    name: settings-sync
    namespace: arx-rbac-demo
  - kind: User                        # the user name from their certificate or login
    apiGroup: rbac.authorization.k8s.io
    name: maya
  - kind: Group                       # a group from their certificate or login
    apiGroup: rbac.authorization.k8s.io
    name: platform-oncall
FieldWhat goes in itExample
apiGroupsThe part of the object's apiVersion before the slash. Core objects have no group, so they use "".Pods (v1): "". (apps/v1): apps. : batch.
resourcesLowercase plural names. A subresource is its own entry: access to pods does not include pods/log.pods, pods/log, deployments/scale
verbsThe actions allowed. "*" means every verb.get, list, watch, create, update, patch, delete
resourceNames (optional)Limits the rule to objects with these names. It cannot limit create.app-settings

Not sure of a group or a plural? kubectl api-resources -o wide lists every resource with its API group and its verbs.

Create it with kubectl

On the exam you rarely write RBAC YAML. kubectl create makes each object in one line. The flags take comma-separated lists, and a resource outside the core group is written <resource>.<group>, such as deployments.apps.

Create a ServiceAccount, Roles and bindings
kubectl create namespace arx-rbac-demo
kubectl -n arx-rbac-demo create serviceaccount settings-sync

# Role: comma-separated verbs, any number of resources; non-core resources as <resource>.<group>
kubectl -n arx-rbac-demo create role app-reader \
  --verb=get,list,watch --resource=pods,services,deployments.apps
kubectl -n arx-rbac-demo create role settings-writer \
  --verb=update,patch --resource=configmaps --resource-name=app-settings

# RoleBinding: --role or --clusterrole, then any mix of subjects (SA is <namespace>:<name>)
kubectl -n arx-rbac-demo create rolebinding app-reader --role=app-reader \
  --serviceaccount=arx-rbac-demo:settings-sync --user=maya --group=platform-oncall
kubectl -n arx-rbac-demo create rolebinding settings-writer --role=settings-writer --user=maya

# Cluster-wide rules and binding
kubectl create clusterrole pv-viewer --verb=get,list,watch \
  --resource=persistentvolumes,storageclasses.storage.k8s.io
kubectl create clusterrolebinding pv-viewer --clusterrole=pv-viewer --group=platform-oncall

# Generate YAML instead when you need to add something the flags cannot express
kubectl -n arx-rbac-demo create role app-reader --verb=get --resource=pods --dry-run=client -o yaml

Look at how the binding names the service account: namespace:name. You write a service account three different ways, depending on where you use it:

WhereHow you write settings-sync from arx-rbac-demo
kubectl create rolebinding--serviceaccount=arx-rbac-demo:settings-sync
A binding's YAMLkind: ServiceAccount, name: settings-sync and namespace: arx-rbac-demo
kubectl auth can-i--as=system:serviceaccount:arx-rbac-demo:settings-sync

Prove it with auth can-i

Always check your work before you move on. kubectl auth can-i asks the API server whether a request would be allowed. It prints yes or no and changes nothing. Add --as to ask on behalf of someone else.

Ask the API server as each subject
# Ask the API server as the subject. "yes" exits 0, "no" exits 1.
kubectl auth can-i list deployments.apps -n arx-rbac-demo \
  --as=system:serviceaccount:arx-rbac-demo:settings-sync
kubectl auth can-i update configmaps/app-settings -n arx-rbac-demo --as=maya   # TYPE/NAME form
kubectl auth can-i get pods --subresource=log -n arx-rbac-demo --as=maya       # subresources need the flag
kubectl auth can-i list persistentvolumes --as=anyone --as-group=platform-oncall  # --as-group needs --as
kubectl auth can-i --list -n arx-rbac-demo --as=system:serviceaccount:arx-rbac-demo:settings-sync
kubectl auth whoami                                                            # who you are right now

Service accounts and tokens

A ServiceAccount is an identity for a program, not a person. Example: your Django app needs to list Pods through the API. You create a service account for it, bind a Role to that account, and run the app's Pods as that account.

  • A Pod runs as the account named in spec.serviceAccountName. Leave it out and the Pod runs as default.
  • The puts a short-lived token into the Pod, at /var/run/secrets/kubernetes.io/serviceaccount/token, and renews it for you.
  • kubectl create token gives you a token on demand. Kubernetes no longer creates token Secrets by itself.
  • Set automountServiceAccountToken: false on the Pod or the account when the app never calls the API.
A token, and a Pod that runs as the account
kubectl -n arx-rbac-demo create serviceaccount report-bot
kubectl -n arx-rbac-demo create token report-bot --duration=2h > /tmp/cka/report-bot.token
# The token is printed once and stored nowhere. A token that never expires needs a Secret of type kubernetes.io/service-account-token: avoid it unless asked.

# Run as the account: kubectl run has no SA flag, so override the spec (or set it in YAML)
kubectl -n arx-rbac-demo run reporter --image=busybox:1.36 --restart=Never \
  --overrides='{"spec":{"serviceAccountName":"report-bot"}}' -- sleep 3600
kubectl -n arx-rbac-demo set serviceaccount deployment/web report-bot   # an existing Deployment

Built-in ClusterRoles

Kubernetes comes with ready-made ClusterRoles. Bind one when it fits, instead of writing your own. For example, kubectl -n shop create rolebinding maya-edit --clusterrole=edit --user=maya lets maya change most things in shop, and nothing anywhere else.

ClusterRoleAllowsDoes not allow
cluster-adminEverything. Through a RoleBinding, everything in one namespace.Nothing is held back
adminRead and write on most objects in a namespace, including Roles and RoleBindingsChanging the Namespace itself or its
editRead and write on most objects in a namespace, including Pods and SecretsReading or changing Roles and RoleBindings
viewRead-only on most objects in a namespaceSecrets (they hold passwords), Roles and RoleBindings

Your admin gets cluster-admin through the group kubeadm:cluster-admins. Certificates and kubeconfig shows where users and groups come from.

In the official docs· open on exam day too

Hands-on task 1 of 3ar-rbac-1
~7 min6% weightArchitecture

A service account that can deploy, and a token for it

In namespace arx-rbac, create a ServiceAccount named deployer and a Role named deployer that allows get, list, watch, create, update and patch on Deployments, and get, list, watch on Pods, and nothing else. Bind the Role to the ServiceAccount with a RoleBinding named deployer-binding. Finally, create a token for deployer that is valid for 2 hours and write only the token to /tmp/cka/rbac/deployer.token.

Cluster:kubectl config use-context kind-cka

  1. 1

    Set up the scenario

    curl -fsSL https://codewithmuh.com/labs/cka/t/ar-rbac-1/setup | bash
  2. 2

    Solve it in your terminal

    Use kubectl and the Kubernetes docs, like on exam day. Save any answer files under /tmp/cka/.

  3. 3

    Check your work

    curl -fsSL https://codewithmuh.com/labs/cka/t/ar-rbac-1/verify | bash
    Got FAIL? Read which check failed, fix it, run it again.
  4. 4

    Clean up (optional)

    curl -fsSL https://codewithmuh.com/labs/cka/t/ar-rbac-1/cleanup | bash
Hands-on task 2 of 3ar-rbac-2
~5 min4% weightArchitecture

Read-only node access for a group

Members of the group arx-ops need to inspect nodes and PersistentVolumes across the cluster without changing anything. Create a ClusterRole named arx-node-reader that allows get, list and watch on nodes and persistentvolumes, and grant it to the group arx-ops with a ClusterRoleBinding named arx-node-reader-ops. The group must not gain any other access.

Cluster:kubectl config use-context kind-cka

  1. 1

    Set up the scenario

    curl -fsSL https://codewithmuh.com/labs/cka/t/ar-rbac-2/setup | bash
  2. 2

    Solve it in your terminal

    Use kubectl and the Kubernetes docs, like on exam day. Save any answer files under /tmp/cka/.

  3. 3

    Check your work

    curl -fsSL https://codewithmuh.com/labs/cka/t/ar-rbac-2/verify | bash
    Got FAIL? Read which check failed, fix it, run it again.
  4. 4

    Clean up (optional)

    curl -fsSL https://codewithmuh.com/labs/cka/t/ar-rbac-2/cleanup | bash
Hands-on task 3 of 3ar-rbac-3
~7 min6% weightArchitecture

Take back cluster-admin from a service account

The ServiceAccount log-shipper in namespace arx-rbac-fix was given cluster-admin to get a log collector working. It only needs to read Pods and their logs in its own namespace. Remove the excess access, then grant exactly get, list, watch on Pods and get on Pod logs in arx-rbac-fix, using a Role named log-reader and a RoleBinding named log-shipper-read. Do not delete the ServiceAccount.

Cluster:kubectl config use-context kind-cka

  1. 1

    Set up the scenario

    curl -fsSL https://codewithmuh.com/labs/cka/t/ar-rbac-3/setup | bash
  2. 2

    Solve it in your terminal

    Use kubectl and the Kubernetes docs, like on exam day. Save any answer files under /tmp/cka/.

  3. 3

    Check your work

    curl -fsSL https://codewithmuh.com/labs/cka/t/ar-rbac-3/verify | bash
    Got FAIL? Read which check failed, fix it, run it again.
  4. 4

    Clean up (optional)

    curl -fsSL https://codewithmuh.com/labs/cka/t/ar-rbac-3/cleanup | bash

Finished this lesson?

0 of 3 tasks passed. Your readiness counts tasks, so run them before you move on.