Create an Assumable Identity for a GitHub Actions Workflow

Tutorial outlining how to create a Chainguard identity that can be assumed by a GitHub Actions workflow.
  4 min read

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. For instance, an assumable identity can be used to allow a GitHub Actions workflow to pull images from cgr.dev without a static pull token.

This tutorial outlines how to create an identity, and then create a GitHub Actions workflow that will assume the identity to interact with Chainguard resources.

Prerequisites

To complete this guide, you will need the following.

  • One of:
    • chainctl — the Chainguard command line interface tool — installed on your local machine. Follow our guide on How to Install chainctl to set this up.
    • terraform installed on your local machine. Terraform is an Infrastructure as Code tool which this guide will use to create various cloud resources. Follow the official Terraform documentation for instructions on installing the tool.
  • A GitHub repository you can use for testing out GitHub identity federation. To complete this guide, you must have permissions to create GitHub Actions on this testing repo.

Creating an Identity

Chainctl

This command creates an identity that can be assumed by workflows in the my-org/repo-name repository. The identity is bound to the registry.pull role.

chainctl iam identities create github my-identity-name \
    --github-repo=my-org/repo-name \
    --role registry.pull

You can also include the --github-ref flag to restrict it to workflows that run from a specific branch. For instance, the main branch.

chainctl iam identities create github my-identity-name \
    --github-repo=my-org/repo-name \
    --github-ref=refs/heads/main \
    --role registry.pull

This will return the identity’s UIDP (unique identity path). Note this value down, as you’ll need it to set up the GitHub Actions workflow.

If you need to retrieve the UIDP later on, you can always run the following chainctl command to list the identity.

chainctl iam identities list --name=my-identity-name

Terraform

Alternatively, you could create the identity with the Chainguard Terraform provider.

Substitute your Chainguard organization name, GitHub organization and GitHub repository for <org-name>, <github-org> and <github-repo>, respectively.

data "chainguard_group" "org" {
  name = "<org-name>"
}

resource "chainguard_identity" "my_identity_name" {
  parent_id   = data.chainguard_group.org.id
  name        = "my-identity-name"

  claim_match {
    issuer  = "https://token.actions.githubusercontent.com"
    subject = "repo:<github-org>/<github-repo>:ref:refs/heads/main"
  }
}

data "chainguard_role" "registry_pull" {
  name = "registry.pull"
}

resource "chainguard_rolebinding" "my_identity_name_registry_pull" {
  identity = chainguard_identity.my_identity_name.id
  group	= data.chainguard_group.org.id
  role 	= data.chainguard_role.registry_pull.items[0].id
}

output "my_identity_name_id" {
  value = chainguard_identity.my_identity_name.id
}

In this example the chainguard_identity.my_identity_name resource defines an identity in your organization that can be assumed by a GitHub workflow that matches the claims in the claim_match block.

The chainguard_rolebinding.my_identity_name_registry_pull resource binds the registry.pull role to the identity.

The my_identity_name_id output provides the identity’s UIDP (unique identity path). You’ll need this value to set up the GitHub Actions workflow.

Creating and Testing a GitHub Actions Workflow

This example workflow definition assumes an identity with the setup-chainctl GitHub Action, lists repositories with chainctl and pulls an image from cgr.dev.

Commit this workflow to the main branch of your repository as .github/workflows/assume-and-explore.yaml, substituting <identity-id> with the UIDP of the assumable identity you created in the previous step and <org-name> with the name of your Chainguard organization.

name: Assume and Explore

on:
  workflow_dispatch: {}

jobs:
  assume-and-explore:
    name: actions assume example

    permissions:
      id-token: write

    runs-on: ubuntu-latest
    steps:

    - uses: chainguard-dev/setup-chainctl@main
      with:
        identity: <identity-id>

    - run: |
        chainctl image repo list --parent=<org-name>

    - run: |
        docker pull cgr.dev/<org-name>/example-image:latest

Once its committed, you can trigger the workflow by navigating to Actions > Assume And Explore from the home page of your repository and selecting Run workflow.

Learn more

For more information about how assumable identities work in Chainguard, check out our conceptual overview of assumable identities. Additionally, the Terraform documentation includes a section on recommended best practices which you can refer to if you’d like to build on the provided Terraform configuration for a production environment. Likewise, for more information on using GitHub Actions, we encourage you to check out the official documentation on the subject.

Last updated: 2025-11-28 06:00