Workload Identityを使ってGitHub ActionsからGoogle Cloudにアクセスする

CI/CD

GitHub Actionsを使ってGoogle Cloud上のリソースにアクセスするには、認証が必要です。
従来、この認証には長期間有効なJSON形式のサービスアカウントキーをエクスポートして保存する必要がありましたが、この方法には以下のような課題がありました。


  • セキュリティリスク:サービスアカウントキーの漏洩による、不正アクセスの危険性
  • 管理の手間:キーを安全に管理するためにシークレット管理システムが必要
  • ポリシー制約:組織によってはセキュリティポリシーの一環としてサービスアカウントキーの作成を禁止している場合があり、認証が行えなくなる可能性。

しかし、GitHub ActionsにOIDC(OpenID Connect)トークンが導入されたため、Workload Identity連携を利用してGoogle Cloudと直接認証できるようになりました。その結果、サービスアカウントキーのエクスポートや管理が不要になり、以前よりもセキュアなアクセスが可能になりました。

出典:GitHub Actions からのキーなしの認証の有効化

本記事では、GitHub ActionsからGoogle CloudへセキュアにアクセスするためのWorkload Identityの設定手順を解説し、最後にGitHub Actionsによる疎通確認を行います。
※GitHubが有用なドキュメントを公開してくれているので、こちらを読むと全体像が把握しやすいと思います。参考:Configuring OpenID Connect in Google Cloud Platform

前提条件

Google Cloudでの設定

Workload Identity Poolの作成

以下のコマンドを実行してWorkload Identity Poolを作成します。

gcloud iam workload-identity-pools create "github-pool" \
  --project="<プロジェクトID>" \
  --location="global" \
  --display-name="GitHub OIDC Pool"

実行した結果、”Created workload identity pool [github-pool].“と表示されればOK。
また、Google Cloudの対象プロジェクト > ダッシュボード > IAMと管理 > Workload Identity連携と進むことで、Workload Identity プールが作成されていれていることが確認できます。

Workload Identity Providerの作成

GitHub OIDCを使用するWorkload Identity Providerを作成します。
※使用したいmappingがある場合は、こちらを参照して適宜設定してください

gcloud iam workload-identity-pools providers create-oidc "github-provider" \
  --project="<プロジェクトID>" \
  --location="global" \
  --workload-identity-pool="github-pool" \
  --display-name="GitHub Provider" \
  --attribute-mapping="google.subject=assertion.sub,attribute.repository=assertion.repository" \
  --issuer-uri="https://token.actions.githubusercontent.com" \
  --attribute-condition="assertion.repository == '<組織名 or リポジトリ所有者名>/<リポジトリ名>'"

実行した結果、"Created workload identity pool provider [github-provider]."と表示されればOK。
また、ダッシュボード > IAMと管理 > Workload Identity連携 > GitHub OIDC Pool > 編集と進むことで、Workload Identity Providerが作成されていれていることが確認できます。

サービスアカウントの作成と権限の付与

GitHub Actionsで使用するサービスアカウントを作成し、必要なIAMロールを付与します。

gcloud iam service-accounts create "github-sa" \
  --project="<プロジェクトID>" \
  --display-name="GitHub Service Account"

実行した結果、"Created service account [github-sa]."と表示されればOK。
また、ダッシュボード > IAMと管理 > サービスアカウントと進むことで、サービスアカウントが作成されていれていることが確認できます。


権限を付与する例:
今回はGoogle Cloudプロジェクトの一覧を表示したいので、roles/viewerを追加します。
※検証が完了したら、不要なロールは削除してください(最小権限の原則)。

gcloud projects add-iam-policy-binding <プロジェクトID> \
  --member="serviceAccount:github-sa@<プロジェクトID>.iam.gserviceaccount.com" \
  --role="roles/viewer"

実行した結果、"Updated IAM policy for project [xxx-xxx]."と表示されればOK。
また、ダッシュボード > IAMと管理 > IAMと進むことで、サービスアカウントに閲覧者の権限が付与されていれていることが確認できます。

サービスアカウントへのポリシーの関連付け

Workload Identity Poolとサービスアカウントを関連付けをします。

gcloud iam service-accounts add-iam-policy-binding \
  "github-sa@<プロジェクトID>.iam.gserviceaccount.com" \
  --project="<プロジェクトID>" \
  --role="roles/iam.workloadIdentityUser" \
  --member="principalSet://iam.googleapis.com/projects/<プロジェクト番号>/locations/global/workloadIdentityPools/github-pool/attribute.repository/<組織名 or リポジトリ所有者名>/<リポジトリ名>"

実行した結果、
Updated IAM policy for serviceAccount [github-sa@xxx-xxx.iam.gserviceaccount.com].
と表示されればOK。
また、ダッシュボード > IAMと管理 > Workload Identity連携 > GitHub OIDC Pool > 接続済みサービス アカウントと進むことで、Workload Identity プールが作成されていれていることが確認できます。

API の有効化

今回の検証で必要なAPIを有効化します。
※権限と同様、検証が完了したら、不要なロールは削除してください(最小権限の原則)。

# IAM Service Account Credentials API の有効化
gcloud services enable iamcredentials.googleapis.com --project=<プロジェクトID>

# Cloud Resource Manager API の有効化
gcloud services enable cloudresourcemanager.googleapis.com --project=<プロジェクトID>

実行した結果、"finished successfully."と表示されればOK。

GitHubリポジトリでの設定

GitHub SecretsにプロジェクトIDを追加

GitHub Actionsで使う2つのSecretsをGitHubリポジトリのSettings > Secrets and variables > Actionsから追加します。
リポジトリのシークレットの作成方法

Name:WORKLOAD_IDENTITY_PROVIDER
Secret:projects/<プロジェクト番号>/locations/global/workloadIdentityPools/github-pool/providers/github-provider

Name:SERVICE_ACCOUNT
Secret:github-sa@<プロジェクトID>.iam.gserviceaccount.com

GitHub Actionsのワークフロー設定

.github/workflows配下に以下のようなgithub-actions.ymlファイルを作成します。

# このワークフローは、GitHub ActionsからGoogle CloudにOIDCを使用して認証し、アクセスの疎通確認を行う。
# トリガーはmainブランチへのpushイベントで発生する。
# ジョブでは以下を実行する:
# 1. リポジトリのコードをクローン。
# 2. Googleが提供する認証アクションを使い、OIDCトークンを利用してGoogle Cloudへ認証。
# 3. gcloud CLIを用いて、Google Cloudプロジェクトへのアクセスが成功することを確認。

name: Connect to Google Cloud via OIDC

on:
  push:
    branches:
      - main

jobs:
  test-oidc:
    runs-on: ubuntu-latest
    permissions:
      id-token: write
      contents: read

    steps:
      - name: Checkout repository
        uses: actions/checkout@v3

      - name: Authenticate to GCP
        uses: google-github-actions/auth@v1
        with:
          workload_identity_provider: ${{ secrets.WORKLOAD_IDENTITY_PROVIDER }}
          service_account: ${{ secrets.SERVICE_ACCOUNT }}

      - name: Verify access to Google Cloud
        run: |
          gcloud projects list

疎通確認

ワークフローをmainブランチへのプッシュでトリガーし、ログに以下のようなgcloud projects listの結果が出力されれば成功です。

まとめ

この記事では、GitHub ActionsからGoogle Cloudへのセキュアな接続をOIDCを用いて設定する方法を説明しました。この方法により、サービスアカウントキーの保存が不要になり、セキュリティが向上します。

詳細な設定やトラブルシューティングはWorkload Identity 連携(Google Cloud公式)あたりを見れば解決できると思われます。