Use Terraform to Create an Assumable Identity for a Jenkins Pipeline
Procedural tutorial outlining how to create a Chainguard identity with Terraform that can be assumed by a Jenkins …
Chainguard’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.
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.A Kubernetes cluster operates as an OIDC issuer. How you find the URL for that issuer depends on where the cluster is running.
The issuer URL for a GKE cluster will follow this format.
https://container.googleapis.com/v1/projects/<project>/locations/<location>/clusters/<cluster-name>
aws eks describe-cluster \
--name <cluster-name> \
--query "cluster.identity.oidc.issuer" \
--output text
az aks show \
--name <cluster-name> \
--resource-group <resource-group> \
--query "oidcIssuerProfile.issuerUrl" \
--output tsv
You can issue a token with kubectl
and find the issuer URL in the iss
claim with jwt
.
kubectl create token default | jwt decode -
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="<issuer-url>" \
--subject-pattern="system:serviceaccount:default:default" \
--role=registry.pull
This will return the ID of the identity which we will use in the next section.
If your cluster’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="$(kubectl get --raw /openid/v1/jwks)" \
--identity-issuer=<issuer-url> \
--subject=system:serviceaccount:default:default \
--role=registry.pull
Many 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.
Create pod.yaml
with this content. Replace <identity-id>
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 "Authorization: Bearer $IDENTITY_TOKEN" \
"https://issuer.enforce.dev/sts/exchange?aud=https://console-api.enforce.dev&identity=$IDENTITY" \
| jq -r .token
)
# List repos in the Chainguard registry
curl -sSf -H "Authorization: Bearer $API_TOKEN" https://console-api.enforce.dev/registry/v1/repos | jq -r .items[].name
env:
- name: IDENTITY
value: "<identity-id>"
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.dev
Then create the pod.
kubectl create -n default -f pod.yaml
Wait 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
Delete the pod.
kubectl -n default delete pod assumable-id-demo
Delete the identity.
chainctl iam id delete <identity-id>
For more information about how assumable identities work in Chainguard, check out our conceptual overview of assumable identities.
Last updated: 2025-08-07 13:00