From e9f09b545dc6b913c8f9f549f7947af4d39e5015 Mon Sep 17 00:00:00 2001 From: Danilo Horta Date: Mon, 11 May 2026 14:52:21 +0100 Subject: [PATCH 1/3] build/bake,build: add Chainguard OIDC keyless cgr.dev auth (opt-in) Add four opt-in inputs to bake.yml and build.yml: chainguard-identity, chainguard-registry, chainguard-apk-host, chainguard-libraries-host. When chainguard-identity is set, the build and finalize jobs install chainctl via chainguard-dev/setup-chainctl@v0.5.1 and register it as a Docker credential helper for cgr.dev. The Chainguard pull token is minted inside the build/finalize job runners and never crosses the workflow_call boundary into the caller's registry-auths secret, where it would be silently stripped by GitHub's cross-job output masker (#146 documents the equivalent GCP WIF failure mode). No existing input changes; registry-auths continues to handle every static-credential registry as before and can be combined with chainguard-identity for multi-registry builds. Refs: #146 --- .github/workflows/bake.yml | 35 +++++++++++++++++++++++++++++++ .github/workflows/build.yml | 35 +++++++++++++++++++++++++++++++ README.md | 41 +++++++++++++++++++++++++++++++++++++ 3 files changed, 111 insertions(+) diff --git a/.github/workflows/bake.yml b/.github/workflows/bake.yml index e9b3a0a..44d634e 100644 --- a/.github/workflows/bake.yml +++ b/.github/workflows/bake.yml @@ -126,6 +126,25 @@ on: type: string description: "Bake target name for metadata (defaults to docker-metadata-action)" required: false + chainguard-identity: + type: string + description: "UIDP of a Chainguard identity to assume via GitHub OIDC for keyless cgr.dev authentication" + required: false + chainguard-registry: + type: string + description: "Chainguard OCI registry host" + required: false + default: cgr.dev + chainguard-apk-host: + type: string + description: "Hostname for APK-related Chainguard authentication (passed through to chainguard-dev/setup-chainctl)" + required: false + default: apk.cgr.dev + chainguard-libraries-host: + type: string + description: "Hostname for Chainguard Libraries authentication (passed through to chainguard-dev/setup-chainctl)" + required: false + default: libraries.cgr.dev secrets: registry-auths: description: "Raw authentication to registries, defined as YAML objects (for image output)" @@ -907,6 +926,14 @@ jobs: core.info(JSON.stringify(bakeOverrides, null, 2)); core.setOutput('overrides', bakeOverrides.join(os.EOL)); }); + - + name: Set up chainctl + if: ${{ inputs.chainguard-identity != '' && inputs.push && inputs.output == 'image' }} + uses: chainguard-dev/setup-chainctl@2cddd35a2f120d9973e58094dc6878c93cf58c28 # v0.5.1 + with: + identity: ${{ inputs.chainguard-identity }} + apk-host: ${{ inputs.chainguard-apk-host }} + libraries-host: ${{ inputs.chainguard-libraries-host }} - name: Login to registry if: ${{ inputs.push && inputs.output == 'image' }} @@ -1091,6 +1118,14 @@ jobs: labels: ${{ inputs.meta-labels }} annotations: ${{ inputs.meta-annotations }} bake-target: ${{ inputs.meta-bake-target }} + - + name: Set up chainctl + if: ${{ inputs.chainguard-identity != '' && inputs.push && inputs.output == 'image' }} + uses: chainguard-dev/setup-chainctl@2cddd35a2f120d9973e58094dc6878c93cf58c28 # v0.5.1 + with: + identity: ${{ inputs.chainguard-identity }} + apk-host: ${{ inputs.chainguard-apk-host }} + libraries-host: ${{ inputs.chainguard-libraries-host }} - name: Login to registry if: ${{ inputs.push && inputs.output == 'image' }} diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index d1a46c2..9d8c5a2 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -129,6 +129,25 @@ on: type: string description: "Flavor defines a global behavior for meta-tags" required: false + chainguard-identity: + type: string + description: "UIDP of a Chainguard identity to assume via GitHub OIDC for keyless cgr.dev authentication" + required: false + chainguard-registry: + type: string + description: "Chainguard OCI registry host" + required: false + default: cgr.dev + chainguard-apk-host: + type: string + description: "Hostname for APK-related Chainguard authentication (passed through to chainguard-dev/setup-chainctl)" + required: false + default: apk.cgr.dev + chainguard-libraries-host: + type: string + description: "Hostname for Chainguard Libraries authentication (passed through to chainguard-dev/setup-chainctl)" + required: false + default: libraries.cgr.dev secrets: registry-auths: description: "Raw authentication to registries, defined as YAML objects (for image output)" @@ -766,6 +785,14 @@ jobs: // for a public repository, we set max provenance mode core.setOutput('provenance', Build.resolveProvenanceAttrs(`mode=max,version=v1`)); } + - + name: Set up chainctl + if: ${{ inputs.chainguard-identity != '' && inputs.push && inputs.output == 'image' }} + uses: chainguard-dev/setup-chainctl@2cddd35a2f120d9973e58094dc6878c93cf58c28 # v0.5.1 + with: + identity: ${{ inputs.chainguard-identity }} + apk-host: ${{ inputs.chainguard-apk-host }} + libraries-host: ${{ inputs.chainguard-libraries-host }} - name: Login to registry if: ${{ inputs.push && inputs.output == 'image' }} @@ -946,6 +973,14 @@ jobs: flavor: ${{ inputs.meta-flavor }} labels: ${{ inputs.meta-labels }} annotations: ${{ inputs.meta-annotations }} + - + name: Set up chainctl + if: ${{ inputs.chainguard-identity != '' && inputs.push && inputs.output == 'image' }} + uses: chainguard-dev/setup-chainctl@2cddd35a2f120d9973e58094dc6878c93cf58c28 # v0.5.1 + with: + identity: ${{ inputs.chainguard-identity }} + apk-host: ${{ inputs.chainguard-apk-host }} + libraries-host: ${{ inputs.chainguard-libraries-host }} - name: Login to registry if: ${{ inputs.push && inputs.output == 'image' }} diff --git a/README.md b/README.md index 3f7d031..97f5166 100644 --- a/README.md +++ b/README.md @@ -19,6 +19,7 @@ ___ * [Notes](#notes) * [Runner mapping](#runner-mapping) * [Metadata templates](#metadata-templates) + * [Chainguard keyless authentication](#chainguard-keyless-authentication) ## Overview @@ -233,6 +234,10 @@ jobs: | `meta-images` | List | | [List of images](https://github.com/docker/metadata-action?tab=readme-ov-file#images-input) to use as base name for tags (required for image output) | | `meta-tags` | List | | [List of tags](https://github.com/docker/metadata-action?tab=readme-ov-file#tags-input) as key-value pair attributes | | `meta-flavor` | List | | [Flavor](https://github.com/docker/metadata-action?tab=readme-ov-file#flavor-input) defines a global behavior for `meta-tags` | +| `chainguard-identity` | String | | UIDP of a Chainguard identity to assume via GitHub OIDC for keyless `cgr.dev` authentication. See [Chainguard keyless authentication](#chainguard-keyless-authentication) | +| `chainguard-registry` | String | `cgr.dev` | Chainguard OCI registry host | +| `chainguard-apk-host` | String | `apk.cgr.dev` | Hostname for APK-related Chainguard authentication. Passed through to `chainguard-dev/setup-chainctl` | +| `chainguard-libraries-host` | String | `libraries.cgr.dev` | Hostname for Chainguard Libraries authentication. Passed through to `chainguard-dev/setup-chainctl` | ### Secrets @@ -342,6 +347,10 @@ jobs: | `meta-labels` | List | | [List of custom labels](https://github.com/docker/metadata-action?tab=readme-ov-file#overwrite-labels-and-annotations) | | `meta-annotations` | List | | [List of custom annotations](https://github.com/docker/metadata-action?tab=readme-ov-file#overwrite-labels-and-annotations) | | `meta-flavor` | List | | [Flavor](https://github.com/docker/metadata-action?tab=readme-ov-file#flavor-input) defines a global behavior for `meta-tags` | +| `chainguard-identity` | String | | UIDP of a Chainguard identity to assume via GitHub OIDC for keyless `cgr.dev` authentication. See [Chainguard keyless authentication](#chainguard-keyless-authentication) | +| `chainguard-registry` | String | `cgr.dev` | Chainguard OCI registry host | +| `chainguard-apk-host` | String | `apk.cgr.dev` | Hostname for APK-related Chainguard authentication. Passed through to `chainguard-dev/setup-chainctl` | +| `chainguard-libraries-host` | String | `libraries.cgr.dev` | Hostname for Chainguard Libraries authentication. Passed through to `chainguard-dev/setup-chainctl` | ### Secrets @@ -431,3 +440,35 @@ jobs: *.args.VERSION={{meta.version}} meta-images: name/app ``` + +### Chainguard keyless authentication + +Setting `chainguard-identity` authenticates to `cgr.dev` via GitHub +OIDC, avoiding a static credential. The workflow runs +[`chainguard-dev/setup-chainctl`](https://github.com/chainguard-dev/setup-chainctl) +inside the `build` and `finalize` jobs so the token is minted on the +build runner and never crosses the `workflow_call` boundary (see +[`docker/github-builder#146`](https://github.com/docker/github-builder/issues/146)). + +```yaml +jobs: + bake: + uses: docker/github-builder/.github/workflows/bake.yml@v1 + permissions: + contents: read + id-token: write + with: + output: image + push: true + meta-images: cgr.dev/your-org/your-image + chainguard-identity: 70e4ec6.../79304d... +``` + +`chainguard-identity` can be combined with `registry-auths` for +multi-registry pushes. + +> [!IMPORTANT] +> `chainguard-dev/setup-chainctl` also authenticates against +> `apk.cgr.dev` and `libraries.cgr.dev`. The assumed identity must be +> claim-matched for those audiences, or `chainguard-apk-host` / +> `chainguard-libraries-host` must be redirected. From 4d9992f8a18977e2652f2d2bc7dad79514b00744 Mon Sep 17 00:00:00 2001 From: Danilo Horta Date: Mon, 11 May 2026 15:35:56 +0100 Subject: [PATCH 2/3] docs(readme): align chainguard parameter table formatting --- README.md | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 97f5166..d8eb140 100644 --- a/README.md +++ b/README.md @@ -234,10 +234,9 @@ jobs: | `meta-images` | List | | [List of images](https://github.com/docker/metadata-action?tab=readme-ov-file#images-input) to use as base name for tags (required for image output) | | `meta-tags` | List | | [List of tags](https://github.com/docker/metadata-action?tab=readme-ov-file#tags-input) as key-value pair attributes | | `meta-flavor` | List | | [Flavor](https://github.com/docker/metadata-action?tab=readme-ov-file#flavor-input) defines a global behavior for `meta-tags` | -| `chainguard-identity` | String | | UIDP of a Chainguard identity to assume via GitHub OIDC for keyless `cgr.dev` authentication. See [Chainguard keyless authentication](#chainguard-keyless-authentication) | -| `chainguard-registry` | String | `cgr.dev` | Chainguard OCI registry host | -| `chainguard-apk-host` | String | `apk.cgr.dev` | Hostname for APK-related Chainguard authentication. Passed through to `chainguard-dev/setup-chainctl` | -| `chainguard-libraries-host` | String | `libraries.cgr.dev` | Hostname for Chainguard Libraries authentication. Passed through to `chainguard-dev/setup-chainctl` | +| `chainguard-identity` | String | | UIDP of a Chainguard identity to assume via GitHub OIDC for keyless `cgr.dev` authentication. See [Chainguard keyless authentication](#chainguard-keyless-authentication) | +| `chainguard-apk-host` | String | `apk.cgr.dev` | Hostname for APK-related Chainguard authentication. Passed through to `chainguard-dev/setup-chainctl` | +| `chainguard-libraries-host` | String | `libraries.cgr.dev` | Hostname for Chainguard Libraries authentication. Passed through to `chainguard-dev/setup-chainctl` | ### Secrets @@ -347,10 +346,9 @@ jobs: | `meta-labels` | List | | [List of custom labels](https://github.com/docker/metadata-action?tab=readme-ov-file#overwrite-labels-and-annotations) | | `meta-annotations` | List | | [List of custom annotations](https://github.com/docker/metadata-action?tab=readme-ov-file#overwrite-labels-and-annotations) | | `meta-flavor` | List | | [Flavor](https://github.com/docker/metadata-action?tab=readme-ov-file#flavor-input) defines a global behavior for `meta-tags` | -| `chainguard-identity` | String | | UIDP of a Chainguard identity to assume via GitHub OIDC for keyless `cgr.dev` authentication. See [Chainguard keyless authentication](#chainguard-keyless-authentication) | -| `chainguard-registry` | String | `cgr.dev` | Chainguard OCI registry host | -| `chainguard-apk-host` | String | `apk.cgr.dev` | Hostname for APK-related Chainguard authentication. Passed through to `chainguard-dev/setup-chainctl` | -| `chainguard-libraries-host` | String | `libraries.cgr.dev` | Hostname for Chainguard Libraries authentication. Passed through to `chainguard-dev/setup-chainctl` | +| `chainguard-identity` | String | | UIDP of a Chainguard identity to assume via GitHub OIDC for keyless `cgr.dev` authentication. See [Chainguard keyless authentication](#chainguard-keyless-authentication) | +| `chainguard-apk-host` | String | `apk.cgr.dev` | Hostname for APK-related Chainguard authentication. Passed through to `chainguard-dev/setup-chainctl` | +| `chainguard-libraries-host` | String | `libraries.cgr.dev` | Hostname for Chainguard Libraries authentication. Passed through to `chainguard-dev/setup-chainctl` | ### Secrets From b7b52df417fa26cec809961a8b458e1ece50519a Mon Sep 17 00:00:00 2001 From: Danilo Horta Date: Mon, 11 May 2026 15:36:00 +0100 Subject: [PATCH 3/3] ci(workflows): remove unused chainguard-registry parameter --- .github/workflows/bake.yml | 5 ----- .github/workflows/build.yml | 5 ----- 2 files changed, 10 deletions(-) diff --git a/.github/workflows/bake.yml b/.github/workflows/bake.yml index 44d634e..85e2e44 100644 --- a/.github/workflows/bake.yml +++ b/.github/workflows/bake.yml @@ -130,11 +130,6 @@ on: type: string description: "UIDP of a Chainguard identity to assume via GitHub OIDC for keyless cgr.dev authentication" required: false - chainguard-registry: - type: string - description: "Chainguard OCI registry host" - required: false - default: cgr.dev chainguard-apk-host: type: string description: "Hostname for APK-related Chainguard authentication (passed through to chainguard-dev/setup-chainctl)" diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 9d8c5a2..5747054 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -133,11 +133,6 @@ on: type: string description: "UIDP of a Chainguard identity to assume via GitHub OIDC for keyless cgr.dev authentication" required: false - chainguard-registry: - type: string - description: "Chainguard OCI registry host" - required: false - default: cgr.dev chainguard-apk-host: type: string description: "Hostname for APK-related Chainguard authentication (passed through to chainguard-dev/setup-chainctl)"