DEV Community

Cheedge Lee
Cheedge Lee

Posted on

CKS Notes - ServiceAccount

Previous Notes about the Apiserver request security we have shown two identities (node identity /etc/kubernetes/kubelet.conf and admin cluster identity ~/.kube/config ). Now we will talk about another identity, it is used for the Pods — ServiceAccount. Actually we have talked about ServiceAccount before in previous post about RBAC(for more details about RBAC pls check here).

RBAC

RBAC is an authorization process, which will grant the Service Account with permissions (Role, ClusterRole).

SA - RoleBinding - Role → allowed actions

  • ServiceAccount: identity

  • Role or ClusterRole : ns-scoped or cluster-scoped allowed operations (permissions)

  • RoleBinding, ClusterRoleBinding

quick recap:

k create clusterrole NAME --verb OPS1,OPS2 --resource RESOURCENAME1,RESOURCENAME2
k create rolebinding NAME --role ROLENAME --serviceaccount SANAME
# do not miss up the --as and --service (--as is kubectl param used for test)
k auth can-i VERB RESOURCE --as system:serviceaccount:NAMESPACE:NAME
Enter fullscreen mode Exit fullscreen mode

Pod → Apiserver

Any pod can connect to the API server, but without RBAC permissions it cannot do anything meaningful.

1. Pod (no API server access)

  • Do not bind SA to any role (default sa)

  • Ideally disable token mounting

  • Pod runs with minimal risk

2. Pod → API Server

  • Create custom ServiceAccount

  • Bind it to Role/ClusterRole

  • Assign that SA to the pod(s)

For case 1, we need to opt out the of API credential auto-mounting

either set on sa

apiVersion: v1
kind: ServiceAccount
metadata:
  name: build-robot
automountServiceAccountToken: false
...
Enter fullscreen mode Exit fullscreen mode

or set on the pod needed

apiVersion: v1
kind: Pod
metadata:
  name: my-pod
spec:
  serviceAccountName: build-robot
  automountServiceAccountToken: false
  ...
Enter fullscreen mode Exit fullscreen mode

more details pls refer to the official docs “opt out of API credential auto mounting”.

Verify mount

# if not mount, will show nothing
kubectl -n test exec -it podA -- mount | grep serviceaccount
# otherwise, if it still mount the token will show sth like:
tmpfs on /run/secrets/kubernetes.io/serviceaccount type tmpfs (ro,relatime,size=2097536k,inode64,noswap)

kubectl -n test exec -it podA -- cat /var/run/secrets/kubernetes.io/serviceaccount/token
# cat: /var/run/secrets/kubernetes.io/serviceaccount/token: No such file or directory
Enter fullscreen mode Exit fullscreen mode

Apiserver ←→ Kubelet (Pod)

API server communicates with pods indirectly via kubelet and kubelet has its own identity (client certificate from kubelet.conf)

Examples:

  • API server tells kubelet to create a pod

  • API server watches pod status

  • API server updates pod info

  • Kubelet sends logs to API server

  • Kubelet mounts volumes/secrets

  • Kubelet reports liveness/readiness

  • API server fetches metrics from kubelet

Identities comparision

1. Human / Automation (kubectl, CI)

Identity comes from kubeconfig, using:

  • client cert

  • or token (OIDC, bearer)

2. Kubelet (Node agent)

Identity comes from:

  • /etc/kubernetes/kubelet.conf

  • client certificate

  • User identity: system:node:<nodeName>

  • Group: system:nodes

3. Pod (Workload)

Identity comes from:

  • ServiceAccount token projected by kubelet

Identity becomes: system:serviceaccount:<ns>:<name>

Workflow

SA token is a JWT token, so basically we can understand this process as a JWT token verify process.

1. send request

k get pod -n test

then kubectl actually send the request

GET /api/v1/namespace/test/pods
Authorization: Bearer <JWT_TOKEN>
Enter fullscreen mode Exit fullscreen mode

That token is a JWT with 3 parts:

  1. Header – algorithm & token type

  2. Payload (claims) – SA identity information

  3. Signature – signed with API server private key

Payload includes:

2. Apiserver handle

2.1 Authentication

look for key to verify the SA JWT token, if it is authenticated, go next

2.2 Authorisation

RBAC authorization

  • request verb = get

  • resource = pods

  • namespace = test

  • user = system:serviceaccount:test:<sa-name>

2.3 Admission Control (NodeRestriction)

2.4 Do the Operation

Summary

ServiceAccount:

  • Pod Identity (JWT token)

  • SA - RoleBinding - Role → allowed actions

  • automountServiceAccountToken

  • Pod → Apiserver

  • Apiserver verify token

  • verify kubectl -n test exec -it podA -- mount | grep serviceaccount

Top comments (0)