# Create an Assumable Identity for a Kubernetes Pod

URL: https://edu.chainguard.dev/chainguard/administration/assumable-ids/identity-examples/kubernetes-identity.md
Last Modified: August 7, 2025
Tags: Chainguard Containers, Procedural

Procedural tutorial outlining how to create a Chainguard identity that can be assumed by a Kubernetes pod.

Chainguard&rsquo;s assumable identities are identities that can be assumed by external applications or workflows in order to perform certain tasks that would otherwise have to be done by a human.
This procedural tutorial outlines how to create an identity that can be assumed by a Kubernetes pod and then used to interact with the Chainguard API.
Prerequisites To complete this guide, you will need the following.
chainctl — the Chainguard command line interface tool — installed on your local machine. Follow our guide on How to Install chainctl to set this up. kubectl - the command line interface tool for Kubernetes. Access to a Kubernetes cluster. Find the Issuer URL of the Kubernetes Cluster A Kubernetes cluster operates as an OIDC issuer. How you find the URL for that issuer depends on where the cluster is running.
GKE (Google Kubernetes Engine) The issuer URL for a GKE cluster will follow this format.
https://container.googleapis.com/v1/projects/&lt;project&gt;/locations/&lt;location&gt;/clusters/&lt;cluster-name&gt; EKS (Amazon Elastic Kubernetes Service) aws eks describe-cluster \ --name &lt;cluster-name&gt; \ --query &#34;cluster.identity.oidc.issuer&#34; \ --output text AKS (Azure Kubernetes Service) az aks show \ --name &lt;cluster-name&gt; \ --resource-group &lt;resource-group&gt; \ --query &#34;oidcIssuerProfile.issuerUrl&#34; \ --output tsv Generic You can issue a token with kubectl and find the issuer URL in the iss claim with jwt.
kubectl create token default | jwt decode - Create an Assumable Identity Run this chainctl command to create an identity for the default service account in the default namespace and assign it the registry.pull role.
Provide the issuer URL you identified in the previous step.
chainctl iam id create example-identity \ --identity-issuer=&#34;&lt;issuer-url&gt;&#34; \ --subject-pattern=&#34;system:serviceaccount:default:default&#34; \ --role=registry.pullThis will return the ID of the identity which we will use in the next section.
If your cluster&rsquo;s issuer URL is not available over the internet then you can create an identity by exporting the JWKS (JSON Web Key Set) from the cluster with kubectl and provide it with the --issuer-keys flag.
chainctl iam identities create example-identity \ --issuer-keys=&#34;$(kubectl get --raw /openid/v1/jwks)&#34; \ --identity-issuer=&lt;issuer-url&gt; \ --subject=system:serviceaccount:default:default \ --role=registry.pullMany Kubernetes clusters will rotate the keys in the JWKS, so this command creates a static identity that expires after a period of time. The default duration is 30 days. In this scenario you should regularly recreate the identity with the latest JWKS.
Assume the Identity in a Pod Create pod.yaml with this content. Replace &lt;identity-id&gt; in the list of environment variables with the ID of the identity you created in the previous step.
apiVersion: v1 kind: Pod metadata: name: assumable-id-demo namespace: default spec: serviceAccountName: default restartPolicy: Never containers: - name: curl image: cgr.dev/chainguard/curl:latest-dev command: - sh - -c - | # Exchange the service account token for a Chainguard # API token IDENTITY_TOKEN=$(cat /var/run/chainguard/oidc/oidc-token) API_TOKEN=$(curl \ -sSf \ -H &#34;Authorization: Bearer $IDENTITY_TOKEN&#34; \ &#34;https://issuer.enforce.dev/sts/exchange?aud=https://console-api.enforce.dev&amp;identity=$IDENTITY&#34; \ | jq -r .token ) # List repos in the Chainguard registry curl -sSf -H &#34;Authorization: Bearer $API_TOKEN&#34; https://console-api.enforce.dev/registry/v1/repos | jq -r .items[].name env: - name: IDENTITY value: &#34;&lt;identity-id&gt;&#34; volumeMounts: - name: oidc-token mountPath: /var/run/chainguard/oidc readOnly: true volumes: - name: oidc-token projected: sources: - serviceAccountToken: path: oidc-token expirationSeconds: 600 audience: issuer.enforce.devThen create the pod.
kubectl create -n default -f pod.yamlWait for the pod to complete and then view the logs. It should return a list of the repositories in your organization.
kubectl -n default logs assumable-id-demo Clean Up Delete the pod.
kubectl -n default delete pod assumable-id-demoDelete the identity.
chainctl iam id delete &lt;identity-id&gt; Learn more For more information about how assumable identities work in Chainguard, check out our conceptual overview of assumable identities.

