> ## 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.

# Automatic authentication with the Pod Identity Webhook

> Configure automatic OIDC credential injection for CoreWeave AI Object Storage using the Pod Identity Webhook on CKS

This tutorial shows you how to automate CoreWeave Kubernetes Service (CKS) Workload Federation for CoreWeave AI Object Storage by configuring the Pod Identity Webhook. With the webhook in place, your Pods automatically receive the configuration needed to obtain temporary Object Storage credentials through their ServiceAccount. Your workloads can then access buckets without managing long-lived access keys. By the end, you'll have a CKS cluster federated with Object Storage and a sample workload that uses an annotated ServiceAccount to obtain credentials on demand.

## Prerequisites

* A [CKS cluster](/products/cks/clusters/create) with [OpenID Connect (OIDC) Workload Identity](/products/cks/auth-access/workload-identity/introduction) enabled.
* [`helm`](https://helm.sh/docs/intro/install/) version 3
* [`kubectl`](https://kubernetes.io/docs/reference/kubectl/) installed and configured for your cluster.

The following table separates roles that cover the administrative tasks from the narrower permissions used by this tutorial:

| Task | Role that covers the task | Granular permissions |
| - | - | - |
| Create or manage the CKS cluster | **CKS Admin** | After the cluster exists, Kubernetes RBAC controls whether you can install the Helm chart and create the tutorial's Namespace, ServiceAccount, and Pods. |
| Create an OIDC Workload Federation configuration if the automatic configuration is missing | **IAM Admin** | CoreWeave IAM Access Policies assign roles rather than individual IAM actions. |
| Create and view the Object Storage organization access policy | **Object Storage Admin** | `cwobject:EnsureAccessPolicy` and `cwobject:ListAccessPolicy` granted to your user through an existing organization access policy. Add `cwobject:DeleteAccessPolicy` if you must delete the policy. |
| Exchange the ServiceAccount token and run the verification command | No CoreWeave IAM role applies to the federated ServiceAccount. | Grant `cwobject:CreateAccessKeyOIDC` and `s3:ListAllMyBuckets` to the WIF principal in an Object Storage organization access policy, with `resources: ["*"]`. |

An Object Storage Admin must create the first organization access policy that delegates granular `cwobject:` permissions. The **Object Storage Admin** role governs the Object Storage control plane; it doesn't grant S3 data access.

## Install the Pod Identity Webhook

Install the Pod Identity Webhook to use Object Storage. The following steps install the webhook from [CoreWeave Charts](/products/cks/clusters/coreweave-charts/introduction):

1. Set environment variables for your organization ID and Availability Zone:

   * Replace `[ORG-ID]` with your organization's ID. You can find your organization ID on the [CoreWeave Console settings page](https://console.coreweave.com/account/settings).
   * Replace `[AVAILABILITY-ZONE]` with an Availability Zone that supports Object Storage.

   ```bash theme={"system"}
   export ORG_ID=[ORG-ID]
   export REGION=[AVAILABILITY-ZONE]
   ```

   <Accordion title="Availability Zones that support AI Object Storage">
     <Tabs>
       <Tab title="US-CENTRAL">
         * `US-CENTRAL-05A`
         * `US-CENTRAL-06A`
         * `US-CENTRAL-07A`
         * `US-CENTRAL-08A`
         * `US-CENTRAL-08B`
       </Tab>

       <Tab title="US-EAST">
         * `US-EAST-01A`
         * `US-EAST-02A`
         * `US-EAST-03A`
         * `US-EAST-04A`
         * `US-EAST-04B`
         * `US-EAST-06A`
         * `US-EAST-08A`
         * `US-EAST-13A`
         * `US-EAST-14A`
         * `US-EAST-15A`
         * `US-EAST-17A`
       </Tab>

       <Tab title="US-WEST">
         * `RNO2A`
         * `US-WEST-01A`
         * `US-WEST-04A`
         * `US-WEST-09B`
         * `US-WEST-10A`
       </Tab>

       <Tab title="CA-EAST">
         * `CA-EAST-01A`
       </Tab>

       <Tab title="EU-NORTH">
         * `EU-NORTH-05A`
       </Tab>

       <Tab title="EU-SOUTH">
         * `EU-SOUTH-03B`
         * `EU-SOUTH-04A`
       </Tab>
     </Tabs>

     Learn more about [Regions and Availability Zones](/platform/regions/about-regions-and-azs).
   </Accordion>

2. Add the CoreWeave Charts repository and install the Pod Identity Webhook:

   ```bash theme={"system"}
   helm repo add coreweave https://charts.core-services.ingress.coreweave.com
   helm install pod-identity-webhook coreweave/pod-identity-webhook \
     --namespace pod-identity-webhook \
     --create-namespace \
     --wait \
     --set config.orgID=$ORG_ID \
     --set config.region=$REGION
   ```

   The output resembles the following:

   ```text theme={"system"}
   "coreweave" has been added to your repositories
   NAME: pod-identity-webhook
   LAST DEPLOYED: Fri Mar 13 20:05:00 2026
   NAMESPACE: pod-identity-webhook
   STATUS: deployed
   REVISION: 1
   DESCRIPTION: Install complete
   ```

   With the `--wait` flag, Helm waits until the release resources are ready. The Pod Identity Webhook can then inject credential configuration into annotated Pods.

## Verify OIDC Workload Federation

Before the Pod Identity Webhook can obtain credentials, Object Storage must trust the OIDC tokens your CKS cluster issues. When you create a CKS cluster with OIDC Workload Identity enabled, CoreWeave registers this trust automatically. CoreWeave creates an OIDC configuration for the cluster with the audience `https://coreweave.com/iam`. This audience matches the default audience that the Pod Identity Webhook injects, so you don't need to create another OIDC configuration.

1. In the Cloud Console, retrieve the OIDC Issuer URL for your CKS cluster:
   * Go to the [Clusters](https://console.coreweave.com/clusters) page.
   * On the **Clusters** page, click the name of your cluster. A cluster details panel opens on the right.
   * In the **Cluster access** section, copy the **OIDC Issuer URL**. You need this URL again when you configure access policies.

2. On the [Workload Federation](https://console.coreweave.com/organization/iam/workload-federation/oidc) page, verify that the automatically created OIDC configuration for your cluster exists:
   * On the **Workload Federation** page, find the row that corresponds to your cluster. The automatically created configuration's description begins with "Auto-created OIDC workload federation config" and contains the cluster name. In the search field, enter the cluster name to filter for matching OIDC configurations.
   * Confirm that its **Issuer** matches your cluster's OIDC Issuer URL.
   * Confirm that its **Client ID (Audience)** is `https://coreweave.com/iam`.

### Configure OIDC workload identity federation manually

If the automatically created configuration is missing, create an OIDC workload identity federation (WIF) configuration manually:

1. In the Cloud Console, go to the [Create OIDC Configuration](https://console.coreweave.com/organization/iam/workload-federation/oidc/create) page.
2. Enter the following values:
   * **Configuration name**: A unique name for this configuration
   * **Issuer URL**: Your cluster's OIDC Issuer URL
   * **Client ID (Audience)**: `https://coreweave.com/iam`
3. On the **Create OIDC Configuration** page, click **Create**.

### Configure OIDC workload identity federation with a custom audience

If a workload needs a custom audience, create an additional OIDC configuration. Set **Issuer URL** to your cluster's OIDC Issuer URL. Set **Client ID (Audience)** to the custom audience. Then annotate the workload's ServiceAccount with `caios.coreweave.com/audience` set to that same custom audience, as described in [Use your ServiceAccount](#use-your-serviceaccount).

To change the default audience for every workload that uses the webhook, set the chart's `config.audience` value instead. See the [Pod Identity Webhook chart values](/products/cks/clusters/coreweave-charts/pod-identity-webhook) for details.

With the OIDC configuration in place, Object Storage trusts tokens issued by your CKS cluster and can map them to access policies.

## Use your ServiceAccount

The Pod Identity Webhook injects the configuration your Pods need to obtain Object Storage credentials. Add one of these annotations to the ServiceAccount that your workload uses:

| Audience type | Annotation syntax |
| - | - |
| Default audience | `caios.coreweave.com/inject: "true"` |
| Custom audience | `caios.coreweave.com/audience: custom`<br /><small>(use when you need to match a specific WIF audience)</small> |

Create a ServiceAccount with the appropriate annotation, then run your workload with that ServiceAccount.

1. Create the following manifest and save it to a file named `object-storage-sa.yaml`. This example uses the default audience annotation. For a custom audience, adjust the annotation:

   ```yaml title="object-storage-sa.yaml" highlight={6-7} theme={"system"}
   apiVersion: v1
   kind: ServiceAccount
   metadata:
     name: my-object-storage-sa
     namespace: default
     annotations:
       caios.coreweave.com/inject: "true"
   ```

2. Apply the manifest to create the ServiceAccount:

   ```bash theme={"system"}
   kubectl apply -f object-storage-sa.yaml
   ```

3. Verify that the ServiceAccount exists and has the appropriate annotation:

   ```bash theme={"system"}
   kubectl get serviceaccounts my-object-storage-sa -o jsonpath='{.metadata.annotations.caios\.coreweave\.com/inject}'
   true
   ```

   The `true` response confirms that the ServiceAccount has the default audience annotation.

## Grant the ServiceAccount access to Object Storage

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

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

```text theme={"system"}
role/[OIDC-ISSUER-URL]:system:serviceaccount:default:my-object-storage-sa
```

The verification Pod requires only `cwobject:CreateAccessKeyOIDC` to exchange its OIDC token and `s3:ListAllMyBuckets` to run `aws s3api list-buckets`. Both are global actions and require `resources: ["*"]`. For a production workload, replace `s3:ListAllMyBuckets` with the specific S3 actions and bucket resources that the workload needs.

The following example policy grants only the actions required by the verification Pod:

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

Create this policy using the [Cloud Console](https://console.coreweave.com/object-storage/access-policies), the [CoreWeave Terraform Provider](https://registry.terraform.io/providers/coreweave/coreweave/latest/docs/resources/object_storage_organization_access_policy), or the Object Storage API. Before you deploy your workload, replace `s3:ListAllMyBuckets` with its required S3 actions and resources. For examples, see [Organization access policy examples](/products/storage/object-storage/auth-access/organization-policies/examples).

After the policy is in place, it authorizes the ServiceAccount's federated identity to call Object Storage.

## Create a workload that uses the ServiceAccount

After you configure federation, the ServiceAccount, and an access policy, you can deploy a workload that obtains credentials through the webhook. This example creates a Pod that uses the ServiceAccount you created earlier.

1. Configure the Pod's S3 endpoints:

   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>

2. Create the following manifest and save it to a file named `object-storage-pod.yaml`. Make the following adjustments:

   * Replace `[CONTAINER-IMAGE]` with the container image that you want to use for your workload.
   * Reference the same ServiceAccount in your Pod so the Pod Identity Webhook can inject credential configuration:

   ```yaml title="object-storage-pod.yaml" highlight={7, 10} theme={"system"}
   apiVersion: v1
   kind: Pod
   metadata:
     name: my-workload
     namespace: default
   spec:
     serviceAccountName: my-object-storage-sa
     containers:
     - name: app
       image: "[CONTAINER-IMAGE]"
       # Your app uses the injected env or volume to obtain S3 credentials.
   ```

3. Apply the manifest to create the workload:

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

Pods that use this ServiceAccount receive the necessary environment or volume configuration to call Object Storage.

## Optional: Verify the webhook injection

Before you deploy your real workload, you can confirm that the Pod Identity Webhook injects credential configuration correctly. Create a test Pod that uses the `amazon/aws-cli:2.33.2` image and run an S3 command against Object Storage.

1. Create the following manifest and save it to a file named `test-webhook-pod.yaml`. The test Pod uses the ServiceAccount and lists your buckets:

   ```yaml title="test-webhook-pod.yaml" theme={"system"}
   apiVersion: v1
   kind: Pod
   metadata:
     name: test-webhook
     namespace: default
   spec:
     restartPolicy: Never
     serviceAccountName: my-object-storage-sa
     containers:
     - name: test
       image: amazon/aws-cli:2.33.2
       command:
       - sh
       - -c
       - |
           aws configure set s3.addressing_style virtual
           aws configure set endpoint_url http://cwlota.com
           aws s3api list-buckets
   ```

2. Apply the manifest:

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

3. Check the Pod logs for the response:

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

   When the webhook injection and your access policies are configured correctly, the logs contain a JSON response that lists your buckets. If you see an `AccessDenied` error, verify the organization policy. It must grant `cwobject:CreateAccessKeyOIDC` and `s3:ListAllMyBuckets` to the correct WIF principal with `resources: ["*"]`.

4. Clean up the test Pod:

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

## Next steps

* To configure OIDC Workload Federation manually or for debugging, see [Manual OIDC token exchange](/security/tutorials/cks-object-storage-authentication/manual).
* Learn more about [Workload Identity Federation for Object Storage](/products/storage/object-storage/auth-access/workload-identity-federation/use-oidc-tokens).
