> ## Documentation Index
> Fetch the complete documentation index at: https://www.truefoundry.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Kubernetes

> Federate Kubernetes projected service-account tokens into short-lived TrueFoundry access tokens.

Kubernetes issues projected service-account JWTs that identify a pod's namespace and service account. With Workload Identity Federation, the pod exchanges that JWT for a short-lived TrueFoundry access token — no Virtual Account token in the pod env or secret store.

TrueFoundry matches nested claims on the token (`kubernetes.io/namespace` and `kubernetes.io/serviceaccount/name`), not only the `sub` string.

For concepts and the shared exchange API, see [Workload Identity Federation](https://www.truefoundry.com/docs/platform/identity-providers/workload-identity-federation/overview.md).

## Prerequisites

* A cluster with projected service-account tokens enabled (default on current Kubernetes).
* The cluster OIDC issuer and JWKS reachable from the TrueFoundry control plane (or your platform team can expose them).
* A [Virtual Account](https://www.truefoundry.com/docs/platform/virtual-account-management.md) or Agent with the permissions the workload needs.

## Get the cluster issuer and JWKS

```bash theme={"dark"}
kubectl get --raw /.well-known/openid-configuration | jq -r .issuer
kubectl get --raw /.well-known/openid-configuration | jq -r .jwks_uri
```

On many managed clusters (EKS, GKE, AKS) the issuer is a public HTTPS URL. Use those values as **Issuer URL** and **JWKS URI** on the TrueFoundry Identity Provider.

## Project a service-account token

Mount a projected token into the pod. Set `audience` to a value you will also list under **Allowed Audiences** on the TrueFoundry Identity Provider (for example `truefoundry`).

```yaml theme={"dark"}
apiVersion: v1
kind: Pod
metadata:
  name: checkout
  namespace: payments
spec:
  serviceAccountName: checkout
  volumes:
    - name: tfy-token
      projected:
        sources:
          - serviceAccountToken:
              audience: truefoundry
              expirationSeconds: 3600
              path: token
  containers:
    - name: app
      image: your-registry/checkout:latest
      volumeMounts:
        - name: tfy-token
          mountPath: /var/run/secrets/truefoundry
          readOnly: true
      env:
        - name: WORKLOAD_JWT_FILE
          value: /var/run/secrets/truefoundry/token
```

A typical projected token includes nested claims TrueFoundry reads with `/` paths:

```json theme={"dark"}
{
  "iss": "https://oidc.eks.us-east-1.amazonaws.com/id/ABCDEF",
  "aud": ["truefoundry"],
  "kubernetes.io": {
    "namespace": "payments",
    "serviceaccount": { "name": "checkout" }
  }
}
```

## Configure TrueFoundry

1. **Settings > Security & Access > Identity Providers** → add provider type **Kubernetes**.
2. Set **Issuer URL** and **JWKS URI** from the cluster discovery document. Set **Allowed Audiences** to the same audience as the projected token (for example `truefoundry`).
3. On the Virtual Account (or Agent), add a mapping for that provider:

**Virtual Account — Claims**

```yaml theme={"dark"}
identity_provider_mapping:
  - identity_provider: prod-eks
    claims:
      kubernetes.io/namespace: payments
      kubernetes.io/serviceaccount/name: checkout
```

**Agent — Subject** (YAML key is still `claims`)

```yaml theme={"dark"}
identity:
  type: identity-provider-backed
  identity_provider_mapping:
    - identity_provider: prod-eks
      claims:
        kubernetes.io/namespace: payments
        kubernetes.io/serviceaccount/name: checkout
```

Required keys for `kubernetes`: `kubernetes.io/namespace`, `kubernetes.io/serviceaccount/name`. Paths use `/` as the nested-object separator; the dots in `kubernetes.io` are part of the key name. You may add further claim matches when your token includes them and you want to pin them.

## Exchange and call TrueFoundry

```bash theme={"dark"}
WORKLOAD_JWT=$(cat /var/run/secrets/truefoundry/token)

curl -sS "https://<tenant-host-origin>/<tenant>/oauth2/v1/token" \
  -H 'Content-Type: application/json' \
  -d "{
    \"grant_type\": \"urn:ietf:params:oauth:grant-type:token-exchange\",
    \"subject_token\": \"$WORKLOAD_JWT\",
    \"subject_token_type\": \"urn:ietf:params:oauth:token-type:jwt\",
    \"tfy_subject\": \"virtual_account:<virtual-account-name>\"
  }"
```

`<tenant-host-origin>` is the issuer origin from OpenID discovery. The exchange path is `/{tenant}/oauth2/v1/token` (no `/api/svc`). Prefer `token_endpoint` from `GET https://<tenant-host-origin>/<tenant>/.well-known/openid-configuration`.

Use the returned `access_token` as `Authorization: Bearer` on the [AI Gateway](https://www.truefoundry.com/docs/ai-gateway/authentication.md) or APIs. For Agents, set `tfy_subject` to `agent:<agent-name>`. Full exchange details: [Workload Identity Federation](https://www.truefoundry.com/docs/platform/identity-providers/workload-identity-federation/overview.md#exchange-the-platform-jwt).

## Scope the mapping

* Pin both namespace and service-account name — do not map a whole cluster to one Virtual Account unless that is intentional.
* Use the same audience on the projected token and the Identity Provider **Allowed Audiences** list.
* Prefer one Virtual Account (or Agent) per workload identity boundary.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.