GitHub リポジトリ + Workload Identity FederationKeyless CI/CD identity
GitHub Actions(CI/CD 基盤 = ソースコード更新を契機に自動でビルド・デプロイする仕組み)から Google Cloud にデプロイするための認証経路を設計しました。JSON 鍵ファイルを発行しない「キーレス」方式(Workload Identity Federation、以下 WIF)で、リポジトリ <owner>/matsuba のワークフローのみが デプロイ用 SA を借りられる構成です。
従来の SA キー方式と WIF の対比SA key vs WIF
JSON 鍵を発行して GitHub Secrets に置く
- 鍵ファイル(JSON)= 長期間有効な「合鍵」を発行
- GitHub Secrets に置いた瞬間、漏洩リスクが GitHub の保護に依存
- 鍵が漏れると 誰でも・どこからでもその SA を使える
- ローテーション(更新)が運用負担。事故時の失効も手作業
- 監査ログに「鍵 ID」しか残らず誰が使ったかが追えない
GitHub の身分を Google が検証して一時的に貸与
- 鍵ファイルは 1 つも発行しない
- GitHub Actions 実行毎に OIDC トークン(短命 ID 証明書)を発行
- Google 側で「
<owner>/matsubaのワークフロー」だけを許可するように属性条件を設定 - 有効期限が短い + リポジトリに紐付くため漏洩リスクが構造的に低い
- ログには発行元リポジトリ・ブランチが残るため誰が使ったか追える
キーレス認証の流れToken exchange flow
3 ステップで何が起きているか: ①GitHub が「私は matsuba リポジトリの main ブランチで動いているワークフローです」という署名付きの身分証(OIDC トークン)を発行 → ②Google の WIF Pool が属性条件で検証し、合致したら SA を借りる権利を付与 → ③SA の権限で Cloud Run / Artifact Registry / Secret Manager に対して最大 1 時間だけ有効なアクセストークンを発行。鍵ファイルが介在する瞬間は 1 度もありません。
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 |
デプロイ用 SA に付与した 5 ロールGranted roles
デプロイに必要な権限だけを 5 個に絞って付与しました。実際のデプロイ操作(コンテナイメージ push → Cloud Run リビジョン作成 → Secret 参照)に必要な最小集合です。
| ロール | 目的 |
|---|---|
roles/run.admin | Cloud Run サービスのリビジョン作成・更新 |
roles/artifactregistry.writer | Artifact Registry に Docker イメージを push |
roles/iam.serviceAccountUser | 各サービスの実行 SA(web の実行 SA 等)を Cloud Run に紐付け |
roles/cloudbuild.builds.builder | Cloud Build 経由のイメージビルド |
roles/secretmanager.secretAccessor | Cloud Run デプロイ時に Secret を --update-secrets で渡す |
GitHub Secrets に登録した値 · 5 種GitHub Secrets
| Secret 名 | 値の種類 | 用途 |
|---|---|---|
WIF_PROVIDER | WIF プロバイダのフルパス | キーレス認証の宛先 |
DEPLOY_SA | SA メール | impersonate 対象 |
GCP_PROJECT_ID | <project-id> | 各種 gcloud コマンド |
PROD_DIRECT_URL | Postgres Direct 接続文字列 | マイグレーション適用(プーラー経由不可) |
RESEND_API_KEY | Resend API キー | CI 上のテスト送信用(本番アプリは Secret Manager 経由) |
本番アプリ用 DATABASE_URL は GitHub Secrets には置きません。Cloud Run の --update-secrets オプションで Secret Manager から動的に注入する設計です。これにより、本番 DB の認証情報は Secret Manager とアプリ実行 SA の組み合わせでしか到達できなくなります。