kuberneteskubectlkubernetes-apiserverk8s-serviceaccount

Why K8s automounted service account token in a pod is different from the token retrieved directly from a service account?


Lets say I create a service account and retrieve the token associated to it:

kubectl -n myexample describe sa myexample-sa

kubectl describe secret myexample-sa-token-xxxxx

Value of the token:

token:      eyJhbGciOiJSUzI1NiIsImtpZCI6IkpHWGxoRlNRTklaWjVzQTh2dmZMWVVsM1haclpRbXRVTEpFZnNUcER6RnMifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJkZXZlbG9wbWVudCIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJteWV4YW1wbGUtc2EtdG9rZW4tOGw3cnciLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC5uYW1lIjoibXlleGFtcGxlLXNhIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQudWlkIjoiNTM1NDhjNTUtZmJlYS00MDc1LThhNDYtNTVhZDQwN2VmYzMxIiwic3ViIjoic3lzdGVtOnNlcnZpY2VhY2NvdW50OmRldmVsb3BtZW50Om15ZXhhbXBsZS1zYSJ9.FJMK2PIsloJRqGGIYAs_ZLpVn9-aW4UPWnGvrnNDscAWHtpatTknAJ0T075gXD86X6j_EShp7JLfv5J_aNRTHJWsYNzJIOXH0ZipdvsMW2oMfEK-VCDLgxlJnT3xikIYaFgYRgmw2-iraSiC-HcSmuuF8XPJgW93JNHqy2Vw2lka9GUzaxoD9D4UAvISk19peHPfDJZjEjr4r5QCUljQz8Va72dwOqNh3b01OI0-7epoRWjEjtCCOhKYyu2hErroo6IlaiUchN_VKTrL5182POMONYmKYrP0Z4ymX0AoA9dkKKbLjtm-Vkxp3B6xhtIrvaJ4upGH2AVNYSFb9aYacg

Then, I create a pod in a deployment and associate the service account above to the pod:

...
spec:
  template:
    spec:
      serviceAccountName: myexample-sa
...

Now, After the pod is deployed I exec to it:

kubectl -n myexample exec -it name-of-pod -- /bin/bash

If I run

cat /var/run/secrets/kubernetes.io/serviceaccount/token

The output is:

eyJhbGciOiJSUzI1NiIsImtpZCI6IkpHWGxoRlNRTklaWjVzQTh2dmZMWVVsM1haclpRbXRVTEpFZnNUcER6RnMifQ.eyJhdWQiOlsidW5rbm93biJdLCJleHAiOjE2ODMxMjk2ODQsImlhdCI6MTY1MTU5MzY4NCwiaXNzIjoicmtlIiwia3ViZXJuZXRlcy5pbyI6eyJuYW1lc3BhY2UiOiJkZXZlbG9wbWVudCIsInBvZCI6eyJuYW1lIjoic3RhdGljLXdlYiIsInVpZCI6ImZmNjMyOTU4LTM5MDctNDkyOS1hZGJjLWFjY2UyYzhkMTMxOCJ9LCJzZXJ2aWNlYWNjb3VudCI6eyJuYW1lIjoibXlleGFtcGxlLXNhIiwidWlkIjoiNTM1NDhjNTUtZmJlYS00MDc1LThhNDYtNTVhZDQwN2VmYzMxIn0sIndhcm5hZnRlciI6MTY1MTU5NzI5MX0sIm5iZiI6MTY1MTU5MzY4NCwic3ViIjoic3lzdGVtOnNlcnZpY2VhY2NvdW50OmRldmVsb3BtZW50Om15ZXhhbXBsZS1zYSJ9.Po-kZUo8nhOnJGxuHtvz6806QgLqPaztS0iWCNpnY0WCfpbRsmt2SWPckMo4P535DTqEJyDslUCF0loL0Tw2RNZxhHwRa-ul3P2G_9CmeApvGTX4nwyBFXjllsAWDiKWJkrxzpEkS0vf2N4r-9mGlEGkIWmPbUyDRD5LyeVmFMgPLNWYBLlAVG9qN5aJ5zzOq9pDFeY5jSXnOl3Ii3ddCZVxhnHDCGkFzu6w_YWkC-7iN68TlykwZb9wy2tFydCpAsPA

I compared the this token to the one I retrieved above (refer to first 2 commands) and they are different! Shouldn't this token value be exactly the same as the one I got for myexample-sa-token-xxxxx?


Solution

  • No, they should not be the same when the type is Service account token volume projection which is the case above.

    Service account token volume projection: Mounts a short-lived, automatically rotating Kubernetes service account token into the Pod. This token is a OpenID Connect Token and can be used to authenticate to the Kubernetes API and other external services.

    Readmore

    Service Account Token Volume Projection

    You can decode the token by using jwt.io and take a look at the payload. One is representing the service account and the other is actually binding for the pod.

    Also, note that K8s manages and rotates the pod key.

    The kubelet will request and store the token on behalf of the pod, make the token available to the pod at a configurable file path, and refresh the token as it approaches expiration. The kubelet proactively rotates the token if it is older than 80% of its total TTL, or if the token is older than 24 hours