<p>I'm using AWS EKS 1.21 with service account discovery enabled.<br />
Created an OIDC provider, the <code>.well-known/openid-configuration</code> endpoint returns a correct configuration:</p>
<pre><code>{
  &quot;issuer&quot;: &quot;https://oidc.eks.eu-west-1.amazonaws.com/id/***&quot;,
  &quot;jwks_uri&quot;: &quot;https://ip-***.eu-west-1.compute.internal:443/openid/v1/jwks&quot;,
  &quot;response_types_supported&quot;: [
    &quot;id_token&quot;
  ],
  &quot;subject_types_supported&quot;: [
    &quot;public&quot;
  ],
  &quot;id_token_signing_alg_values_supported&quot;: [
    &quot;RS256&quot;
  ]
}
</code></pre>
<p>Created a ServiceAccount for one of my deployments and the pod gets this as projected volume:</p>
<pre><code>  volumes:
  - name: kube-api-access-b4xt9
    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
</code></pre>
<p>The secret created for the ServiceAccount contains this token:</p>
<pre><code>{
  &quot;iss&quot;: &quot;kubernetes/serviceaccount&quot;,
  &quot;kubernetes.io/serviceaccount/namespace&quot;: &quot;sbx&quot;,
  &quot;kubernetes.io/serviceaccount/secret.name&quot;: &quot;dliver-site-config-service-token-kz874&quot;,
  &quot;kubernetes.io/serviceaccount/service-account.name&quot;: &quot;dliver-site-config-service&quot;,
  &quot;kubernetes.io/serviceaccount/service-account.uid&quot;: &quot;c26ad760-9067-4d90-a327-b3d6e32bce42&quot;,
  &quot;sub&quot;: &quot;system:serviceaccount:sbx:dliver-site-config-service&quot;
}
</code></pre>
<p>The projected token mounted in to the pod contains this:</p>
<pre><code>{
  &quot;aud&quot;: [
    &quot;https://kubernetes.default.svc&quot;
  ],
  &quot;exp&quot;: 1664448004,
  &quot;iat&quot;: 1632912004,
  &quot;iss&quot;: &quot;https://oidc.eks.eu-west-1.amazonaws.com/id/***&quot;,
  &quot;kubernetes.io&quot;: {
    &quot;namespace&quot;: &quot;sbx&quot;,
    &quot;pod&quot;: {
      &quot;name&quot;: &quot;dliver-site-config-service-77494b8fdd-45pxw&quot;,
      &quot;uid&quot;: &quot;0dd440a6-1213-4faa-a69e-398b83d2dd6b&quot;
    },
    &quot;serviceaccount&quot;: {
      &quot;name&quot;: &quot;dliver-site-config-service&quot;,
      &quot;uid&quot;: &quot;c26ad760-9067-4d90-a327-b3d6e32bce42&quot;
    },
    &quot;warnafter&quot;: 1632915611
  },
  &quot;nbf&quot;: 1632912004,
  &quot;sub&quot;: &quot;system:serviceaccount:sbx:dliver-site-config-service&quot;
}
</code></pre>
<p>Kubernetes renew the projected token every hour, so everything looks fine.<br />
Except the projected token &quot;exp&quot; field:<br />
<code>&quot;iat&quot;: 1632912004</code> which is <code>Wednesday, September 29, 2021 10:40:04 AM</code><br />
<code>&quot;exp&quot;: 1664448004</code> which is <code>Thursday, September 29, 2022 10:40:04 AM</code></p>
<p>So the problem is, that the projected token expiry time is 1 year, instead of around 1 hour, which makes Kubernetes effort to renew the token basically useless.<br />
I searched for hours but was simply unable to figure out where this is coming from.<br />
The expiration flag is passed to the kube-api server: <code>--service-account-max-token-expiration=&quot;24h0m0s&quot;</code>, so
my assumption is that this should be configured on the OIDC provider somehow, but unable to find any related documentation.</p>
<p>Any idea how to make the projected token expiry date around the same as the <code>expirationSeconds</code> in the pod projected volume?</p>
<h2>Update</h2>
<p>It only happens, when the projected token <code>expirationSeconds</code> is set to the default <code>3607</code> value, any other value gives the correct <code>exp</code> in the mounted token, which is really weird.</p>

ncsibra
<p>Finally got an answer <a href="https://github.com/kubernetes/kubernetes/issues/105654#issuecomment-942777567" rel="noreferrer">elsewhere</a>.</p>
<blockquote>
<p>cluster operators can specify flag --service-account-extend-token-expiration=true to kube apiserver to allow tokens have longer expiration temporarily during the migration. Any usage of legacy token will be recorded in both metrics and audit logs.</p>
</blockquote>
<p>The &quot;3607&quot; magic number is part of the Bound Service Account Tokens safe rollout plan, <a href="https://github.com/kubernetes/enhancements/blob/master/keps/sig-auth/1205-bound-service-account-tokens/README.md#safe-rollout-of-time-bound-token" rel="noreferrer">described in this kep</a>.
The actual number <a href="https://github.com/kubernetes/kubernetes/blob/ea0764452222146c47ec826977f49d7001b0ea8c/pkg/serviceaccount/claims.go#L35" rel="noreferrer">hardcoded in the source code</a>.<br />
The <code>--service-account-extend-token-expiration</code> flag was <a href="https://github.com/kubernetes/kubernetes/pull/96273" rel="noreferrer">set to true</a> by default from 1.20.</p>
<p>The mentioned metric/log info can be found <a href="https://github.com/kubernetes/enhancements/blob/master/keps/sig-auth/1205-bound-service-account-tokens/README.md#serviceaccount-admission-controller-migration" rel="noreferrer">in the kep too</a> and was implemented <a href="https://github.com/kubernetes/kubernetes/pull/89549" rel="noreferrer">here</a>.<br />
To see these logs in EKS need to <a href="https://docs.aws.amazon.com/eks/latest/userguide/control-plane-logs.html" rel="noreferrer">enable audit logging on the cluster</a>, then check Cloudwatch for related log entries.</p>
<p>I used this query in Cloudwatch Log Insight to find which pods don't reload the token periodically:</p>
<pre class="lang-kotlin prettyprint-override"><code>filter @logStream like 'kube-apiserver-audit'
 | filter ispresent(`annotations.authentication.k8s.io/stale-token`)
 | parse `annotations.authentication.k8s.io/stale-token` &quot;subject: *,&quot; as subject
 | stats count(*) as staleCount by subject, `user.username`
 | sort staleCount desc
</code></pre>
