Docker は GitHub Actions と Docker Hub 間で OpenID Connect 認証を有効化し、ワークフローがリポジトリのシークレットから Personal Access Token を読み込む代わりに、実行ごとに署名された ID トークンを Docker と交換して短命の Docker 認証情報を取得できるようにしました。Docker ブログによると、この機能は Docker Team、Docker Business、Docker Hardened Images プランの組織で利用可能です。プラットフォームチームにとっては、レジストリ認証情報を「90 日ごとにローテーションして祈る」状態から、AWS、GCP、Azure、HashiCorp Vault ですでに使われているフェデレーテッドアイデンティティパターンと同じ枠組みへ移行するものです。
仕組みの概要
このパターンは Actions の標準的な OIDC 交換です。ワークフローが permissions: id-token: write を宣言すると、GitHub はリポジトリ、ブランチまたは環境、ワークフロー名などのクレームを含む署名付き JWT を発行します。ワークフローはこの JWT を Docker に提示し、Docker は GitHub の公開鍵で署名を検証した後、Docker 側で設定された信頼ポリシーとクレームを照合して、実行中の残りのステップで使用できる短命の認証情報を返します。ジョブが終了すると認証情報は失効します。リポジトリ、環境シークレット、Actions キャッシュに長期的な Docker トークンは残りません。Docker はこの変更を CI/CD パイプラインから保存された認証情報を排除するものと位置づけていますが、これは PAT を実際に削除した場合に限られます。
この信頼ポリシーについて 2 点重要です。1 つ目は、ポリシーのスコープが GitHub ではなく Docker 側で定義される点です。my-org/* の任意のブランチで任意のワークフローを信頼するポリシーを書くと、攻撃者が組織内の任意のリポジトリにブランチをプッシュするだけで Docker 認証情報を取得できてしまいます。より安全な形は、特定のリポジトリと特定の環境(environment:prod)にポリシーを固定し、GitHub 側で環境に必須のレビューアを配置することです。2 つ目は、OIDC は認証情報は排除しますが、認可境界は排除しない点です。漏洩したトークンは短命ですが、信頼ポリシー自体は長期的に監査が必要なオブジェクトになります。
認証情報が重要だった理由
静的なレジストリトークンは、今年発生した多くのサプライチェーンインシデントの原因となっています。公開タグへのプッシュが可能な PAT や OAT が侵害されたブランチから取得されると、1 回の API 呼び出しでサプライチェーンハイジャックが成立し、クラウド IAM キーとは異なり、ワークロードアイデンティティ境界の背後に置かれることは稀です。ローテーションは有効ですが無料ではありません。ローテーションされた Docker トークンは、イメージをプッシュするすべての Actions リポジトリとセルフホストランナーに再配布する必要があり、そのためチームはポリシーで定められた頻度よりもローテーションを怠りがちです。
OIDC は、侵害されたワークフローが自身の実行内でできることを変えるものではありません。残留物を変えるものです。ジョブ終了後、シークレットストアから盗むべきものは何も残りません。漏洩したトークンの影響範囲は「次のローテーションサイクルまで」から「ジョブ終了まで」に縮小され、ほとんどの Actions ジョブでは数分程度です。これが運用面での読み:ローテーション対象が減り、インベントリ対象が減り、インシデント時の失効対象が減るということです。
ワークフローへの組み込み
Actions 側の交換は、他の OIDC 統合と同等の形です。リリース固有の部分をプレースホルダーとしたスケッチを以下に示します。
permissions:
id-token: write
contents: read
jobs:
push:
runs-on: ubuntu-latest
environment: prod
steps:
- uses: actions/checkout@<full-40-char-sha>
- name: Log in to Docker Hub via OIDC
uses: docker/login-action@<full-40-char-sha>
with:
# OIDC-mode inputs per the Docker docs for this feature;
# no username or password is stored in the repo.
registry: docker.io
# ...OIDC-specific parameters go here...
- name: Build and push
run: |
docker buildx build \
--tag docker.io/$REGISTRY_NAMESPACE/app:${{ github.sha }} \
--push .
Enter fullscreen mode Exit fullscreen mode
運用担当者向けの 2 つの注意点。ログインアクションはフローティングタグではなく完全なコミット SHA にピン留めしてください。渡す認証情報は時間制限されますが、その中のコードは制限されません。また、Docker 側の信頼ポリシーは狭く保ってください。リポジトリ、ブランチまたは環境、ワークフローファイルパスを指定します。ここでワイルドカードを使うことは、廃止しようとしていた古い read_write PAT と同等です。
この変更が解決しないこと
OIDC フェデレーションは認証情報の配管の変更です。「実行が有効なトークンを持っている」以降のすべては、従来通りの注意が必要です。
イメージの出所は変わりません。OIDC で認証されたワークフローは、依然として実行するよう指示されたワークフローであり、トリガーが許可するブランチのものです。ポリシーが main を信頼する場合、main へのセルフ承認 PR が Docker 認証情報を取得します。ブランチ保護、デプロイメント環境での必須レビューア、疑わしい悪意あるワークフローに対する Actions の承認保留制御は、すべてこの変更の上流にあります。
セルフホストランナーはもう一つの静かな注意点です。GitHub ホストランナーはドキュメント通りに OIDC トークンを発行します。セルフホストランナーも発行できますが、信頼境界は「ランナーホストを制御する者が、信頼ポリシーの範囲で Docker 認証情報を要求できる」になります。セルフホストランナーフリートがリポジトリまたは環境ごとに完全に分離されていない場合、Docker の信頼ポリシーはランナー登録トークンと少なくとも同等に慎重に扱う必要があります。
署名は別問題です。OIDC はプッシュ認証情報を排除しますが、署名付きダイジェストを追加するものではありません。プッシュ側が生成したものをプル側で検証したい場合は、Cosign またはプラットフォーム独自のアテステーションフローが依然として必要です。
他 CI プラットフォームでのレジストリ認証の扱い
Docker Hub はこの特定の統合には遅れましたが、パターン自体には遅れていません。レジストリ認証の話は、パイプラインがどこで実行されるかによって異なります。
GitHub Actions → GHCR。 レジストリが ghcr.io の場合、GitHub Actions は以前から最も緊密な仕組みを持っていました。組み込みの GITHUB_TOKEN がリポジトリスコープで組織のコンテナレジストリにプッシュでき、追加のフェデレーション設定は不要です。Docker Hub が必須要件でなければ、GitHub ネイティブなチームにとっては GHCR が依然としてよりシンプルな選択肢であり、今回の Docker OIDC 変更はこのギャップを埋めるものではありません。
GitLab CI ID トークン。 GitLab 独自の OIDC(パイプライン内の id_tokens:)は AWS、GCP、Vault へ、そしてレジストリ自身の OIDC プロバイダ経由で GitLab の Container Registry へネイティブにフェデレーションします。すでに GitLab を利用しているチームにとって、ID トークンワークフローは外部レジストリ統合よりもファーストパーティであり、スタックをゼロから選ぶ場合により適した選択肢です。
CircleCI OIDC。 CircleCI はジョブごとに OIDC トークンを発行し、主な用途はクラウド IAM(AWS、GCP)です。CircleCI でのレジストリログインは、ほとんどのチームのセットアップで Docker Hub 用の保存されたコンテキストシークレットに依存しており、これが GitHub 側で Docker の変更が対処する状態そのものです。
Buildkite agent OIDC。 Buildkite のエージェント署名 OIDC トークンは AWS や Vault で広く使われています。レジストリ認証パターンはフリートによって異なり、エージェントフリートの信頼境界の方がトークンの種類よりも重要な調整点です。
Buddy。 Buddy はホスト型 CI/CD プラットフォームで、Docker パイプラインアクションに Buddy スコープのシークレットやパイプラインごとの短命認証情報を読み込むレジストリログインステップが含まれています。Docker プッシュと環境ゲーティングを残りのデリバリーパイプラインと同じ UI で扱いたい場合に選択肢の一つです。レジストリ要件が完全に Docker Hub にあり、CI の残りがすでに GitHub にある場合、Docker の新しい OIDC フローは既存のツールチェーン内で作業を継続できます。
通底するメッセージ:フェデレーテッドアイデンティティは、レジストリ認証のデフォルトの前提となりつつあり、nice-to-have ではなくなりました。CI での長期的なレジストリトークンは例外となり、残るすべてのトークンはプラットフォームチームのバックログにおけるローテーション項目です。
今後の注目点
追跡すべき点が 2 つあります。1 つ目は、Docker 側の信頼ポリシーサーフェスが、初期の AWS-to-Actions OIDC ポリシーで見られたような設定ミスによる影響範囲の拡大を起こすかどうかです。過度に広い aud や sub クレームにより組織内の任意のワークフローが本番ロールを引き継げる状態です。対策はクレームの厳格化であり、同じ規律が初日からここにも適用されます。2 つ目は、Docker が OIDC フローを GitHub Actions 以外の CI プラットフォームへ拡張するかどうかです。現在のリリースは発表によると GitHub Actions と有料 Docker Org ティアのみです。その他のプラットフォームは PAT のローテーションを継続します。
0 Comments
Log in to join the conversation.No comments yet. Be the first to share your thoughts.