CI/CDパイプラインから保存された認証情報を排除

TL;DR: DockerがGitHub Actions向けのOpenID Connect(OIDC)をサポートしました。ワークフローは保存されたPATやOATの代わりに、実行ごとに発行される短期間のトークンで認証できます。シークレットをローテーションする必要がなく、認証情報の漏洩もありません。

GitHub OIDC接続は、Docker Team、Docker Business、またはDocker Hardened Images (DHI)サブスクリプションを持つ組織、およびDocker Sponsored Open Source Program (DSOS)に参加している組織で利用できます。

目次

  • 保存された認証情報の問題
  • 対象ユーザー
  • OIDC接続の仕組み
  • はじめに
  • 変更されないこと
  • 詳細を見る

GitHub ActionsとDocker間のOIDCトークン交換フロー

diagram final

保存された認証情報の問題

Docker HubからイメージをプッシュまたはプルするすべてのGitHub Actionsワークフローは、GitHubシークレットとして保存されたpersonal access token(PAT)またはorganization access token(OAT)で認証します。これらの認証情報は長期有効です。誰かがローテーションを忘れないようにする必要があります。漏洩したトークンはレジストリへのアクセス権を与え — プライベートイメージのプルや悪意のあるイメージのプッシュが可能になり — そのアクセス権は誰かが発見して失効させるまで有効です。ローテーションは手動であり、スケールしません。パイプラインが増えるにつれ、追跡が必要な認証情報も増え、古いトークンは一般的な監査所見となります。

対象ユーザー

  1. GitHubは、ワークフローの実行に関するリポジトリ、ブランチ、環境、その他のメタデータをエンコードした署名付きアイデンティティトークン(JWT)を発行します。
  2. ワークフローは、docker/login-actionを呼び出し、このトークンをDockerに提示します。
  3. Dockerは、GitHubのパブリックキー レジストリに対してトークンの署名を検証し、Admin Consoleで設定されたルールセットと照合します。
  4. トークンがルールセットと一致する場合、Dockerはそのルールセットで定義されたリソースにスコープされた短期間のアクセストークンを返します。
  5. docker/login-actionはこのトークンを使用してDocker Hubに認証します。以降は、docker pull、docker push、docker buildコマンドが通常通り動作します。

交換全体は、保存されたシークレット、APIキー、アクセストークンなしで行われます。短期間のDockerアクセストークンは数分で有効期限が切れ、再利用できません。

これは、クラウドリソースへのアクセスにAWSとGCPがすでに使用しているパターン(AWS OIDC for GitHub ActionsGCP Workload Identity Federation)と同じです。Dockerはこれをコンテナレジストリアクセスに適用しています。

はじめに

セットアップは、Docker Homeでの1回限りの接続と、ワークフローYAMLへの小さな更新です。

ステップ1: 接続を作成する

Docker Homeにサインインし、組織を選択して、OIDC接続に移動します。Create OIDC connectionを選択し、どのリポジトリ、ブランチ、ワークフローがどのDocker Hubリソースにアクセスできるかを制御するルールセットを設定します。1つの接続につき最大5つのルールセットを作成できます。ワークフローがOIDC交換をトリガーすると、Dockerは接続で定義されたすべてのルールセットに対してトークンをチェックします。ルールセットの条件が満たされた場合、Dockerはそのルールセットで設定されたパラメータに基づいてアクセスを許可します。

ルールセットはOIDCサブジェクトクレームを使用して着信トークンと照合します。推奨されるセキュリティのベストプラクティスとして、特定のレポとブランチにピン留めできます:

  • repo:my-org/my-repo:ref:refs/heads/main — 特定のレポのmainブランチのみ
  • repo:my-org/my-repo:ref:refs/heads/release-* — すべてのリリースブランチ
  • repo:my-org/my-repo:* – このレポのすべてのブランチ
  • repo:my-org/* — 組織内の任意のレポ(推奨されません)

完了したら接続IDをコピーします。

注: 2026年7月15日以降に作成されたGitHubリポジトリは、デフォルトのサブジェクトクレームに不変の識別子を使用します。例: repo:octocat@123456/my-repo@456789:ref:refs/heads/main。詳細はGitHub changelogを参照してください。

ステップ2: ワークフローを更新する

GitHub Actionsワークフローを更新します。前のステップのIDで<YOUR_CONNECTION_ID> を置き換え、Docker組織名で<YOUR_ORG_NAME>を置き換えます:

permissions:
  contents: read
  id-token: write

steps:
    - name: Docker login                                                                                                                                                                 
      uses: docker/login-action@v4 # v4.5.0+                                                                                                                                                                
      with:                           
        username: <YOUR_ORG_NAME>
      env:                                                                                                                                                                               
        DOCKERHUB_OIDC_CONNECTIONID: <YOUR_CONNECTION_ID>

id-token: writeパーミッションにより、ワークフローはGitHub OIDCトークンをリクエストできます。docker/login-actionは、DOCKERHUB_OIDC_CONNECTIONIDが設定されている場合、トークン交換とDockerログインを1つのステップで処理します。以降は、docker pull、docker push、docker buildコマンドが通常通り動作します。着信クレームsub値の詳細は、接続が失敗した理由を診断するために使用できます。

ステップ3: OIDC接続が動作することを確認する

ワークフローを実行し、正常に完了することを確認します。エラーが発生した場合、OIDC接続ページのFailuresタブに着信クレームsub値の詳細が表示され、接続が失敗した理由を診断するために使用できます。

ステップ4: 保存された認証情報を削除する

OIDCでワークフローが正常に実行されることを確認したら、古いPATまたはOATをGitHubリポジトリのシークレットから削除します。もう必要ありません。

移行チェックリスト

  • 接続を作成する
  • ワークフローを更新する
  • OIDC接続が動作することを確認する
  • 保存された認証情報を削除する

変更されないこと

  • 既存のPATとOATは引き続き動作します。組織は、独自のペースでOIDC接続に移行できます。
  • イメージ、レジストリ、ビルドワークフローは変更されません。OIDC接続は認証ステップのみを置き換えます。以降はすべて同じです。
  • ローカル開発とGitHub以外のCIは引き続きPATとOATを使用します。OIDC接続は、GitHub Actions専用の推奨される代替手段です。他のCIプロバイダーは、需要に基づいて今後対応します。

詳細を見る