Skip to content

Commit 52bdf65

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 52bdf65

4 files changed

Lines changed: 188 additions & 4 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: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,24 @@ 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:
25-
RUNTIME_MODULE: "@docker/github-builder-runtime@0.92.0"
40+
RUNTIME_MODULE: "@docker/github-builder-runtime@0.93.0"
2641
RUNTIME_INSTALL_ARGS: |
2742
--loglevel=error
2843
--no-save
@@ -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: 54 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:
@@ -435,10 +439,57 @@ jobs:
435439
registry: 123456789100.dkr.ecr.us-east-1.amazonaws.com
436440
```
437441

442+
| Name | Type | Required | Description |
443+
|------------------|--------|----------|---------------------------------------------------------------------------------------------------------------------------------|
444+
| `type` | String | Yes | Registry identity provider type. Must be `aws-ecr`. |
445+
| `aws-region` | String | Yes | AWS region passed to `aws-actions/configure-aws-credentials` when assuming the role. Use `us-east-1` for ECR Public. |
446+
| `role-to-assume` | String | Yes | IAM role ARN assumed through GitHub OIDC. |
447+
| `registry` | String | Yes | Registry server passed to `docker/login-action`, such as `public.ecr.aws` for public ECR or a private ECR host for private ECR. |
448+
438449
The `registry` value is required for AWS ECR. Use the registry server that
439450
`docker/login-action` should log in to, such as `public.ecr.aws` for public ECR
440451
or `123456789100.dkr.ecr.us-east-1.amazonaws.com` for private ECR.
441452

453+
#### Google Artifact Registry
454+
455+
Google Artifact Registry authentication is configured with `type: gcp-wif`.
456+
Callers must grant `id-token: write` so `google-github-actions/auth` can
457+
exchange the GitHub OIDC token through GCP Workload Identity Federation:
458+
459+
```yaml
460+
jobs:
461+
build:
462+
uses: docker/github-builder/.github/workflows/build.yml@v1
463+
permissions:
464+
contents: read # to fetch the repository content
465+
id-token: write # for signing attestations, cache entries with GitHub OIDC and log in to Google Artifact Registry
466+
with:
467+
output: image
468+
push: ${{ github.event_name != 'pull_request' }}
469+
meta-images: |
470+
us-docker.pkg.dev/my-project/sandbox/test-github-builder
471+
registry-identities: |
472+
- type: gcp-wif
473+
registry: us-docker.pkg.dev
474+
workload_identity_provider: projects/123456789/locations/global/workloadIdentityPools/github/providers/provider
475+
service_account: builder@my-project.iam.gserviceaccount.com
476+
project_id: my-project
477+
```
478+
479+
| Name | Type | Required | Description |
480+
|------------------------------|--------|----------|------------------------------------------------------------------------------------------------------------------------------------------------|
481+
| `type` | String | Yes | Registry identity provider type. Must be `gcp-wif`. |
482+
| `registry` | String | Yes | Google Artifact Registry host passed to `docker/login-action`, such as `us-docker.pkg.dev`. Do not use the full repository path. |
483+
| `workload_identity_provider` | String | Yes | Workload Identity Provider resource name passed to `google-github-actions/auth`. |
484+
| `service_account` | String | Yes | Service account email passed to `google-github-actions/auth` for Workload Identity Federation. |
485+
| `project_id` | String | Yes | Google Cloud project ID passed to `google-github-actions/auth`. |
486+
487+
The `registry` value is required for GCP WIF. Use the Artifact Registry host
488+
that `docker/login-action` should log in to, such as `us-docker.pkg.dev`, not
489+
the full repository path. The workflow requests an access token from
490+
`google-github-actions/auth` and passes it directly to `docker/login-action`
491+
with the `oauth2accesstoken` username inside the same job.
492+
442493
### Runner mapping
443494

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

0 commit comments

Comments
 (0)