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

# Manual OIDC token exchange for Object Storage

> Manually configure OIDC Workload Identity Federation to authenticate CKS workloads to AI Object Storage

This guide describes how to manually configure OIDC Workload Identity Federation between a CKS cluster and AI Object Storage so that CKS workloads can authenticate to AI Object Storage without long-lived static credentials. The resulting Pod receives a projected service account token that it exchanges for temporary S3 credentials at runtime.

You can do this automatically with minimal configuration by installing the [Pod Identity Webhook](/security/tutorials/cks-object-storage-authentication/automatic). Use this guide when you need full control over the token exchange or for debugging.

## Prerequisites

Before you begin, make sure you have the following in place.

In your CoreWeave organization, you must have:

* A deployed [CKS cluster with OIDC Workload Identity enabled](/products/cks/auth-access/workload-identity/introduction).
* A user with the appropriate permissions to create and deploy AI Object Storage buckets and policies. These are enabled using an [IAM Access Policy](/security/iam/access-policies) tied to the principal with the **Object Storage Admin** role, or an AI Object Storage [organization access policy](/products/storage/object-storage/auth-access/organization-policies/about) that grants the following permissions: `s3:CreateBucket`, `cwobject:CreateAccessKey`, `cwobject:EnsureAccessPolicy`, `cwobject:ListAccessPolicy`, `cwobject:DeleteAccessPolicy`.

In your local environment, you must have:

* A terminal. This tutorial is written for bash and zsh.
* [`kubectl`](https://kubernetes.io/docs/reference/kubectl/) installed and accessible from your terminal path.
* An S3 CLI client installed and accessible from your terminal path. This guide uses the [AWS CLI](https://aws.amazon.com/cli/) but any S3 CLI should work.

## Configure the CKS OIDC provider

Register your CKS cluster as a trusted OIDC identity provider for AI Object Storage. This lets Pods running in the cluster exchange their projected service account tokens for temporary S3 credentials.

1. Launch your CKS cluster.

2. In the Cloud Console, retrieve the OIDC Issuer URL of your CKS cluster:
   * Go to the [Clusters](https://console.coreweave.com/clusters) page.
   * Click the name of your desired cluster. A cluster details panel opens on the right.
   * Copy the OIDC Issuer URL from the **Overview** section.

3. Configure OIDC Workload Identity Federation in the Cloud Console using this OIDC Issuer URL.

   <Note>Your organization must be flagged for this feature.</Note>

4. Create a new OIDC configuration in the [Workload Federation](https://console.coreweave.com/organization/iam/workload-federation/oidc) page.
   * Click **Create OIDC configuration**. The configuration form opens.
   * Set the configuration name (choose a name that indicates it is for federating CKS tokens with AI Object Storage).
   * Enter the CKS cluster's OIDC Issuer URL that you copied earlier into the **Issuer URL** field.
   * Set the **Client ID (Audience)** field to `https://coreweave.com/iam` (recommended) or choose another audience.
   * Click **Create** to save the configuration.

## Configure `kubectl` and create a Kubernetes service account

1. Download a kubeconfig for your CKS cluster:
   1. Go to the [Tokens](https://console.coreweave.com/tokens) page.
   2. Click **Create Token**. The token creation form opens.
   3. Set the context for your cluster.
   4. Click **Download** to download the kubeconfig.

2. Using the kubeconfig you downloaded, export an environment variable that `kubectl` uses to locate your kubeconfig. Fill in the path to the kubeconfig file you downloaded:

   ```bash theme={"system"}
   export KUBECONFIG=[PATH-TO-KUBECONFIG-FILE]
   ```

3. Test that your `kubectl` installation works:

   ```bash theme={"system"}
   kubectl config get-contexts
   kubectl get nodes
   ```

   If the environment variable is set properly, you see the context you downloaded for your CKS environment from your `kubeconfig.yaml` file, and you see running Nodes for your CoreWeave environment.

4. Create a Kubernetes service account. Create a `.yaml` file with the following data and save it to a file named `test-service-account.yaml`:

   ```yaml title="test-service-account.yaml" theme={"system"}
   apiVersion: v1
   kind: ServiceAccount
   metadata:
     name: test-service-account
     namespace: default
   ```

5. Create the account:

   ```bash theme={"system"}
   kubectl apply -f test-service-account.yaml
   ```

6. Verify the account is created:

   ```bash theme={"system"}
   kubectl get serviceaccounts
   ```

   If successful, `test-service-account` is visible.

## Grant the service account access to Object Storage

You must grant the service account's federated identity access to AI Object Storage through an [organization access policy](/products/storage/object-storage/auth-access/organization-policies/about). Use the OIDC Issuer URL you copied earlier and the service account name to construct the WIF principal:

```text theme={"system"}
role/[OIDC-ISSUER-URL]:system:serviceaccount:default:test-service-account
```

Replace `[OIDC-ISSUER-URL]` with the OIDC Issuer URL from your cluster's details panel.

The following example policy grants the service account full S3 access to all buckets in your organization:

```json theme={"system"}
{
  "policy": {
    "version": "v1alpha1",
    "name": "wif-service-account-access",
    "statements": [
      {
        "name": "allow-s3-access-for-cks-workload",
        "effect": "Allow",
        "actions": ["s3:*", "cwobject:CreateAccessKeyOIDC"],
        "resources": ["*"],
        "principals": ["role/[OIDC-ISSUER-URL]:system:serviceaccount:default:test-service-account"]
      }
    ]
  }
}
```

Create this policy using the [Cloud Console](https://console.coreweave.com/organization/iam/workload-federation/oidc), with the [CoreWeave Terraform Provider](https://registry.terraform.io/providers/coreweave/coreweave/latest/docs/resources/object_storage_organization_access_policy), or the AI Object Storage API. For more granular policies (read-only access, specific buckets, multiple principals), see [Organization access policy examples](/products/storage/object-storage/auth-access/organization-policies/examples).

## Set up the workload

With the service account created and granted access, reference it from your AI Object Storage policies and from your workload Pod.

* You can define AI Object Storage policies that reference a role of the form `[ISSUER]:[SUBJECT]`, where the issuer is discovered through the well-known URL and the subject follows a standard pattern for Kubernetes service accounts, based on namespace and service account name.
* To get the OIDC well-known URL, go to the Cloud Console, navigate to the [Clusters](https://console.coreweave.com/clusters) page, select your cluster, and copy the OIDC Issuer URL.

Using the service account you created, use the following syntax for principals when you create your AI Object Storage org and bucket policies:

| Principal type                     | Syntax                                                                                                       |
| ---------------------------------- | ------------------------------------------------------------------------------------------------------------ |
| Principal                          | `[OIDC-ISSUER-URL]:system:serviceaccount:default:test-service-account`                                       |
| Organization policy `"principals"` | `["role/[OIDC-ISSUER-URL]:system:serviceaccount:default:test-service-account"]`                              |
| Bucket policy `"Principal"`        | `{"AWS": "arn:aws:iam::[ORG-ID]:role/[OIDC-ISSUER-URL]:system:serviceaccount:default:test-service-account"}` |

## Create the workload Pod

Create a Pod manifest that mounts a projected service account token with the correct audience. The Pod uses this token to exchange for temporary AI Object Storage credentials at runtime.

Replace `[ORG-ID]` with your CoreWeave organization ID, and replace `[CONTAINER-IMAGE]` with your application's container image:

To work with AI Object Storage, configure your Pod's S3 endpoints to use virtual addressing style and set the appropriate endpoint URL.

<Accordion title="Configure S3 endpoints for Pods">
  Because the environment variables handle credential exchange, you only need to configure the S3 endpoint and addressing style in your application. For example, with the AWS CLI:

  ```bash theme={"system"}
  aws configure set s3.addressing_style virtual
  aws configure set endpoint_url "http://cwlota.com"
  ```

  Alternatively, you can mount this configuration file into the container from a ConfigMap and set the `AWS_CONFIG_FILE` variable to the location of the mounted file.

  ```ini theme={"system"}
  [default]
  s3 =
      addressing_style = virtual
  endpoint_url = http://cwlota.com
  ```

  When your workloads run inside a CKS cluster, use the LOTA endpoint (`cwlota.com`) for optimal performance. For more configuration options (Boto3, s3cmd, Multi-Storage Client), see [Attaching endpoints](/products/storage/object-storage/using-object-storage/configure-endpoints#full-configuration-examples).
</Accordion>

```yaml title="workload-pod.yaml" theme={"system"}
apiVersion: v1
kind: Pod
metadata:
  name: my-workload
  namespace: default
spec:
  serviceAccountName: test-service-account
  containers:
  - name: app
    image: "[CONTAINER-IMAGE]"
    env:
    - name: AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE
      value: /var/run/secrets/tokens/oidc-token
    - name: AWS_CONTAINER_CREDENTIALS_FULL_URI
      value: "https://api.coreweave.com/v1/cwobject/temporary-credentials/oidc/[ORG-ID]"
    - name: AWS_DEFAULT_REGION
      value: "US-EAST-04A"
    volumeMounts:
    - name: oidc-token
      mountPath: /var/run/secrets/tokens
      readOnly: true
  volumes:
  - name: oidc-token
    projected:
      sources:
      - serviceAccountToken:
          path: oidc-token
          audience: "https://coreweave.com/iam"   # Or a custom audience
          expirationSeconds: 3600
```

1. Apply the manifest:

   ```bash theme={"system"}
   kubectl apply -f workload-pod.yaml
   ```

The projected token is mounted at `/var/run/secrets/tokens/oidc-token` inside the Pod. AWS SDKs and the AWS CLI automatically use the `AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE` and `AWS_CONTAINER_CREDENTIALS_FULL_URI` environment variables to exchange the OIDC token for temporary S3 credentials. Credentials rotate automatically based on the `expirationSeconds` value.

## Optional: Verify the setup

To confirm the projected token exchange works before you deploy your real workload, create a test Pod that uses the `amazon/aws-cli` image:

```yaml title="test-manual-pod.yaml" theme={"system"}
apiVersion: v1
kind: Pod
metadata:
  name: test-manual-oidc
  namespace: default
spec:
  serviceAccountName: test-service-account
  containers:
  - name: test
    image: amazon/aws-cli
    command:
    - sh
    - -c
    - |
        aws configure set s3.addressing_style virtual
        aws configure set endpoint_url http://cwlota.com
        aws s3api list-buckets
    env:
    - name: AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE
      value: /var/run/secrets/tokens/oidc-token
    - name: AWS_CONTAINER_CREDENTIALS_FULL_URI
      value: "https://api.coreweave.com/v1/cwobject/temporary-credentials/oidc/[ORG-ID]"
    - name: AWS_DEFAULT_REGION
      value: "US-EAST-04A"
    volumeMounts:
    - name: oidc-token
      mountPath: /var/run/secrets/tokens
      readOnly: true
  volumes:
  - name: oidc-token
    projected:
      sources:
      - serviceAccountToken:
          path: oidc-token
          audience: "https://coreweave.com/iam"   # Or a custom audience
          expirationSeconds: 3600
```

1. Apply the test Pod:

   ```bash theme={"system"}
   kubectl apply -f test-manual-pod.yaml
   ```

2. Check the Pod logs for the response:

   ```bash theme={"system"}
   kubectl logs test-manual-oidc
   ```

   If your OIDC configuration and organization access policies are configured correctly, you see a JSON response that lists your buckets. If you see an `AccessDenied` error, verify that your [organization access policies](/products/storage/object-storage/auth-access/organization-policies/about) grant the `s3:ListAllMyBuckets` action to the correct WIF principal.

3. Clean up the test Pod:

   ```bash theme={"system"}
   kubectl delete pod test-manual-oidc
   ```

## Optional: Validate locally

You can also validate the OIDC token exchange from your local machine, outside of a Kubernetes Pod, by creating a service account token and calling the credential endpoint directly. This helps with one-time testing and debugging when you want to isolate the credential exchange from the rest of your workload.

**Additional local prerequisites:**

* `curl` for calling the credential endpoint.
* `jq` for parsing JSON responses.
* [jwt.io](https://www.jwt.io/) (optional) for inspecting OIDC token contents.

### Test that the service account token can authenticate

Create a service account token and exchange it for temporary AI Object Storage credentials. Replace `[ORG-ID]` with your CoreWeave organization ID:

```bash theme={"system"}
curl \
    -H "Authorization: $(kubectl create token -n default test-service-account)" \
    "https://api.coreweave.com/v1/cwobject/temporary-credentials/oidc/[ORG-ID]" | jq
```

If authentication succeeds, you see a response similar to the following:

```json theme={"system"}
{
  "AccessKeyId": "CWAKIAEXAMPLE1234567",
  "SecretAccessKey": "wJalrXUtnFEMIK7MDENGbPxRfiCYEXAMPLEKEY",
  "Token": "",
  "Expiration": "2026-03-14T21:44:43Z",
  "attributes": {
    "cw-role": "https://oidc.example.coreweave.com/abc123:system:serviceaccount:default:test-service-account"
  }
}
```

### Test access with the AWS CLI

Configure a local AWS CLI profile that uses a credential process script to fetch temporary credentials. Replace `[CREDENTIAL-SCRIPT-PATH]` with the path to your credential script (for example, `/bin/cw-auth.sh`). The script must obtain a service account token, exchange it at the credential endpoint, and return JSON in the format the AWS CLI expects. For a full walkthrough of writing this script, see [Workload Identity Federation with a credential process](/products/storage/object-storage/using-object-storage/s3-clients/aws#workload-identity-federation-with-a-credential-process).

The following commands set the virtual addressing style, the credential process, the region, and the endpoint URL in a new profile called `cw-test`:

```bash theme={"system"}
export AWS_CONTAINER_AUTHORIZATION_TOKEN=$(kubectl create token -n default test-service-account)
export AWS_CONTAINER_CREDENTIALS_FULL_URI="https://api.coreweave.com/v1/cwobject/temporary-credentials/oidc/[ORG-ID]"

aws configure set s3.addressing_style virtual --profile cw-test
aws configure set credential_process "[CREDENTIAL-SCRIPT-PATH]" --profile cw-test
aws configure set region "US-EAST-04A" --profile cw-test
aws configure set endpoint_url "https://cwobject.com" --profile cw-test
```

<Note>
  Use the primary endpoint (`https://cwobject.com`) for local testing because the LOTA endpoint (`http://cwlota.com`) is accessible only from within CoreWeave clusters.
</Note>

Run an S3 command to verify the credential exchange works:

```bash theme={"system"}
aws s3api list-buckets --profile cw-test
```

## Next steps

* To use the automatic method instead, see [Automatic authentication with the Pod Identity Webhook](/security/tutorials/cks-object-storage-authentication/automatic).
* Learn more about [OIDC Workload Identity for CKS](/products/cks/auth-access/workload-identity/introduction).
* Learn more about [Workload Identity Federation for AI Object Storage](/products/storage/object-storage/auth-access/workload-identity-federation/use-oidc-tokens).
