本文へ移動
Step 05 · Keyless CI/CD

GitHub リポジトリ + Workload Identity FederationKeyless CI/CD identity

GitHub Actions(CI/CD 基盤 = ソースコード更新を契機に自動でビルド・デプロイする仕組み)から Google Cloud にデプロイするための認証経路を設計しました。JSON 鍵ファイルを発行しない「キーレス」方式(Workload Identity Federation、以下 WIF)で、リポジトリ <owner>/matsuba のワークフローのみが デプロイ用 SA を借りられる構成です。

所要時間: 40 分 前提条件: Step 00 + Step 03 後続: Step 06
01

従来の SA キー方式と WIF の対比SA key vs WIF

従来 · SA キー方式

JSON 鍵を発行して GitHub Secrets に置く

  • 鍵ファイル(JSON)= 長期間有効な「合鍵」を発行
  • GitHub Secrets に置いた瞬間、漏洩リスクが GitHub の保護に依存
  • 鍵が漏れると 誰でも・どこからでもその SA を使える
  • ローテーション(更新)が運用負担。事故時の失効も手作業
  • 監査ログに「鍵 ID」しか残らず誰が使ったかが追えない
本構築 · Workload Identity Federation

GitHub の身分を Google が検証して一時的に貸与

  • 鍵ファイルは 1 つも発行しない
  • GitHub Actions 実行毎に OIDC トークン(短命 ID 証明書)を発行
  • Google 側で「<owner>/matsuba のワークフロー」だけを許可するように属性条件を設定
  • 有効期限が短い + リポジトリに紐付くため漏洩リスクが構造的に低い
  • ログには発行元リポジトリ・ブランチが残るため誰が使ったか追える
02

キーレス認証の流れToken exchange flow

図 · GitHub OIDC → Google → SA impersonate の 3 ステップ
GitHub Actions<owner>/matsubapush → mainWorkload Identity Poolgithub-actions-pool · OIDC プロバイダ属性条件で発行元を検証デプロイ用 SA短命アクセストークン発行最大 1 時間有効① OIDC token② impersonateCloud Runrun.admin · デプロイArtifact Registryartifactregistry.writerSecret ManagersecretAccessor③ short-lived access token で本番デプロイ属性条件: assertion.repository_owner == '<owner>'これにより他リポジトリ(フォーク等)から SA を借りる経路を構造的に遮断

3 ステップで何が起きているか: ①GitHub が「私は matsuba リポジトリの main ブランチで動いているワークフローです」という署名付きの身分証(OIDC トークン)を発行 → ②Google の WIF Pool が属性条件で検証し、合致したら SA を借りる権利を付与 → ③SA の権限で Cloud Run / Artifact Registry / Secret Manager に対して最大 1 時間だけ有効なアクセストークンを発行。鍵ファイルが介在する瞬間は 1 度もありません。

03

WIF の主要設定WIF configuration

項目値
Workload Identity Pool 名github-actions-pool
プロバイダ名github(OIDC、Issuer https://token.actions.githubusercontent.com)
属性マッピングgoogle.subject ← assertion.sub / attribute.repository ← assertion.repository / attribute.repository_owner / attribute.ref
属性条件(核)assertion.repository_owner == '<owner>'
プリンシパル紐付けattribute.repository == '<owner>/matsuba'
WIF Provider フルパスprojects/<project-number>/locations/global/workloadIdentityPools/github-actions-pool/providers/github
04

デプロイ用 SA に付与した 5 ロールGranted roles

デプロイに必要な権限だけを 5 個に絞って付与しました。実際のデプロイ操作(コンテナイメージ push → Cloud Run リビジョン作成 → Secret 参照)に必要な最小集合です。

ロール目的
roles/run.adminCloud Run サービスのリビジョン作成・更新
roles/artifactregistry.writerArtifact Registry に Docker イメージを push
roles/iam.serviceAccountUser各サービスの実行 SA(web の実行 SA 等)を Cloud Run に紐付け
roles/cloudbuild.builds.builderCloud Build 経由のイメージビルド
roles/secretmanager.secretAccessorCloud Run デプロイ時に Secret を --update-secrets で渡す
05

GitHub Secrets に登録した値 · 5 種GitHub Secrets

Secret 名値の種類用途
WIF_PROVIDERWIF プロバイダのフルパスキーレス認証の宛先
DEPLOY_SASA メールimpersonate 対象
GCP_PROJECT_ID<project-id>各種 gcloud コマンド
PROD_DIRECT_URLPostgres Direct 接続文字列マイグレーション適用(プーラー経由不可)
RESEND_API_KEYResend API キーCI 上のテスト送信用(本番アプリは Secret Manager 経由)

本番アプリ用 DATABASE_URL は GitHub Secrets には置きません。Cloud Run の --update-secrets オプションで Secret Manager から動的に注入する設計です。これにより、本番 DB の認証情報は Secret Manager とアプリ実行 SA の組み合わせでしか到達できなくなります。