Lab 28 - Service accounts
Lab 28 - Service accounts
Goal: see the token every Pod carries, call the API with it, and give an application exactly the rights it needs. Chapter: Service accounts
# 1 - a Pod with curl, running as the default ServiceAccount
kubectl run api-client -n dev --image curlimages/curl:8.10.1 --command -- sleep 3600
kubectl get pod api-client -n dev -o jsonpath='{.spec.serviceAccountName}{"\n"}' # default
kubectl exec -n dev api-client -- ls /var/run/secrets/kubernetes.io/serviceaccount
# 2 - what is in the token? (a JWT: header.payload.signature)
kubectl exec -n dev api-client -- cat /var/run/secrets/kubernetes.io/serviceaccount/token \
| cut -d. -f2 | base64 -d 2>/dev/null; echo
Find sub (system:serviceaccount:dev:default), aud, exp (about 1 hour)
and the Pod name - the token is bound to this Pod.
# 3 - call the API from inside the Pod
kubectl exec -n dev api-client -- sh -c '
SA=/var/run/secrets/kubernetes.io/serviceaccount
curl -s --cacert $SA/ca.crt -H "Authorization: Bearer $(cat $SA/token)" \
https://kubernetes.default.svc/api/v1/namespaces/dev/pods | head -20'
403 Forbidden ... "system:serviceaccount:dev:default" cannot list pods.
Authenticated, not authorized - exactly like Jane.
A dedicated ServiceAccount
# 4 -
kubectl create sa pod-lister -n dev
kubectl create role list-pods -n dev --verb=get,list --resource=pods
kubectl create rolebinding pod-lister -n dev --role=list-pods --serviceaccount=dev:pod-lister
kubectl auth can-i list pods -n dev --as system:serviceaccount:dev:pod-lister
# 5 - the serviceAccountName of a Pod cannot be changed - create a new one
kubectl delete pod api-client -n dev
kubectl run api-client -n dev --image curlimages/curl:8.10.1 \
--overrides='{"spec":{"serviceAccountName":"pod-lister"}}' --command -- sleep 3600
kubectl exec -n dev api-client -- sh -c '
SA=/var/run/secrets/kubernetes.io/serviceaccount
curl -s --cacert $SA/ca.crt -H "Authorization: Bearer $(cat $SA/token)" \
https://kubernetes.default.svc/api/v1/namespaces/dev/pods | grep "\"name\": \"web" | head -3'
No token where none is needed
# 6 -
kubectl patch sa default -n dev -p '{"automountServiceAccountToken":false}'
kubectl run no-token -n dev --image nginx:1.27
kubectl exec -n dev no-token -- ls /var/run/secrets/kubernetes.io/serviceaccount # no such directory
Most applications never call the API. Without a token, a compromised container has nothing to steal.
Discovery
InfodiscoverTask A. A CI pipeline needs a token for pod-lister, valid 10 minutes.
Create it and use it with kubectl from support01.
Task B. Which ServiceAccounts in the cluster are bound to cluster-admin?
Clean up
kubectl delete pod api-client no-token -n dev
kubectl patch sa default -n dev -p '{"automountServiceAccountToken":null}'