Skip to content
Merged
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
57 changes: 57 additions & 0 deletions .github/workflows/.test-bake.yml
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,63 @@ jobs:
const builderOutputs = JSON.parse(core.getInput('builder-outputs'));
core.info(JSON.stringify(builderOutputs, null, 2));

bake-dockerhub-oidc:
uses: ./.github/workflows/bake.yml
if: ${{ github.event_name != 'pull_request' }}
permissions:
contents: read
id-token: write
with:
job-name-prefix: bake-dockerhub-oidc
context: test
output: image
push: true
sbom: true
set: |
*.args.VERSION={{meta.version}}
target: hello
registry-identities: |
- type: dockerhub
registry: docker.io
username: ${{ vars.DOCKERHUB_OIDC_USERNAME }}
connection_id: ${{ vars.DOCKERHUB_OIDC_CONNECTIONID }}
meta-images: |
docker.io/dockereng/github-builder-test
meta-tags: |
type=raw,value=bake-ghbuilder-oidc-${{ github.run_id }}

bake-dockerhub-oidc-verify:
uses: ./.github/workflows/verify.yml
if: ${{ github.event_name != 'pull_request' }}
needs:
- bake-dockerhub-oidc
permissions:
contents: read
id-token: write
with:
builder-outputs: ${{ toJSON(needs.bake-dockerhub-oidc.outputs) }}
registry-identities: |
- type: dockerhub
registry: docker.io
username: ${{ vars.DOCKERHUB_OIDC_USERNAME }}
connection_id: ${{ vars.DOCKERHUB_OIDC_CONNECTIONID }}

bake-dockerhub-oidc-outputs:
runs-on: ubuntu-24.04
if: ${{ github.event_name != 'pull_request' }}
needs:
- bake-dockerhub-oidc
steps:
-
name: Builder outputs
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
env:
INPUT_BUILDER-OUTPUTS: ${{ toJSON(needs.bake-dockerhub-oidc.outputs) }}
with:
script: |
const builderOutputs = JSON.parse(core.getInput('builder-outputs'));
core.info(JSON.stringify(builderOutputs, null, 2));

bake-dockerhub-scan:
runs-on: ubuntu-24.04
if: ${{ github.event_name != 'pull_request' }}
Expand Down
56 changes: 56 additions & 0 deletions .github/workflows/.test-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,62 @@ jobs:
const builderOutputs = JSON.parse(core.getInput('builder-outputs'));
core.info(JSON.stringify(builderOutputs, null, 2));

build-dockerhub-oidc:
uses: ./.github/workflows/build.yml
if: ${{ github.event_name != 'pull_request' }}
permissions:
contents: read
id-token: write
with:
job-name-prefix: build-dockerhub-oidc
build-args: |
VERSION={{meta.version}}
file: test/hello.Dockerfile
output: image
push: true
sbom: true
registry-identities: |
- type: dockerhub
registry: docker.io
username: ${{ vars.DOCKERHUB_OIDC_USERNAME }}
connection_id: ${{ vars.DOCKERHUB_OIDC_CONNECTIONID }}
meta-images: |
docker.io/dockereng/github-builder-test
meta-tags: |
type=raw,value=build-ghbuilder-oidc-${{ github.run_id }}

build-dockerhub-oidc-verify:
uses: ./.github/workflows/verify.yml
if: ${{ github.event_name != 'pull_request' }}
needs:
- build-dockerhub-oidc
permissions:
contents: read
id-token: write
with:
builder-outputs: ${{ toJSON(needs.build-dockerhub-oidc.outputs) }}
registry-identities: |
- type: dockerhub
registry: docker.io
username: ${{ vars.DOCKERHUB_OIDC_USERNAME }}
connection_id: ${{ vars.DOCKERHUB_OIDC_CONNECTIONID }}

build-dockerhub-oidc-outputs:
runs-on: ubuntu-24.04
if: ${{ github.event_name != 'pull_request' }}
needs:
- build-dockerhub-oidc
steps:
-
name: Builder outputs
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
env:
INPUT_BUILDER-OUTPUTS: ${{ toJSON(needs.build-dockerhub-oidc.outputs) }}
with:
script: |
const builderOutputs = JSON.parse(core.getInput('builder-outputs'));
core.info(JSON.stringify(builderOutputs, null, 2));

build-dockerhub-scan:
runs-on: ubuntu-24.04
if: ${{ github.event_name != 'pull_request' }}
Expand Down
20 changes: 20 additions & 0 deletions .github/workflows/bake.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1021,6 +1021,16 @@ jobs:
- registry: ${{ needs.registry-identities.outputs.gcp-wif-registry }}
username: oauth2accesstoken
password: ${{ steps.gcp-wif-auth.outputs.access_token }}
-
name: Login to Docker Hub with OIDC
if: ${{ needs.registry-identities.outputs.dockerhub-oidc-enabled == 'true' }}
uses: docker/login-action@abd2ef45e78c5afb21d64d4ca52ee8550d9572c7 # v4.5.1
env:
DOCKERHUB_OIDC_CONNECTIONID: ${{ needs.registry-identities.outputs.dockerhub-oidc-connection-id }}
with:
registry-auth: |
- registry: ${{ needs.registry-identities.outputs.dockerhub-oidc-registry }}
username: ${{ needs.registry-identities.outputs.dockerhub-oidc-username }}
-
name: Login to registry
if: ${{ inputs.push && inputs.output == 'image' && env.REGISTRY_AUTHS_PRESENT == 'true' }}
Expand Down Expand Up @@ -1263,6 +1273,16 @@ jobs:
- registry: ${{ needs.registry-identities.outputs.gcp-wif-registry }}
username: oauth2accesstoken
password: ${{ steps.gcp-wif-auth.outputs.access_token }}
-
name: Login to Docker Hub with OIDC
if: ${{ inputs.push && inputs.output == 'image' && needs.registry-identities.outputs.dockerhub-oidc-enabled == 'true' }}
uses: docker/login-action@abd2ef45e78c5afb21d64d4ca52ee8550d9572c7 # v4.5.1
env:
DOCKERHUB_OIDC_CONNECTIONID: ${{ needs.registry-identities.outputs.dockerhub-oidc-connection-id }}
with:
registry-auth: |
- registry: ${{ needs.registry-identities.outputs.dockerhub-oidc-registry }}
username: ${{ needs.registry-identities.outputs.dockerhub-oidc-username }}
-
name: Login to registry
if: ${{ inputs.push && inputs.output == 'image' && env.REGISTRY_AUTHS_PRESENT == 'true' }}
Expand Down
20 changes: 20 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -887,6 +887,16 @@ jobs:
- registry: ${{ needs.registry-identities.outputs.gcp-wif-registry }}
username: oauth2accesstoken
password: ${{ steps.gcp-wif-auth.outputs.access_token }}
-
name: Login to Docker Hub with OIDC
if: ${{ needs.registry-identities.outputs.dockerhub-oidc-enabled == 'true' }}
uses: docker/login-action@abd2ef45e78c5afb21d64d4ca52ee8550d9572c7 # v4.5.1
env:
DOCKERHUB_OIDC_CONNECTIONID: ${{ needs.registry-identities.outputs.dockerhub-oidc-connection-id }}
with:
registry-auth: |
- registry: ${{ needs.registry-identities.outputs.dockerhub-oidc-registry }}
username: ${{ needs.registry-identities.outputs.dockerhub-oidc-username }}
Comment on lines +890 to +899

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My AI frend flagged this:

The pinned docker/login-action requests a 300-second Docker Hub OIDC token unless DOCKERHUB_OIDC_EXPIREIN is set.

This login runs before the full build-and-push step. Docker stores that token as the registry password, so a build lasting more than five minutes can fail when BuildKit requests authorization during the push.

Set DOCKERHUB_OIDC_EXPIREIN: 3600 in the Docker Hub login steps, including the equivalent bake.yml block, or otherwise refresh credentials before registry operations.
The verify and finalize jobs should use the longer lifetime too if they can process many images.

@crazy-max crazy-max Jul 24, 2026

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

He's wrong, the expire-in doesn't apply to the auth to the registry but the mint token used before authenticating.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, I see!

-
name: Login to registry
if: ${{ inputs.push && inputs.output == 'image' && env.REGISTRY_AUTHS_PRESENT == 'true' }}
Expand Down Expand Up @@ -1125,6 +1135,16 @@ jobs:
- registry: ${{ needs.registry-identities.outputs.gcp-wif-registry }}
username: oauth2accesstoken
password: ${{ steps.gcp-wif-auth.outputs.access_token }}
-
name: Login to Docker Hub with OIDC
if: ${{ inputs.push && inputs.output == 'image' && needs.registry-identities.outputs.dockerhub-oidc-enabled == 'true' }}
uses: docker/login-action@abd2ef45e78c5afb21d64d4ca52ee8550d9572c7 # v4.5.1
env:
DOCKERHUB_OIDC_CONNECTIONID: ${{ needs.registry-identities.outputs.dockerhub-oidc-connection-id }}
with:
registry-auth: |
- registry: ${{ needs.registry-identities.outputs.dockerhub-oidc-registry }}
username: ${{ needs.registry-identities.outputs.dockerhub-oidc-username }}
-
name: Login to registry
if: ${{ inputs.push && inputs.output == 'image' && env.REGISTRY_AUTHS_PRESENT == 'true' }}
Expand Down
48 changes: 48 additions & 0 deletions .github/workflows/setup-registry-identities.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,18 @@ on:
gcp-wif-project-id:
description: "GCP project ID"
value: ${{ jobs.setup-registry-identities.outputs.gcp-wif-project-id }}
dockerhub-oidc-enabled:
description: "Whether a Docker Hub OIDC registry identity was configured"
value: ${{ jobs.setup-registry-identities.outputs.dockerhub-oidc-enabled }}
dockerhub-oidc-registry:
description: "Docker Hub registry hostname"
value: ${{ jobs.setup-registry-identities.outputs.dockerhub-oidc-registry }}
dockerhub-oidc-username:
description: "Docker Hub username or organization to authenticate as"
value: ${{ jobs.setup-registry-identities.outputs.dockerhub-oidc-username }}
dockerhub-oidc-connection-id:
description: "Docker Hub OIDC connection ID"
value: ${{ jobs.setup-registry-identities.outputs.dockerhub-oidc-connection-id }}

env:
RUNTIME_MODULE: "@docker/github-builder-runtime@0.94.0"
Expand Down Expand Up @@ -62,6 +74,10 @@ jobs:
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 }}
dockerhub-oidc-enabled: ${{ steps.validate.outputs.dockerhub-oidc-enabled }}
dockerhub-oidc-registry: ${{ steps.validate.outputs.dockerhub-oidc-registry }}
dockerhub-oidc-username: ${{ steps.validate.outputs.dockerhub-oidc-username }}
dockerhub-oidc-connection-id: ${{ steps.validate.outputs.dockerhub-oidc-connection-id }}
steps:
-
name: Install dependencies
Expand Down Expand Up @@ -111,6 +127,10 @@ jobs:
core.setOutput('gcp-wif-workload-identity-provider', '');
core.setOutput('gcp-wif-service-account', '');
core.setOutput('gcp-wif-project-id', '');
core.setOutput('dockerhub-oidc-enabled', 'false');
core.setOutput('dockerhub-oidc-registry', '');
core.setOutput('dockerhub-oidc-username', '');
core.setOutput('dockerhub-oidc-connection-id', '');
};

const registryIdentities = core.getInput('registry-identities', {trimWhitespace: false});
Expand Down Expand Up @@ -142,6 +162,12 @@ jobs:
}
return value.trim();
};
const optionalString = (entry, key, path, defaultValue) => {
if (!Object.prototype.hasOwnProperty.call(entry, key)) {
return defaultValue;
}
return requireString(entry, key, path);
};
let parsed;
try {
parsed = yaml.load(registryIdentities);
Expand All @@ -161,6 +187,7 @@ jobs:

let awsEcr;
let gcpWif;
let dockerhubOidc;
entries.forEach((entry, index) => {
const path = `registry-identities[${index}]`;
ensureObject(entry, path);
Expand Down Expand Up @@ -201,6 +228,23 @@ jobs:
};
break;
}
case 'dockerhub': {
const allowedKeys = new Set(['type', 'registry', 'username', 'connection_id']);
for (const key of Object.keys(entry)) {
if (!allowedKeys.has(key)) {
fail(`${path}.${key} is not supported for dockerhub`);
}
}
if (dockerhubOidc) {
fail('only one dockerhub registry identity is supported');
}
dockerhubOidc = {
registry: optionalString(entry, 'registry', path, 'docker.io'),
username: requireString(entry, 'username', path),
connectionID: requireString(entry, 'connection_id', path)
};
break;
}
default:
fail(`${path}.type has unsupported provider ${type}`);
}
Expand All @@ -215,3 +259,7 @@ jobs:
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 || '');
core.setOutput('dockerhub-oidc-enabled', dockerhubOidc ? 'true' : 'false');
core.setOutput('dockerhub-oidc-registry', dockerhubOidc?.registry || '');
core.setOutput('dockerhub-oidc-username', dockerhubOidc?.username || '');
core.setOutput('dockerhub-oidc-connection-id', dockerhubOidc?.connectionID || '');
60 changes: 59 additions & 1 deletion .github/workflows/verify.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ on:
type: string
description: "JSON build outputs from Docker GitHub Builder reusable workflows"
required: true
registry-identities:
type: string
description: "Keyless registry identity configuration as YAML objects"
required: false
secrets:
registry-auths:
description: "Registry authentication details as YAML objects"
Expand All @@ -26,8 +30,17 @@ env:
NPM_CONFIG_FETCH_RETRIES: "5"

jobs:
registry-identities:
uses: ./.github/workflows/setup-registry-identities.yml
with:
registry-identities: ${{ inputs.registry-identities }}

verify:
runs-on: ubuntu-24.04
needs:
- registry-identities
env:
REGISTRY_AUTHS_PRESENT: ${{ secrets.registry-auths != '' }}
steps:
-
name: Extract builder outputs
Expand Down Expand Up @@ -103,9 +116,54 @@ jobs:

const cosign = new Cosign();
await cosign.printVersion();
-
name: Configure AWS credentials
if: ${{ steps.vars.outputs.signed == 'true' && steps.vars.outputs.output-type == 'image' && needs.registry-identities.outputs.aws-ecr-enabled == 'true' }}
uses: aws-actions/configure-aws-credentials@517a711dbcd0e402f90c77e7e2f81e849156e31d # v6.2.2
with:
role-to-assume: ${{ needs.registry-identities.outputs.aws-ecr-role-to-assume }}
aws-region: ${{ needs.registry-identities.outputs.aws-ecr-region }}
-
name: Login to Amazon ECR
if: ${{ steps.vars.outputs.signed == 'true' && steps.vars.outputs.output-type == 'image' && needs.registry-identities.outputs.aws-ecr-enabled == 'true' }}
uses: docker/login-action@abd2ef45e78c5afb21d64d4ca52ee8550d9572c7 # v4.5.1
with:
registry-auth: |
- registry: ${{ needs.registry-identities.outputs.aws-ecr-registry }}
-
name: Authenticate to Google Cloud
id: gcp-wif-auth
if: ${{ steps.vars.outputs.signed == 'true' && steps.vars.outputs.output-type == '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: ${{ steps.vars.outputs.signed == 'true' && steps.vars.outputs.output-type == 'image' && needs.registry-identities.outputs.gcp-wif-enabled == 'true' }}
uses: docker/login-action@abd2ef45e78c5afb21d64d4ca52ee8550d9572c7 # v4.5.1
with:
registry-auth: |
- registry: ${{ needs.registry-identities.outputs.gcp-wif-registry }}
username: oauth2accesstoken
password: ${{ steps.gcp-wif-auth.outputs.access_token }}
-
name: Login to Docker Hub with OIDC
if: ${{ steps.vars.outputs.signed == 'true' && steps.vars.outputs.output-type == 'image' && needs.registry-identities.outputs.dockerhub-oidc-enabled == 'true' }}
uses: docker/login-action@abd2ef45e78c5afb21d64d4ca52ee8550d9572c7 # v4.5.1
env:
DOCKERHUB_OIDC_CONNECTIONID: ${{ needs.registry-identities.outputs.dockerhub-oidc-connection-id }}
with:
registry-auth: |
- registry: ${{ needs.registry-identities.outputs.dockerhub-oidc-registry }}
username: ${{ needs.registry-identities.outputs.dockerhub-oidc-username }}
-
name: Login to registry
if: ${{ steps.vars.outputs.signed == 'true' && steps.vars.outputs.output-type == 'image' }}
if: ${{ steps.vars.outputs.signed == 'true' && steps.vars.outputs.output-type == 'image' && env.REGISTRY_AUTHS_PRESENT == 'true' }}
uses: docker/login-action@abd2ef45e78c5afb21d64d4ca52ee8550d9572c7 # v4.5.1
with:
registry-auth: ${{ secrets.registry-auths }}
Expand Down
Loading
Loading