Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 46 additions & 2 deletions .github/workflows/bake.yml
Original file line number Diff line number Diff line change
Expand Up @@ -998,7 +998,29 @@ jobs:
if: ${{ needs.registry-identities.outputs.aws-ecr-enabled == 'true' }}
uses: docker/login-action@af1e73f918a031802d376d3c8bbc3fe56130a9b0 # v4.4.0
with:
registry-auth: ${{ needs.registry-identities.outputs.aws-ecr-registry-auth }}
registry-auth: |
- registry: ${{ needs.registry-identities.outputs.aws-ecr-registry }}
-
name: Authenticate to Google Cloud
id: gcp-wif-auth
if: ${{ needs.registry-identities.outputs.gcp-wif-enabled == 'true' }}
uses: google-github-actions/auth@7c6bc770dae815cd3e89ee6cdf493a5fab2cc093 # v3.0.0
with:
token_format: access_token
workload_identity_provider: ${{ needs.registry-identities.outputs.gcp-wif-workload-identity-provider }}
service_account: ${{ needs.registry-identities.outputs.gcp-wif-service-account }}
project_id: ${{ needs.registry-identities.outputs.gcp-wif-project-id }}
create_credentials_file: false
export_environment_variables: false
-
name: Login to Google Artifact Registry
if: ${{ needs.registry-identities.outputs.gcp-wif-enabled == 'true' }}
uses: docker/login-action@af1e73f918a031802d376d3c8bbc3fe56130a9b0 # v4.4.0
with:
registry-auth: |
- registry: ${{ needs.registry-identities.outputs.gcp-wif-registry }}
username: oauth2accesstoken
password: ${{ steps.gcp-wif-auth.outputs.access_token }}
-
name: Login to registry
if: ${{ inputs.push && inputs.output == 'image' && env.REGISTRY_AUTHS_PRESENT == 'true' }}
Expand Down Expand Up @@ -1218,7 +1240,29 @@ jobs:
if: ${{ inputs.push && inputs.output == 'image' && needs.registry-identities.outputs.aws-ecr-enabled == 'true' }}
uses: docker/login-action@af1e73f918a031802d376d3c8bbc3fe56130a9b0 # v4.4.0
with:
registry-auth: ${{ needs.registry-identities.outputs.aws-ecr-registry-auth }}
registry-auth: |
- registry: ${{ needs.registry-identities.outputs.aws-ecr-registry }}
-
name: Authenticate to Google Cloud
id: gcp-wif-auth
if: ${{ inputs.push && inputs.output == 'image' && needs.registry-identities.outputs.gcp-wif-enabled == 'true' }}
uses: google-github-actions/auth@7c6bc770dae815cd3e89ee6cdf493a5fab2cc093 # v3.0.0
with:
token_format: access_token
workload_identity_provider: ${{ needs.registry-identities.outputs.gcp-wif-workload-identity-provider }}
service_account: ${{ needs.registry-identities.outputs.gcp-wif-service-account }}
project_id: ${{ needs.registry-identities.outputs.gcp-wif-project-id }}
create_credentials_file: false
export_environment_variables: false
-
name: Login to Google Artifact Registry
if: ${{ inputs.push && inputs.output == 'image' && needs.registry-identities.outputs.gcp-wif-enabled == 'true' }}
uses: docker/login-action@af1e73f918a031802d376d3c8bbc3fe56130a9b0 # v4.4.0
with:
registry-auth: |
- registry: ${{ needs.registry-identities.outputs.gcp-wif-registry }}
username: oauth2accesstoken
password: ${{ steps.gcp-wif-auth.outputs.access_token }}
-
name: Login to registry
if: ${{ inputs.push && inputs.output == 'image' && env.REGISTRY_AUTHS_PRESENT == 'true' }}
Expand Down
48 changes: 46 additions & 2 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -864,7 +864,29 @@ jobs:
if: ${{ needs.registry-identities.outputs.aws-ecr-enabled == 'true' }}
uses: docker/login-action@af1e73f918a031802d376d3c8bbc3fe56130a9b0 # v4.4.0
with:
registry-auth: ${{ needs.registry-identities.outputs.aws-ecr-registry-auth }}
registry-auth: |
- registry: ${{ needs.registry-identities.outputs.aws-ecr-registry }}
-
name: Authenticate to Google Cloud
id: gcp-wif-auth
if: ${{ needs.registry-identities.outputs.gcp-wif-enabled == 'true' }}
uses: google-github-actions/auth@7c6bc770dae815cd3e89ee6cdf493a5fab2cc093 # v3.0.0
with:
token_format: access_token
workload_identity_provider: ${{ needs.registry-identities.outputs.gcp-wif-workload-identity-provider }}
service_account: ${{ needs.registry-identities.outputs.gcp-wif-service-account }}
project_id: ${{ needs.registry-identities.outputs.gcp-wif-project-id }}
create_credentials_file: false
export_environment_variables: false
-
name: Login to Google Artifact Registry
if: ${{ needs.registry-identities.outputs.gcp-wif-enabled == 'true' }}
uses: docker/login-action@af1e73f918a031802d376d3c8bbc3fe56130a9b0 # v4.4.0
with:
registry-auth: |
- registry: ${{ needs.registry-identities.outputs.gcp-wif-registry }}
username: oauth2accesstoken
password: ${{ steps.gcp-wif-auth.outputs.access_token }}
-
name: Login to registry
if: ${{ inputs.push && inputs.output == 'image' && env.REGISTRY_AUTHS_PRESENT == 'true' }}
Expand Down Expand Up @@ -1080,7 +1102,29 @@ jobs:
if: ${{ inputs.push && inputs.output == 'image' && needs.registry-identities.outputs.aws-ecr-enabled == 'true' }}
uses: docker/login-action@af1e73f918a031802d376d3c8bbc3fe56130a9b0 # v4.4.0
with:
registry-auth: ${{ needs.registry-identities.outputs.aws-ecr-registry-auth }}
registry-auth: |
- registry: ${{ needs.registry-identities.outputs.aws-ecr-registry }}
-
name: Authenticate to Google Cloud
id: gcp-wif-auth
if: ${{ inputs.push && inputs.output == 'image' && needs.registry-identities.outputs.gcp-wif-enabled == 'true' }}
uses: google-github-actions/auth@7c6bc770dae815cd3e89ee6cdf493a5fab2cc093 # v3.0.0
with:
token_format: access_token
workload_identity_provider: ${{ needs.registry-identities.outputs.gcp-wif-workload-identity-provider }}
service_account: ${{ needs.registry-identities.outputs.gcp-wif-service-account }}
project_id: ${{ needs.registry-identities.outputs.gcp-wif-project-id }}
create_credentials_file: false
export_environment_variables: false
-
name: Login to Google Artifact Registry
if: ${{ inputs.push && inputs.output == 'image' && needs.registry-identities.outputs.gcp-wif-enabled == 'true' }}
uses: docker/login-action@af1e73f918a031802d376d3c8bbc3fe56130a9b0 # v4.4.0
with:
registry-auth: |
- registry: ${{ needs.registry-identities.outputs.gcp-wif-registry }}
username: oauth2accesstoken
password: ${{ steps.gcp-wif-auth.outputs.access_token }}
-
name: Login to registry
if: ${{ inputs.push && inputs.output == 'image' && env.REGISTRY_AUTHS_PRESENT == 'true' }}
Expand Down
80 changes: 62 additions & 18 deletions .github/workflows/setup-registry-identities.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: registry-identities
name: setup-registry-identities

on:
workflow_call:
Expand All @@ -11,18 +11,33 @@ on:
aws-ecr-enabled:
description: "Whether an AWS ECR registry identity was configured"
value: ${{ jobs.setup-registry-identities.outputs.aws-ecr-enabled }}
aws-ecr-registry:
description: "AWS ECR registry host to authenticate against"
value: ${{ jobs.setup-registry-identities.outputs.aws-ecr-registry }}
aws-ecr-role-to-assume:
description: "AWS IAM role ARN to assume for ECR authentication"
value: ${{ jobs.setup-registry-identities.outputs.aws-ecr-role-to-assume }}
aws-ecr-region:
description: "AWS region to use for ECR authentication"
value: ${{ jobs.setup-registry-identities.outputs.aws-ecr-region }}
aws-ecr-registry-auth:
description: "Registry auth YAML for Docker login"
value: ${{ jobs.setup-registry-identities.outputs.aws-ecr-registry-auth }}
gcp-wif-enabled:
description: "Whether a GCP Workload Identity Federation registry identity was configured"
value: ${{ jobs.setup-registry-identities.outputs.gcp-wif-enabled }}
gcp-wif-registry:
description: "Google Artifact Registry host to authenticate against"
value: ${{ jobs.setup-registry-identities.outputs.gcp-wif-registry }}
gcp-wif-workload-identity-provider:
description: "GCP Workload Identity Provider resource name"
value: ${{ jobs.setup-registry-identities.outputs.gcp-wif-workload-identity-provider }}
gcp-wif-service-account:
description: "GCP service account to impersonate"
value: ${{ jobs.setup-registry-identities.outputs.gcp-wif-service-account }}
gcp-wif-project-id:
description: "GCP project ID"
value: ${{ jobs.setup-registry-identities.outputs.gcp-wif-project-id }}

env:
RUNTIME_MODULE: "@docker/github-builder-runtime@0.92.0"
RUNTIME_MODULE: "@docker/github-builder-runtime@0.93.0"
RUNTIME_INSTALL_ARGS: |
--loglevel=error
--no-save
Expand All @@ -39,9 +54,14 @@ jobs:
runs-on: ubuntu-24.04
outputs:
aws-ecr-enabled: ${{ steps.validate.outputs.aws-ecr-enabled }}
aws-ecr-registry: ${{ steps.validate.outputs.aws-ecr-registry }}
aws-ecr-role-to-assume: ${{ steps.validate.outputs.aws-ecr-role-to-assume }}
aws-ecr-region: ${{ steps.validate.outputs.aws-ecr-region }}
aws-ecr-registry-auth: ${{ steps.validate.outputs.aws-ecr-registry-auth }}
gcp-wif-enabled: ${{ steps.validate.outputs.gcp-wif-enabled }}
gcp-wif-registry: ${{ steps.validate.outputs.gcp-wif-registry }}
gcp-wif-workload-identity-provider: ${{ steps.validate.outputs.gcp-wif-workload-identity-provider }}
gcp-wif-service-account: ${{ steps.validate.outputs.gcp-wif-service-account }}
gcp-wif-project-id: ${{ steps.validate.outputs.gcp-wif-project-id }}
steps:
-
name: Install dependencies
Expand Down Expand Up @@ -83,9 +103,14 @@ jobs:
script: |
const setEmptyOutputs = () => {
core.setOutput('aws-ecr-enabled', 'false');
core.setOutput('aws-ecr-registry', '');
core.setOutput('aws-ecr-role-to-assume', '');
core.setOutput('aws-ecr-region', '');
core.setOutput('aws-ecr-registry-auth', '');
core.setOutput('gcp-wif-enabled', 'false');
core.setOutput('gcp-wif-registry', '');
core.setOutput('gcp-wif-workload-identity-provider', '');
core.setOutput('gcp-wif-service-account', '');
core.setOutput('gcp-wif-project-id', '');
};

const registryIdentities = core.getInput('registry-identities', {trimWhitespace: false});
Expand Down Expand Up @@ -135,13 +160,14 @@ jobs:
}

let awsEcr;
let gcpWif;
entries.forEach((entry, index) => {
const path = `registry-identities[${index}]`;
ensureObject(entry, path);
const type = requireString(entry, 'type', path);
switch (type) {
case 'aws-ecr': {
const allowedKeys = new Set(['type', 'aws-region', 'role-to-assume', 'registry']);
const allowedKeys = new Set(['type', 'registry', 'role-to-assume', 'region']);
for (const key of Object.keys(entry)) {
if (!allowedKeys.has(key)) {
fail(`${path}.${key} is not supported for aws-ecr`);
Expand All @@ -150,15 +176,28 @@ jobs:
if (awsEcr) {
fail('only one aws-ecr registry identity is supported');
}
const awsRegion = requireString(entry, 'aws-region', path);
const roleToAssume = requireString(entry, 'role-to-assume', path);
const registry = requireString(entry, 'registry', path);
awsEcr = {
awsRegion,
roleToAssume,
registryAuth: yaml.dump([{
registry
}], {lineWidth: -1})
registry: requireString(entry, 'registry', path),
roleToAssume: requireString(entry, 'role-to-assume', path),
region: requireString(entry, 'region', path)
};
break;
}
case 'gcp-wif': {
const allowedKeys = new Set(['type', 'registry', 'workload_identity_provider', 'service_account', 'project_id']);
for (const key of Object.keys(entry)) {
if (!allowedKeys.has(key)) {
fail(`${path}.${key} is not supported for gcp-wif`);
}
}
if (gcpWif) {
fail('only one gcp-wif registry identity is supported');
}
gcpWif = {
registry: requireString(entry, 'registry', path),
workloadIdentityProvider: requireString(entry, 'workload_identity_provider', path),
serviceAccount: requireString(entry, 'service_account', path),
projectId: requireString(entry, 'project_id', path)
};
break;
}
Expand All @@ -168,6 +207,11 @@ jobs:
});

core.setOutput('aws-ecr-enabled', awsEcr ? 'true' : 'false');
core.setOutput('aws-ecr-registry', awsEcr?.registry || '');
core.setOutput('aws-ecr-role-to-assume', awsEcr?.roleToAssume || '');
core.setOutput('aws-ecr-region', awsEcr?.awsRegion || '');
core.setOutput('aws-ecr-registry-auth', awsEcr?.registryAuth || '');
core.setOutput('aws-ecr-region', awsEcr?.region || '');
core.setOutput('gcp-wif-enabled', gcpWif ? 'true' : 'false');
core.setOutput('gcp-wif-registry', gcpWif?.registry || '');
core.setOutput('gcp-wif-workload-identity-provider', gcpWif?.workloadIdentityProvider || '');
core.setOutput('gcp-wif-service-account', gcpWif?.serviceAccount || '');
core.setOutput('gcp-wif-project-id', gcpWif?.projectId || '');
61 changes: 56 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ ___
* [Notes](#notes)
* [Signed GitHub Actions cache](#signed-github-actions-cache)
* [Registry identities](#registry-identities)
* [AWS ECR](#aws-ecr)
* [Google Artifact Registry](#google-artifact-registry)
* [Runner mapping](#runner-mapping)
* [Metadata templates](#metadata-templates)

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

Amazon ECR private registry authentication is configured with `type: aws-ecr`.
Callers must grant `id-token: write` so the AWS credential step can assume the
role through GitHub OIDC:
#### AWS ECR

Amazon ECR registry authentication is configured with `type: aws-ecr`. Callers
must grant `id-token: write` so the AWS credential step can assume the role
through GitHub OIDC:

```yaml
jobs:
Expand All @@ -430,15 +434,62 @@ jobs:
123456789100.dkr.ecr.us-east-1.amazonaws.com/sandbox/test-github-builder
registry-identities: |
- type: aws-ecr
aws-region: us-east-1
role-to-assume: arn:aws:iam::123456789100:role/my-github-actions-role
registry: 123456789100.dkr.ecr.us-east-1.amazonaws.com
role-to-assume: arn:aws:iam::123456789100:role/my-github-actions-role
region: us-east-1
```

| Name | Type | Required | Description |
|------------------|--------|----------|---------------------------------------------------------------------------------------------------------------------------------|
| `type` | String | Yes | Registry identity provider type. Must be `aws-ecr`. |
| `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. |
| `role-to-assume` | String | Yes | IAM role ARN assumed through GitHub OIDC. |
| `region` | String | Yes | AWS region passed to `aws-actions/configure-aws-credentials` when assuming the role. Use `us-east-1` for ECR Public. |

The `registry` value is required for AWS ECR. Use the registry server that
`docker/login-action` should log in to, such as `public.ecr.aws` for public ECR
or `123456789100.dkr.ecr.us-east-1.amazonaws.com` for private ECR.

#### Google Artifact Registry

Google Artifact Registry authentication is configured with `type: gcp-wif`.
Callers must grant `id-token: write` so `google-github-actions/auth` can
exchange the GitHub OIDC token through GCP Workload Identity Federation:

```yaml
jobs:
build:
uses: docker/github-builder/.github/workflows/build.yml@v1
permissions:
contents: read # to fetch the repository content
id-token: write # for signing attestations, cache entries with GitHub OIDC and log in to Google Artifact Registry
with:
output: image
push: ${{ github.event_name != 'pull_request' }}
meta-images: |
us-docker.pkg.dev/my-project/sandbox/test-github-builder
registry-identities: |
- type: gcp-wif
registry: us-docker.pkg.dev
workload_identity_provider: projects/123456789/locations/global/workloadIdentityPools/github/providers/provider
service_account: builder@my-project.iam.gserviceaccount.com
project_id: my-project
```

| Name | Type | Required | Description |
|------------------------------|--------|----------|------------------------------------------------------------------------------------------------------------------------------------------------|
| `type` | String | Yes | Registry identity provider type. Must be `gcp-wif`. |
| `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. |
| `workload_identity_provider` | String | Yes | Workload Identity Provider resource name passed to `google-github-actions/auth`. |
| `service_account` | String | Yes | Service account email passed to `google-github-actions/auth` for Workload Identity Federation. |
| `project_id` | String | Yes | Google Cloud project ID passed to `google-github-actions/auth`. |

The `registry` value is required for GCP WIF. Use the Artifact Registry host
that `docker/login-action` should log in to, such as `us-docker.pkg.dev`, not
the full repository path. The workflow requests an access token from
`google-github-actions/auth` and passes it directly to `docker/login-action`
with the `oauth2accesstoken` username inside the same job.

### Runner mapping

The `runner` input accepts either a single GitHub-hosted Linux runner label or a
Expand Down
Loading