> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.mixlayer.com/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.mixlayer.com/_mcp/server.

# Kubernetes Workload Identity

> Authenticate with a projected Kubernetes ServiceAccount token

Kubernetes can mount a short-lived, automatically rotated ServiceAccount JWT into a Pod. Mixlayer verifies that JWT through the cluster's OIDC issuer and exchanges it for a short-lived Mixlayer access token.

Use projected ServiceAccount tokens rather than legacy Secret-backed tokens.

## 1. Inspect the cluster issuer

Get the cluster's OIDC discovery document:

```bash
kubectl get --raw /.well-known/openid-configuration | jq
```

Record its `issuer` value. Mixlayer must be able to reach the issuer and its `jwks_uri` over public HTTPS to use OIDC discovery.

For a private issuer, download the cluster's public JWKS and upload it as a static JWKS when configuring the provider:

```bash
kubectl get --raw /openid/v1/jwks > kubernetes-jwks.json
```

When using a static JWKS, add a new signing key to the Mixlayer provider before the cluster starts issuing tokens with it.

## 2. Configure the Mixlayer provider

Create an OIDC provider in [Workload Identity](https://console.mixlayer.com/app/workload-identity) with these values:

| Setting          | Value                                                                |
| ---------------- | -------------------------------------------------------------------- |
| Issuer URI       | The exact `issuer` from the discovery document                       |
| Allowed audience | `https://api.mixlayer.com`                                           |
| JWKS source      | OIDC discovery for a public issuer; static JWKS for a private issuer |

Map the ServiceAccount subject:

```text
mixlayer.subject = assertion.sub
```

Kubernetes subjects use this format:

```text
system:serviceaccount:<namespace>:<service-account-name>
```

Admit only the dedicated ServiceAccount:

```cel
mixlayer.subject == "system:serviceaccount:production:mixlayer-client"
```

Use `true` as the final authorization rule and grant only the permissions the Pod needs, such as `inference`.

## 3. Project a ServiceAccount token

The following manifest creates a dedicated ServiceAccount and mounts its token at `/var/run/secrets/mixlayer/token`:

**`file=`**

```yaml file=mixlayer-workload.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
  name: mixlayer-client
  namespace: production
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: mixlayer-client
  namespace: production
spec:
  replicas: 1
  selector:
    matchLabels:
      app: mixlayer-client
  template:
    metadata:
      labels:
        app: mixlayer-client
    spec:
      serviceAccountName: mixlayer-client
      containers:
        - name: app
          image: example/mixlayer-client:latest
          env:
            - name: MIXLAYER_IDENTITY_PROVIDER_ID
              value: wi_replace_me
          volumeMounts:
            - name: mixlayer-identity
              mountPath: /var/run/secrets/mixlayer
              readOnly: true
      volumes:
        - name: mixlayer-identity
          projected:
            sources:
              - serviceAccountToken:
                  path: token
                  audience: https://api.mixlayer.com
                  expirationSeconds: 3600
```

Apply it with:

```bash
kubectl apply -f mixlayer-workload.yaml
```

Do not mount the projected token using `subPath`; Kubernetes cannot rotate that mount.

## 4. Exchange the projected token

Read the token file each time you exchange so your application picks up rotations:

**`file=`**

```bash file=exchange-kubernetes-workload-identity.sh
MIXLAYER_SUBJECT_TOKEN=$(cat /var/run/secrets/mixlayer/token)

MIXLAYER_ACCESS_TOKEN=$(
  jq -n \
    --arg provider "$MIXLAYER_IDENTITY_PROVIDER_ID" \
    --arg token "$MIXLAYER_SUBJECT_TOKEN" \
    '{
      grant_type: "urn:ietf:params:oauth:grant-type:token-exchange",
      subject_token_type: "urn:ietf:params:oauth:token-type:jwt",
      subject_token: $token,
      identity_provider_id: $provider
    }' |
  curl --fail-with-body --silent --show-error \
    https://api.mixlayer.com/v1/workload_identity/token \
    -H "Content-Type: application/json" \
    --data-binary @- |
  jq -er .access_token
)
```

Use `MIXLAYER_ACCESS_TOKEN` as a bearer token with the Mixlayer APIs. Cache it in memory until shortly before it expires, then reread the projected token and exchange again.

## Troubleshooting

* Decode a sample token locally and compare its `iss`, `aud`, `sub`, `iat`, and `exp` claims with the provider. Decoding does not verify its signature.
* If discovery fails, confirm the issuer and JWKS endpoints are publicly reachable. Otherwise use a static JWKS.
* If exchange breaks after cluster signing-key rotation, update the provider's static JWKS.
* If the ServiceAccount, namespace, or cluster changes, update the admission policy or create a separate provider for the new trust boundary.

Amazon EKS and Google Kubernetes Engine can use this same projected-token flow with their cluster-specific issuer URLs.