Hi Team, I appreciate your input on the below. This is the pod defintion and lo . . .

Karim:
Hi Team, I appreciate your input on the below. This is the pod defintion and looking at the definition it is using the default service account in the default namespace. The part that is doesn’t make sense to me is when I look at the token leveraging the kubectl describe secret and put it on the http://JWT.io|JWT.io website I can see some details of the token without any expiry vs if I run the command kubectl exec web-dashboard-767bc588bc-7rl29 – cat /var/run/secrets/kubernetes.io/serviceaccount/token & I put it in http://JWT.io|JWT.io I see expiry for the token. I am not able to make sense of it. Appreciate your input

- apiVersion: v1
  kind: Pod
  metadata:
    creationTimestamp: "2022-09-29T18:10:09Z"
    generateName: web-dashboard-767bc588bc-
    labels:
      name: web-dashboard
      pod-template-hash: 767bc588bc
    name: web-dashboard-767bc588bc-7rl29
    namespace: default
    ownerReferences:
    - apiVersion: apps/v1
      blockOwnerDeletion: true
      controller: true
      kind: ReplicaSet
      name: web-dashboard-767bc588bc
      uid: 7536e92e-2724-417a-bdc3-b755c4ac6482
    resourceVersion: "2657"
    uid: fd803b54-2c11-4d66-bfb1-856bd69d555d
  spec:
    containers:
    - env:
      - name: PYTHONUNBUFFERED
        value: "1"
      image: <http://gcr.io/kodekloud/customimage/my-kubernetes-dashboard|gcr.io/kodekloud/customimage/my-kubernetes-dashboard>
      imagePullPolicy: Always
      name: web-dashboard
      ports:
      - containerPort: 8080
        protocol: TCP
      resources: {}
      terminationMessagePath: /dev/termination-log
      terminationMessagePolicy: File
      volumeMounts:
      - mountPath: /var/run/secrets/kubernetes.io/serviceaccount
        name: kube-api-access-2jw8r
        readOnly: true
    dnsPolicy: ClusterFirst
    enableServiceLinks: true
    nodeName: controlplane
    preemptionPolicy: PreemptLowerPriority
    priority: 0
    restartPolicy: Always
    schedulerName: default-scheduler
    securityContext: {}
    serviceAccount: default
    serviceAccountName: default
    terminationGracePeriodSeconds: 30
    tolerations:
    - effect: NoExecute
      key: <http://node.kubernetes.io/not-ready|node.kubernetes.io/not-ready>
      operator: Exists
      tolerationSeconds: 300
    - effect: NoExecute
      key: <http://node.kubernetes.io/unreachable|node.kubernetes.io/unreachable>
      operator: Exists
      tolerationSeconds: 300
    volumes:
    - name: kube-api-access-2jw8r
      projected:
        defaultMode: 420
        sources:
        - serviceAccountToken:
            expirationSeconds: 3607
            path: token
        - configMap:
            items:
            - key: ca.crt
              path: ca.crt
            name: kube-root-ca.crt
        - downwardAPI:
            items:
            - fieldRef:
                apiVersion: v1
                fieldPath: metadata.namespace
              path: namespace

Alistair Mackay:
Hi @Karim

The way service accounts and tokens work has changed in v1.24 and above. Also note that service accounts is now a topic for CKAD, and all this is covered in those lectures.

You will note in the volumes section of what you pasted above, that there is a projected volume. It is automatically added to the pod for the service account that the pod is using. This overlays the new token API to the pod’s filesystem. The token API can supply tokens with time and audience constraints and automatically rotate them, thus is much more secure than the old secrets bound tokens.

Karim:
Hi @Alistair Mackay, thanks for your response I have went through the updated lectures and I understand the projection aspect. The only thing that I am not getting is that the token appears once with an expiry data when queried from the container and without when queried using kubectl describe secret. Is this the expected behavior? Do you mean to say that the token API is taking the default secret and updating it to be time/audience constrained? Many thanks!

Karim:
do you mean to say that this is not the default service token?

Alistair Mackay:
The token you are seeing inside the container is not coming from any secret. Its being issued directly by the api server, and you can see the lifetime as part of the projected volume declaration in the YAML.

Karim:
Ahh now I get it…Is there a way to see this token from kubectl or it automatically gets projected into the pod and that’s the only way to see its value?

Alistair Mackay:
That’s how I understand it. It’s increasing the security as only the pod knows it.
If you needed to extract it, you could kubectl cp it out, but of course it’s still only valid for a short time before it’s renewed within the pod

Karim:
got it…very very grateful for the explanation :slightly_smiling_face:

Trung Tran:
Hi @Alistair Mackay
So let say, all we need to do is create a SA, then assign it to pod via serviceAccountName field, and the rest is handled by K8S?

Karim:
@Trung Tran this is an example of how it is done from the docs

apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  containers:
  - image: nginx
    name: nginx
    volumeMounts:
    - mountPath: /var/run/secrets/tokens
      name: vault-token
  serviceAccountName: build-robot
  volumes:
  - name: vault-token
    projected:
      sources:
      - serviceAccountToken:
          path: vault-token
          expirationSeconds: 7200
          audience: vault

Karim:
https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/