From f6bf871eb00a9b2a7002215ce4656ffa9a1b0a33 Mon Sep 17 00:00:00 2001 From: ethernet Date: Fri, 31 Jul 2026 12:09:55 -0400 Subject: [PATCH] fix(ci): restore buildx cache reads on PR builds via pod WI login MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The PR-read-only hardening (1d5eb3bf4) gated the WIF auth step on non-PR events, which also silently gated the Artifact Registry docker login that step fed. The comment said "PRs read the cache via the pod's GKE Workload Identity", but pod WI is not ambient for buildx: with no login, cache-from does an anonymous pull against us-central1-docker.pkg.dev and gets 403 Forbidden (visible as "failed to configure registry cache importer" in every PR build since), so every PR built cache-cold (~12-16 min instead of ~2-3). Fix: on PR events, mint an access token from the pod's GKE metadata server (the runner pod's KSA impersonates gha-buildx-cache-ro@, which has only artifactregistry.reader) and feed it to the same docker login step. The security boundary is unchanged — PR builds still cannot write cache layers; cache-to remains gated on the WIF token that only exists on trusted main-push/release contexts. --- .github/workflows/docker.yml | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 163fc5e0547..31c3375db3a 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -92,13 +92,36 @@ jobs: service_account: gha-buildx-cache@hermes-agent-github-actions.iam.gserviceaccount.com token_format: access_token + # PR builds mint a READ-ONLY registry token from the runner pod's GKE + # Workload Identity instead. The pod's KSA (arc-runners/buildx-cache- + # reader) impersonates gha-buildx-cache-ro@, which holds only + # artifactregistry.reader on the ci-cache repo — so this token cannot + # write cache layers, and the layer-poisoning boundary above holds. + # + # This step is what actually turns pod WI into a docker credential: + # buildx only forwards auth that's present in the docker cred store, + # and there is no ambient cred helper for *.pkg.dev in the runner + # image — without an explicit login, cache-from falls back to an + # anonymous pull, gets 403, and every PR build runs cache-cold + # (~15 min instead of ~3). + - name: Mint read-only cache token (pod Workload Identity) + id: wi-token + if: github.event_name == 'pull_request' + run: | + set -euo pipefail + token=$(curl -sSf -H "Metadata-Flavor: Google" \ + "http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token" \ + | jq -r .access_token) + echo "::add-mask::$token" + echo "token=$token" >> "$GITHUB_OUTPUT" + - name: Log in to Artifact Registry - if: steps.gcp-auth.outputs.access_token != '' + if: steps.gcp-auth.outputs.access_token != '' || steps.wi-token.outputs.token != '' uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4.1.0 with: registry: us-central1-docker.pkg.dev username: oauth2accesstoken - password: ${{ steps.gcp-auth.outputs.access_token }} + password: ${{ steps.gcp-auth.outputs.access_token || steps.wi-token.outputs.token }} # Build once, load into the local daemon for testing. Cached # per-arch; the push step below reuses every layer from this build.