Workload Identity 連携で GithubActions から GCP リソースをデプロイする

この記事は個人ブログと同じ内容です

www.ritolab.com


GCP 外のアプリケーションから GCP リソースを操作する場合に、サービスアカウントキーを用いずに安全にリソースへアクセスできる Workload Identity 連携を用いて、Github Actions から GCP リソースのデプロイを行います。

Workload Identity 連携:簡単で安全な Google Cloud アクセス

Workload Identity 連携は、Google Cloud外のアプリケーションが安全かつ簡単にGoogle Cloudリソースを利用できるようにする機能です。

従来、外部アプリケーションはサービスアカウントキーを使ってGoogle Cloudにアクセスしていました。しかし、このキーは、漏洩リスクやローテーションなど管理が難しく、セキュリティリスクも高いものです。

Workload Identity 連携はこの問題を解決します。キーの代わりに、外部の ID システム(例:AWS IAMなど)と Google Cloud の IAM を連携させます。これにより、以下の利点があります。

  1. セキュリティが向上します:キーの漏洩リスクがなくなります。
  2. 管理が楽になります:キーの作成や更新、削除の手間が不要になります。
  3. きめ細かな制御が可能になります:外部 ID に直接権限を付与したり、一時的に権限を貸し出したりできます。

例えば、AWSで動いているアプリケーションが Google Cloud Storage のデータを読み取りたい場合、Workload Identity 連携を使えば、AWS の IAMロールに Google Cloud の読み取り権限を付与できます。これにより、安全かつ簡単にクラウド間でのデータアクセスが実現します。

Workload Identity 連携は、こういったマルチクラウド環境や、クラウドとオンプレミス環境を跨ぐシステムで特に力を発揮します。

GithubActions から GCP リソースのデプロイ

今回は、GithubGCP を連携させて動作させてみます。

例えば、CloudFunctions の関数を Git 管理しているとして、それらのデプロイを Workload Identity 連携で実施するようなイメージです。本来ならば、デプロイヤーとして作成したサービスアカウントとして GithubActions からデプロイを実行する場合、サービスアカウントキーを用いた認証が必要ですが、それが不要になります。

まずは、GCP リソースをデプロイするサービスアカウントを作成します。Terraform で定義していきます。

resource "google_service_account" "github_action_deploy" {
  account_id   = "github-action-deploy"
  display_name = "github_action_deploy"
  project      = var.project_id
}

resource "google_project_iam_member" "github_action_deploy_roles" {
  for_each = toset([
    .
    .
    (GCPリソース操作に必要な権限)
    .
    .
  ])
  project = var.project_id
  role    = each.value
  member  = "serviceAccount:${google_service_account.github_action_deploy.email}"
}

Workload Identity 連携における pool と provider

ここから Workload Identity 連携を構築していきますが、プールとプロパイダという概念があります。

  • Workload Identity Pool (プール):
    • 外部のIDシステム(例:AWS、Azure, Github)からのアイデンティティを一つにまとめて管理する仕組みです。これにより、複数の外部システムのユーザーやアプリケーションを一元的に扱うことができます。プールは、これらの外部 ID を GoogleCloud のリソースにアクセスできるよう橋渡しする役割を果たします。
    • 一般には、外部アプリの環境(開発環境、ステージング環境、本番環境など)ごとにプールは分けるのが望ましいとされています。
  • Workload Identity Pool Provider (プロバイダー):
    • プール内に存在し、特定の外部 ID プロバイダー(例:AWS IAM、Azure AD)と GoogleCloud を接続する設定(認証方法)を管理します。プロバイダーは、外部システムの認証情報を GoogleCloud が理解できる形式に変換(属性マッピング)し、適切な権限を割り当てる手助けをします。
    • 各プールには、複数のプロバイダーを設定できます。

例えると、プール (Pool) は「空港」のようなものです。様々な航空会社(プロバイダー)からの乗客(認証要求)を受け入れます。

プロバイダー (Provider) は「特定の航空会社」のようなものです。その航空会社特有のチケット(認証情報)を持つ乗客を確認し、適切に処理します。

この構造により、複数の外部IDソースを柔軟に管理し、それぞれに対して細かな設定を行うことが可能になります。

では、プールとプロパイダを定義します。

resource "google_iam_workload_identity_pool" "github_pool" {
  provider                  = google-beta
  project                   = var.project_id
  workload_identity_pool_id = "github-pool"
  display_name              = "GitHub Pool"
}

resource "google_iam_workload_identity_pool_provider" "github_provider" {
  provider                           = google-beta
  project                            = var.project_id
  workload_identity_pool_id          = google_iam_workload_identity_pool.github_pool.workload_identity_pool_id
  workload_identity_pool_provider_id = "github-provider"
  display_name                       = "GitHub Provider"
  attribute_condition                = "assertion.repository_owner_id == 'xxxxxxxxx'"
  attribute_mapping = {
    "google.subject"       = "assertion.sub"
    "attribute.actor"      = "assertion.actor"
    "attribute.aud"        = "assertion.aud"
    "attribute.repository" = "assertion.repository"
  }
  oidc {
    issuer_uri = "https://token.actions.githubusercontent.com"
  }
}

プールとプロバイダを作成し、プールにプロバイダを紐づけています。

プロバイダでは、属性のマッピングと、認証方法として OIDC を指定しています。

また、attribute_condition を設定し、特定の組織でのみ利用可能に制限しています。
(repository_owner_id の値は https://api.github.com/users/<user_or_org_name> の id を指定)

参考: GitHub または他のマルチテナント ID プロバイダと連携する場合に属性条件を使用する - Google Cloud

そして最後に、デプロイ用のサービスアカウントとこれらを紐づけます。

resource "google_service_account_iam_member" "github_action_deploy_workload_identity" {
  service_account_id = google_service_account.github_action_deploy.name
  role               = "roles/iam.workloadIdentityUser"
  member             = "principalSet://iam.googleapis.com/${google_iam_workload_identity_pool.github_pool.name}/attribute.repository/${var.github_org}/${var.github_repo}"
}

デプロイ用のサービスアカウントは、先ほど作成した Workload Identity Pool と Provider を介して、GitHub Actions からの認証を受け付けるように設定されます。

この設定により、GitHub Actions のワークフローが Google Cloud のリソースにアクセスする際、このサービスアカウントの権限を使用することができます。

具体的には、google_service_account_iam_member リソースを使用して、以下の設定を行っています:

  1. service_account_id: デプロイ用に作成したサービスアカウントを指定します。
  2. role: "roles/iam.workloadIdentityUser" を指定することで、外部IDシステム(この場合はGitHub)からこのサービスアカウントを使用する権限を付与します。
  3. member: Workload Identity Pool と、GitHubリポジトリを指定します。これにより、特定の GitHub リポジトリからの認証要求のみを受け付けるよう制限します。

この設定が完了すると、指定された GitHub リポジトリの Actions ワークフローから、Google Cloud のリソースに安全にアクセスできるようになります。ワークフロー内では、OpenID Connect (OIDC) トークンを使用して認証を行い、このサービスアカウントの権限で Google Cloud API を呼び出すことが可能になります。

GithubActions ワークフロー

最後のステップとして、GitHub Actions のワークフローを定義します。ワークフロー内では、公式から提供されている google-github-actions/auth アクションを使用して認証を行い、その後 Google Cloud CLI や他の関連アクションを使用してデプロイやその他の操作を実行できます。

- name: Authenticate to Google Cloud
  uses: google-github-actions/auth@v2
  with:
    workload_identity_provider: ${{ secrets.GCP_WORKLOAD_IDENTITY_PROVIDER }}
    service_account: ${{ secrets.GCP_SERVICE_ACCOUNT }}

ここで渡している workload_identity_provider は、プロジェクト番号、プール名、プロバイダー名を含む、ワークロード ID プロバイダーの完全な識別子です。コンソール画面から取得するか、以下の gcloud コマンドでも取得できます。

gcloud iam workload-identity-pools providers describe <プロパイダ名 今回の例では github-provider> \
--workload-identity-pool="<プール名 今回の例では github-pool>" \
--location="global" \
--format="value(name)"

# -> projects/123456789/locations/global/workloadIdentityPools/github-pool/providers/github-provider

https://cloud.google.com/sdk/gcloud/reference/iam/workload-identity-pools/providers/describe

service_account は、デプロイ用に作成したサービスアカウント(email)です。

このように、Workload Identity 連携を使用することで、サービスアカウントのキーファイルを管理する必要がなくなります。GithubActions でデプロイを実施する際に、よりセキュアな CI/CD パイプラインを構築できます。

まとめ

Workload Identity 連携は、GCP 外のアプリケーションから GCP リソースを安全に操作する革新的な方法です。本記事では、GithubActions から GCP リソースをデプロイする過程を通じて、その実装方法を解説しました。

この技術を活用することで、サービスアカウントキーの管理が不要となり、セキュリティが向上し、運用負荷が大幅に軽減されます。より安全で効率的な CI/CD パイプラインや外部アプリケーション連携を構築できますので、是非試してみてください。