Skip to content

Commit 0200bc8

Browse files
committed
build/bake: support GCP WIF registry identities
Signed-off-by: CrazyMax <1951866+crazy-max@users.noreply.github.com>
1 parent 27181d3 commit 0200bc8

4 files changed

Lines changed: 172 additions & 3 deletions

File tree

.github/workflows/bake.yml

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -999,6 +999,27 @@ jobs:
999999
uses: docker/login-action@af1e73f918a031802d376d3c8bbc3fe56130a9b0 # v4.4.0
10001000
with:
10011001
registry-auth: ${{ needs.registry-identities.outputs.aws-ecr-registry-auth }}
1002+
-
1003+
name: Authenticate to Google Cloud
1004+
id: gcp-wif-auth
1005+
if: ${{ needs.registry-identities.outputs.gcp-wif-enabled == 'true' }}
1006+
uses: google-github-actions/auth@7c6bc770dae815cd3e89ee6cdf493a5fab2cc093 # v3.0.0
1007+
with:
1008+
token_format: access_token
1009+
workload_identity_provider: ${{ needs.registry-identities.outputs.gcp-wif-workload-identity-provider }}
1010+
service_account: ${{ needs.registry-identities.outputs.gcp-wif-service-account }}
1011+
project_id: ${{ needs.registry-identities.outputs.gcp-wif-project-id }}
1012+
create_credentials_file: false
1013+
export_environment_variables: false
1014+
-
1015+
name: Login to Google Artifact Registry
1016+
if: ${{ needs.registry-identities.outputs.gcp-wif-enabled == 'true' }}
1017+
uses: docker/login-action@af1e73f918a031802d376d3c8bbc3fe56130a9b0 # v4.4.0
1018+
with:
1019+
registry-auth: |
1020+
- registry: ${{ needs.registry-identities.outputs.gcp-wif-registry }}
1021+
username: oauth2accesstoken
1022+
password: ${{ steps.gcp-wif-auth.outputs.access_token }}
10021023
-
10031024
name: Login to registry
10041025
if: ${{ inputs.push && inputs.output == 'image' && env.REGISTRY_AUTHS_PRESENT == 'true' }}
@@ -1219,6 +1240,27 @@ jobs:
12191240
uses: docker/login-action@af1e73f918a031802d376d3c8bbc3fe56130a9b0 # v4.4.0
12201241
with:
12211242
registry-auth: ${{ needs.registry-identities.outputs.aws-ecr-registry-auth }}
1243+
-
1244+
name: Authenticate to Google Cloud
1245+
id: gcp-wif-auth
1246+
if: ${{ inputs.push && inputs.output == 'image' && needs.registry-identities.outputs.gcp-wif-enabled == 'true' }}
1247+
uses: google-github-actions/auth@7c6bc770dae815cd3e89ee6cdf493a5fab2cc093 # v3.0.0
1248+
with:
1249+
token_format: access_token
1250+
workload_identity_provider: ${{ needs.registry-identities.outputs.gcp-wif-workload-identity-provider }}
1251+
service_account: ${{ needs.registry-identities.outputs.gcp-wif-service-account }}
1252+
project_id: ${{ needs.registry-identities.outputs.gcp-wif-project-id }}
1253+
create_credentials_file: false
1254+
export_environment_variables: false
1255+
-
1256+
name: Login to Google Artifact Registry
1257+
if: ${{ inputs.push && inputs.output == 'image' && needs.registry-identities.outputs.gcp-wif-enabled == 'true' }}
1258+
uses: docker/login-action@af1e73f918a031802d376d3c8bbc3fe56130a9b0 # v4.4.0
1259+
with:
1260+
registry-auth: |
1261+
- registry: ${{ needs.registry-identities.outputs.gcp-wif-registry }}
1262+
username: oauth2accesstoken
1263+
password: ${{ steps.gcp-wif-auth.outputs.access_token }}
12221264
-
12231265
name: Login to registry
12241266
if: ${{ inputs.push && inputs.output == 'image' && env.REGISTRY_AUTHS_PRESENT == 'true' }}

.github/workflows/build.yml

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -865,6 +865,27 @@ jobs:
865865
uses: docker/login-action@af1e73f918a031802d376d3c8bbc3fe56130a9b0 # v4.4.0
866866
with:
867867
registry-auth: ${{ needs.registry-identities.outputs.aws-ecr-registry-auth }}
868+
-
869+
name: Authenticate to Google Cloud
870+
id: gcp-wif-auth
871+
if: ${{ needs.registry-identities.outputs.gcp-wif-enabled == 'true' }}
872+
uses: google-github-actions/auth@7c6bc770dae815cd3e89ee6cdf493a5fab2cc093 # v3.0.0
873+
with:
874+
token_format: access_token
875+
workload_identity_provider: ${{ needs.registry-identities.outputs.gcp-wif-workload-identity-provider }}
876+
service_account: ${{ needs.registry-identities.outputs.gcp-wif-service-account }}
877+
project_id: ${{ needs.registry-identities.outputs.gcp-wif-project-id }}
878+
create_credentials_file: false
879+
export_environment_variables: false
880+
-
881+
name: Login to Google Artifact Registry
882+
if: ${{ needs.registry-identities.outputs.gcp-wif-enabled == 'true' }}
883+
uses: docker/login-action@af1e73f918a031802d376d3c8bbc3fe56130a9b0 # v4.4.0
884+
with:
885+
registry-auth: |
886+
- registry: ${{ needs.registry-identities.outputs.gcp-wif-registry }}
887+
username: oauth2accesstoken
888+
password: ${{ steps.gcp-wif-auth.outputs.access_token }}
868889
-
869890
name: Login to registry
870891
if: ${{ inputs.push && inputs.output == 'image' && env.REGISTRY_AUTHS_PRESENT == 'true' }}
@@ -1081,6 +1102,27 @@ jobs:
10811102
uses: docker/login-action@af1e73f918a031802d376d3c8bbc3fe56130a9b0 # v4.4.0
10821103
with:
10831104
registry-auth: ${{ needs.registry-identities.outputs.aws-ecr-registry-auth }}
1105+
-
1106+
name: Authenticate to Google Cloud
1107+
id: gcp-wif-auth
1108+
if: ${{ inputs.push && inputs.output == 'image' && needs.registry-identities.outputs.gcp-wif-enabled == 'true' }}
1109+
uses: google-github-actions/auth@7c6bc770dae815cd3e89ee6cdf493a5fab2cc093 # v3.0.0
1110+
with:
1111+
token_format: access_token
1112+
workload_identity_provider: ${{ needs.registry-identities.outputs.gcp-wif-workload-identity-provider }}
1113+
service_account: ${{ needs.registry-identities.outputs.gcp-wif-service-account }}
1114+
project_id: ${{ needs.registry-identities.outputs.gcp-wif-project-id }}
1115+
create_credentials_file: false
1116+
export_environment_variables: false
1117+
-
1118+
name: Login to Google Artifact Registry
1119+
if: ${{ inputs.push && inputs.output == 'image' && needs.registry-identities.outputs.gcp-wif-enabled == 'true' }}
1120+
uses: docker/login-action@af1e73f918a031802d376d3c8bbc3fe56130a9b0 # v4.4.0
1121+
with:
1122+
registry-auth: |
1123+
- registry: ${{ needs.registry-identities.outputs.gcp-wif-registry }}
1124+
username: oauth2accesstoken
1125+
password: ${{ steps.gcp-wif-auth.outputs.access_token }}
10841126
-
10851127
name: Login to registry
10861128
if: ${{ inputs.push && inputs.output == 'image' && env.REGISTRY_AUTHS_PRESENT == 'true' }}

.github/workflows/setup-registry-identities.yml

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,21 @@ on:
2020
aws-ecr-registry-auth:
2121
description: "Registry auth YAML for Docker login"
2222
value: ${{ jobs.setup-registry-identities.outputs.aws-ecr-registry-auth }}
23+
gcp-wif-enabled:
24+
description: "Whether a GCP Workload Identity Federation registry identity was configured"
25+
value: ${{ jobs.setup-registry-identities.outputs.gcp-wif-enabled }}
26+
gcp-wif-registry:
27+
description: "Google Artifact Registry host to authenticate against"
28+
value: ${{ jobs.setup-registry-identities.outputs.gcp-wif-registry }}
29+
gcp-wif-workload-identity-provider:
30+
description: "GCP Workload Identity Provider resource name"
31+
value: ${{ jobs.setup-registry-identities.outputs.gcp-wif-workload-identity-provider }}
32+
gcp-wif-service-account:
33+
description: "GCP service account to impersonate"
34+
value: ${{ jobs.setup-registry-identities.outputs.gcp-wif-service-account }}
35+
gcp-wif-project-id:
36+
description: "GCP project ID"
37+
value: ${{ jobs.setup-registry-identities.outputs.gcp-wif-project-id }}
2338

2439
env:
2540
RUNTIME_MODULE: "@docker/github-builder-runtime@0.92.0"
@@ -42,6 +57,11 @@ jobs:
4257
aws-ecr-role-to-assume: ${{ steps.validate.outputs.aws-ecr-role-to-assume }}
4358
aws-ecr-region: ${{ steps.validate.outputs.aws-ecr-region }}
4459
aws-ecr-registry-auth: ${{ steps.validate.outputs.aws-ecr-registry-auth }}
60+
gcp-wif-enabled: ${{ steps.validate.outputs.gcp-wif-enabled }}
61+
gcp-wif-registry: ${{ steps.validate.outputs.gcp-wif-registry }}
62+
gcp-wif-workload-identity-provider: ${{ steps.validate.outputs.gcp-wif-workload-identity-provider }}
63+
gcp-wif-service-account: ${{ steps.validate.outputs.gcp-wif-service-account }}
64+
gcp-wif-project-id: ${{ steps.validate.outputs.gcp-wif-project-id }}
4565
steps:
4666
-
4767
name: Install dependencies
@@ -86,6 +106,11 @@ jobs:
86106
core.setOutput('aws-ecr-role-to-assume', '');
87107
core.setOutput('aws-ecr-region', '');
88108
core.setOutput('aws-ecr-registry-auth', '');
109+
core.setOutput('gcp-wif-enabled', 'false');
110+
core.setOutput('gcp-wif-registry', '');
111+
core.setOutput('gcp-wif-workload-identity-provider', '');
112+
core.setOutput('gcp-wif-service-account', '');
113+
core.setOutput('gcp-wif-project-id', '');
89114
};
90115
91116
const registryIdentities = core.getInput('registry-identities', {trimWhitespace: false});
@@ -135,6 +160,7 @@ jobs:
135160
}
136161
137162
let awsEcr;
163+
let gcpWif;
138164
entries.forEach((entry, index) => {
139165
const path = `registry-identities[${index}]`;
140166
ensureObject(entry, path);
@@ -162,6 +188,24 @@ jobs:
162188
};
163189
break;
164190
}
191+
case 'gcp-wif': {
192+
const allowedKeys = new Set(['type', 'registry', 'workload_identity_provider', 'service_account', 'project_id']);
193+
for (const key of Object.keys(entry)) {
194+
if (!allowedKeys.has(key)) {
195+
fail(`${path}.${key} is not supported for gcp-wif`);
196+
}
197+
}
198+
if (gcpWif) {
199+
fail('only one gcp-wif registry identity is supported');
200+
}
201+
gcpWif = {
202+
registry: requireString(entry, 'registry', path),
203+
workloadIdentityProvider: requireString(entry, 'workload_identity_provider', path),
204+
serviceAccount: requireString(entry, 'service_account', path),
205+
projectId: requireString(entry, 'project_id', path)
206+
};
207+
break;
208+
}
165209
default:
166210
fail(`${path}.type has unsupported provider ${type}`);
167211
}
@@ -171,3 +215,8 @@ jobs:
171215
core.setOutput('aws-ecr-role-to-assume', awsEcr?.roleToAssume || '');
172216
core.setOutput('aws-ecr-region', awsEcr?.awsRegion || '');
173217
core.setOutput('aws-ecr-registry-auth', awsEcr?.registryAuth || '');
218+
core.setOutput('gcp-wif-enabled', gcpWif ? 'true' : 'false');
219+
core.setOutput('gcp-wif-registry', gcpWif?.registry || '');
220+
core.setOutput('gcp-wif-workload-identity-provider', gcpWif?.workloadIdentityProvider || '');
221+
core.setOutput('gcp-wif-service-account', gcpWif?.serviceAccount || '');
222+
core.setOutput('gcp-wif-project-id', gcpWif?.projectId || '');

README.md

Lines changed: 39 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ ___
1919
* [Notes](#notes)
2020
* [Signed GitHub Actions cache](#signed-github-actions-cache)
2121
* [Registry identities](#registry-identities)
22+
* [AWS ECR](#aws-ecr)
23+
* [Google Artifact Registry](#google-artifact-registry)
2224
* [Runner mapping](#runner-mapping)
2325
* [Metadata templates](#metadata-templates)
2426

@@ -412,9 +414,11 @@ secret. Provider-specific authentication steps are pinned in these reusable
412414
workflows; callers can only select supported provider types and pass identity
413415
configuration.
414416

415-
Amazon ECR private registry authentication is configured with `type: aws-ecr`.
416-
Callers must grant `id-token: write` so the AWS credential step can assume the
417-
role through GitHub OIDC:
417+
#### AWS ECR
418+
419+
Amazon ECR registry authentication is configured with `type: aws-ecr`. Callers
420+
must grant `id-token: write` so the AWS credential step can assume the role
421+
through GitHub OIDC:
418422

419423
```yaml
420424
jobs:
@@ -439,6 +443,38 @@ The `registry` value is required for AWS ECR. Use the registry server that
439443
`docker/login-action` should log in to, such as `public.ecr.aws` for public ECR
440444
or `123456789100.dkr.ecr.us-east-1.amazonaws.com` for private ECR.
441445

446+
#### Google Artifact Registry
447+
448+
Google Artifact Registry authentication is configured with `type: gcp-wif`.
449+
Callers must grant `id-token: write` so `google-github-actions/auth` can
450+
exchange the GitHub OIDC token through GCP Workload Identity Federation:
451+
452+
```yaml
453+
jobs:
454+
build:
455+
uses: docker/github-builder/.github/workflows/build.yml@v1
456+
permissions:
457+
contents: read # to fetch the repository content
458+
id-token: write # for signing attestations, cache entries with GitHub OIDC and log in to Google Artifact Registry
459+
with:
460+
output: image
461+
push: ${{ github.event_name != 'pull_request' }}
462+
meta-images: |
463+
us-docker.pkg.dev/my-project/sandbox/test-github-builder
464+
registry-identities: |
465+
- type: gcp-wif
466+
registry: us-docker.pkg.dev
467+
workload_identity_provider: projects/123456789/locations/global/workloadIdentityPools/github/providers/provider
468+
service_account: builder@my-project.iam.gserviceaccount.com
469+
project_id: my-project
470+
```
471+
472+
The `registry` value is required for GCP WIF. Use the Artifact Registry host
473+
that `docker/login-action` should log in to, such as `us-docker.pkg.dev`, not
474+
the full repository path. The workflow requests an access token from
475+
`google-github-actions/auth` and passes it directly to `docker/login-action`
476+
with the `oauth2accesstoken` username inside the same job.
477+
442478
### Runner mapping
443479

444480
The `runner` input accepts either a single GitHub-hosted Linux runner label or a

0 commit comments

Comments
 (0)