{"id":4704,"date":"2026-07-31T16:56:21","date_gmt":"2026-07-31T16:56:21","guid":{"rendered":"https:\/\/rssfeedtelegrambot.bnaya.co.il\/index.php\/2026\/07\/31\/docker-oidc-connections-for-github-actions-available-for-docker-orgs\/"},"modified":"2026-07-31T16:56:21","modified_gmt":"2026-07-31T16:56:21","slug":"docker-oidc-connections-for-github-actions-available-for-docker-orgs","status":"publish","type":"post","link":"https:\/\/rssfeedtelegrambot.bnaya.co.il\/index.php\/2026\/07\/31\/docker-oidc-connections-for-github-actions-available-for-docker-orgs\/","title":{"rendered":"Docker OIDC connections for GitHub Actions available for Docker Orgs"},"content":{"rendered":"<h6 class=\"wp-block-heading\">Eliminate Stored Credentials in Your CI\/CD Pipelines<\/h6>\n<p class=\"wp-block-paragraph\">TL;DR: Docker now supports <a href=\"https:\/\/openid.net\/developers\/how-connect-works\/\" rel=\"nofollow noopener\" target=\"_blank\">OpenID Connect<\/a> (OIDC) for GitHub Actions. Your workflows can authenticate with short-lived, per-run tokens instead of stored PATs or OATs. No secrets to rotate, no credentials to leak.\u00a0<\/p>\n<p class=\"wp-block-paragraph\">GitHub OIDC connections are available to organizations with Docker Team, Docker Business, or <a href=\"https:\/\/docs.docker.com\/dhi\/\" rel=\"nofollow noopener\" target=\"_blank\">Docker Hardened Images (DHI)<\/a> subscriptions, as well as organizations enrolled in the <a href=\"https:\/\/docs.docker.com\/docker-hub\/repos\/manage\/trusted-content\/dsos-program\/\" rel=\"nofollow noopener\" target=\"_blank\">Docker Sponsored Open Source Program (DSOS)<\/a>.<\/p>\n<h3 class=\"wp-block-heading\"> Table of contents<\/h3>\n<ul class=\"wp-block-list\">\n<li>The problem with stored credentials<\/li>\n<li>Who should use this<\/li>\n<li>How OIDC connections work<\/li>\n<li>Getting started<\/li>\n<li>What doesn\u2019t change<\/li>\n<li>Learn more<\/li>\n<\/ul>\n<p class=\"wp-block-paragraph\">\n<\/p><p class=\"wp-block-paragraph\"><em>OIDC token exchange flow between GitHub Actions and Docker<\/em><\/p>\n<figure class=\"wp-block-image size-full\"><img data-opt-id=1131234443  fetchpriority=\"high\" decoding=\"async\" width=\"900\" height=\"674\" src=\"https:\/\/www.docker.com\/app\/uploads\/2026\/07\/diagram-final.png\" alt=\"diagram final\" class=\"wp-image-92570\" title=\"- diagram final\" \/><\/figure>\n<p class=\"wp-block-paragraph\">\n<h2 class=\"wp-block-heading\"><strong>The problem with stored credentials<\/strong><br \/><\/h2>\n<\/p><p class=\"wp-block-paragraph\">Every GitHub Actions workflow that pushes or pulls images from Docker Hub authenticates with a personal access token (PAT) or organization access token (OAT) stored as a GitHub secret. These credentials are long-lived. Someone has to remember to rotate them. A leaked token grants access to your registry \u2014 pulling private images, pushing malicious ones \u2014 and that access persists until someone discovers and revokes it. Rotation is manual and does not scale. As pipelines multiply, so do the credentials that need tracking, and stale tokens are a common audit finding.<\/p>\n<h2 class=\"wp-block-heading\"><strong>Who should use this<\/strong><\/h2>\n<ol class=\"wp-block-list\">\n<li>GitHub issues a signed identity token (a JWT) that encodes the repository, branch, environment, and other metadata about the workflow run.<\/li>\n<li>The workflow calls <a href=\"https:\/\/github.com\/docker\/oidc-action\" rel=\"nofollow noopener\" target=\"_blank\">docker\/<\/a><a href=\"https:\/\/github.com\/docker\/login-action\" rel=\"nofollow noopener\" target=\"_blank\">login<\/a><a href=\"https:\/\/github.com\/docker\/oidc-action\" rel=\"nofollow noopener\" target=\"_blank\">-action<\/a>, which presents this token to Docker.<\/li>\n<li>Docker verifies the token\u2019s signature against GitHub\u2019s public key registry and checks it against rulesets configured in the Admin Console.<\/li>\n<li>If the token matches a ruleset, Docker returns a short-lived access token scoped to the resources defined in that ruleset.<\/li>\n<li><a href=\"https:\/\/github.com\/docker\/login-action\" rel=\"nofollow noopener\" target=\"_blank\">docker\/login-action<\/a> uses this token to authenticate to Docker Hub. From there, docker pull, docker push, and docker build commands work as usual.<\/li>\n<\/ol>\n<p class=\"wp-block-paragraph\">The entire exchange happens without any stored secrets, API keys, or access tokens. The short-lived Docker access token expires in minutes and cannot be reused.<\/p>\n<p class=\"wp-block-paragraph\">This is the same pattern that AWS and GCP already use for cloud resource access (<a href=\"https:\/\/docs.github.com\/en\/actions\/security-for-github-actions\/security-hardening-your-deployments\/configuring-openid-connect-in-amazon-web-services\" rel=\"nofollow noopener\" target=\"_blank\">AWS OIDC for GitHub Actions<\/a>, <a href=\"https:\/\/cloud.google.com\/iam\/docs\/workload-identity-federation\" rel=\"nofollow noopener\" target=\"_blank\">GCP Workload Identity Federation<\/a>). Docker is applying it to container registry access.<\/p>\n<h2 class=\"wp-block-ponyo-heading text-lg\">\n        <strong>Getting started<\/strong><br \/>\n    <\/h2>\n<p class=\"wp-block-paragraph\">Setup is a one-time connection in <a href=\"https:\/\/app.docker.com\/\" rel=\"nofollow noopener\" target=\"_blank\">Docker Home<\/a> plus a small update to your workflow YAML.<\/p>\n<h3 class=\"wp-block-ponyo-heading text-lg\">\n        Step 1: Create a connection<br \/>\n    <\/h3>\n<p class=\"wp-block-paragraph\">Sign in to <a href=\"https:\/\/app.docker.com\/\" rel=\"nofollow noopener\" target=\"_blank\">Docker Home<\/a>, select your organization, and navigate to OIDC connections. Select Create OIDC connection and configure the rulesets that control which repositories, branches, and workflows can access which Docker Hub resources. You can create up to five rulesets per connection. When a workflow triggers an OIDC exchange, Docker checks the token against every ruleset defined in your connection. If a ruleset\u2019s conditions are satisfied, Docker grants access based on the parameters set by that ruleset.<\/p>\n<p class=\"wp-block-paragraph\">Rulesets use OIDC subject claims to match incoming tokens. You can pin to specific repos and branches as a recommended security best practice:<\/p>\n<ul class=\"wp-block-list\">\n<li>repo:my-org\/my-repo:ref:refs\/heads\/main \u2014 only the main branch of a specific repo<\/li>\n<li>repo:my-org\/my-repo:ref:refs\/heads\/release-* \u2014 all release branches<\/li>\n<li>repo:my-org\/my-repo:* \u2013 all branches of this repo<\/li>\n<li>repo:my-org\/* \u2014 any repo in the organization (not recommended)<\/li>\n<\/ul>\n<p class=\"wp-block-paragraph\">Copy the connection ID when you are done.<\/p>\n<p class=\"wp-block-paragraph\">Note: GitHub repositories created after July 15, 2026 use immutable identifiers for default subject claims. For example: repo:octocat@123456\/my-repo@456789:ref:refs\/heads\/main. See the <a href=\"https:\/\/github.blog\/changelog\/2026-04-23-immutable-subject-claims-for-github-actions-oidc-tokens\/\" rel=\"nofollow noopener\" target=\"_blank\">GitHub changelog<\/a> for more details.<\/p>\n<h3 class=\"wp-block-ponyo-heading text-lg\">\n        Step 2: Update your workflow<br \/>\n    <\/h3>\n<p class=\"wp-block-paragraph\">Update your GitHub Actions workflow. Replace <code>&lt;YOUR_CONNECTION_ID&gt; <\/code>with the ID from the previous step and <code>&lt;YOUR_ORG_NAME&gt;<\/code> with your Docker organization name:<\/p>\n<pre class=\"wp-block-code\"><code><\/code><code>permissions:\n  contents: read\n  id-token: write\n\nsteps:\n    - name: Docker login                                                                                                                                                                 \n      uses: docker\/login-action@v4 # v4.5.0+                                                                                                                                                                \n      with:                           \n        username: &lt;YOUR_ORG_NAME&gt;\n      env:                                                                                                                                                                               \n        DOCKERHUB_OIDC_CONNECTIONID: &lt;YOUR_CONNECTION_ID&gt;<\/code><\/pre>\n<p class=\"wp-block-paragraph\">\n<\/p><p class=\"wp-block-paragraph\">The <code>id-token<\/code>: write permission lets the workflow request a GitHub OIDC token. The <code>docker\/login-action<\/code> handles the token exchange and Docker login in a single step when <code>DOCKERHUB_OIDC_CONNECTIONID<\/code> is set. From there, <kbd>docker pull,<\/kbd> <kbd>docker push<\/kbd>, and <kbd>docker build<\/kbd> commands work as usual.details of the incoming claim sub value, which you can use to diagnose why the connection failed.<\/p>\n<h3 class=\"wp-block-heading\"><\/h3>\n<h3 class=\"wp-block-ponyo-heading text-lg\">\n        Step 3: Verify the OIDC connection works<br \/>\n    <\/h3>\n<p class=\"wp-block-paragraph\">Run your workflow and confirm it completes successfully. If you encounter an error, the Failures tab of the OIDC connection page will show the details of the incoming claim sub value, which you can use to diagnose why the connection failed.<\/p>\n<h3 class=\"wp-block-ponyo-heading text-lg\">\n        Step 4: Remove the stored credential<br \/>\n    <\/h3>\n<p class=\"wp-block-paragraph\">After verifying your workflow runs successfully with OIDC, remove the old PAT or OAT from your GitHub repository secrets. You no longer need it.<\/p>\n<h3 class=\"wp-block-ponyo-heading text-lg\">\n        Migration Checklist<br \/>\n    <\/h3>\n<ul class=\"wp-block-list\">\n<li>Create a connection<\/li>\n<li>Update your workflow<\/li>\n<li>Verify the OIDC connection works<\/li>\n<li>Remove stored credentials<\/li>\n<\/ul>\n<h2 class=\"wp-block-ponyo-heading text-lg\">\n        What doesn\u2019t change<br \/>\n    <\/h2>\n<ul class=\"wp-block-list\">\n<li>Existing PATs and OATs keep working. Organizations can migrate workflows to OIDC connections at their own pace.<\/li>\n<li>Images, registries, and build workflows are unchanged. OIDC connections only replace the authentication step; everything downstream is the same.<\/li>\n<li>Local development and non-GitHub CI still use PATs and OATs. OIDC connections are the recommended replacement for GitHub Actions specifically. Other CI providers will follow based on demand.<\/li>\n<\/ul>\n<h2 class=\"wp-block-ponyo-heading text-lg\">\n        Learn more<br \/>\n    <\/h2>\n<ul class=\"wp-block-list\">\n<li>Learn more about <a href=\"https:\/\/openid.net\/developers\/how-connect-works\/\" rel=\"nofollow noopener\" target=\"_blank\">OpenID Connect<\/a><\/li>\n<li>Visit <a href=\"https:\/\/app.docker.com\/\" rel=\"nofollow noopener\" target=\"_blank\">Docker Home<\/a> to get started<\/li>\n<li>Read the <a href=\"https:\/\/docs.docker.com\/enterprise\/security\/oidc-connections\/\" rel=\"nofollow noopener\" target=\"_blank\">documentation<\/a><\/li>\n<\/ul>\n<p class=\"wp-block-paragraph\">\n<\/p>","protected":false},"excerpt":{"rendered":"<p>Eliminate Stored Credentials in Your CI\/CD Pipelines TL;DR: Docker now supports OpenID Connect (OIDC) for GitHub Actions. Your workflows can [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":4705,"comment_status":"","ping_status":"","sticky":false,"template":"","format":"standard","meta":{"site-sidebar-layout":"default","site-content-layout":"","ast-site-content-layout":"default","site-content-style":"default","site-sidebar-style":"default","ast-global-header-display":"","ast-banner-title-visibility":"","ast-main-header-display":"","ast-hfb-above-header-display":"","ast-hfb-below-header-display":"","ast-hfb-mobile-header-display":"","site-post-title":"","ast-breadcrumbs-content":"","ast-featured-img":"","footer-sml-layout":"","ast-disable-related-posts":"","theme-transparent-header-meta":"","adv-header-id-meta":"","stick-header-meta":"","header-above-stick-meta":"","header-main-stick-meta":"","header-below-stick-meta":"","astra-migrate-meta-layouts":"default","ast-page-background-enabled":"default","ast-page-background-meta":{"desktop":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"ast-content-background-meta":{"desktop":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"footnotes":""},"categories":[4],"tags":[],"class_list":["post-4704","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-docker"],"_links":{"self":[{"href":"https:\/\/rssfeedtelegrambot.bnaya.co.il\/index.php\/wp-json\/wp\/v2\/posts\/4704","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/rssfeedtelegrambot.bnaya.co.il\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/rssfeedtelegrambot.bnaya.co.il\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/rssfeedtelegrambot.bnaya.co.il\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/rssfeedtelegrambot.bnaya.co.il\/index.php\/wp-json\/wp\/v2\/comments?post=4704"}],"version-history":[{"count":0,"href":"https:\/\/rssfeedtelegrambot.bnaya.co.il\/index.php\/wp-json\/wp\/v2\/posts\/4704\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/rssfeedtelegrambot.bnaya.co.il\/index.php\/wp-json\/wp\/v2\/media\/4705"}],"wp:attachment":[{"href":"https:\/\/rssfeedtelegrambot.bnaya.co.il\/index.php\/wp-json\/wp\/v2\/media?parent=4704"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/rssfeedtelegrambot.bnaya.co.il\/index.php\/wp-json\/wp\/v2\/categories?post=4704"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/rssfeedtelegrambot.bnaya.co.il\/index.php\/wp-json\/wp\/v2\/tags?post=4704"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}