Workforce Identity Federationとは?Workloadとの違いを整理する

「Workforce Identity Federation」「People, Not Workloads」の文字。中央の破線で左右に分かれ、左は「Organization」の建物の中に ID バッジが積まれた「Workforce Pool」のトレイ、右は「Project」の箱の中にサーバーと歯車が入った「Workload Pool」のトレイが置かれ、2 つはつながっていない図 認証・IAM

はじめに

Workforce Identity Federation を使うと、Entra ID などの社内 IdP のアカウントのまま Google Cloud を使えます。Google アカウントを作る必要はありません。IdP(Identity Provider)は、ユーザーの ID を管理してログインを受け持つサービスです。

社内の IdP で管理しているユーザーに Google Cloud を使わせる方法を確かめるため、個人の検証環境で構築しました。名前のよく似た Workload Identity Federation との違いが、最初は私もあいまいでした。

本記事では、Workload Identity Federation との違いを中心に概念を整理します。そのうえで、最初の一歩になる Workforce Identity Pool を Terraform で作るところまでを紹介します。IdP と接続してサインインするところは、続きの記事で扱います。

本記事のまとめ

  • Workforce Identity Federation は「人」の ID を、Workload Identity Federation は「処理」の ID を扱う仕組みである。
  • Workforce Identity Pool は組織に作るリソースで、プロジェクトには作れない。
  • 作成には組織レベルの roles/iam.workforcePoolAdmin が必要である。組織の閲覧ロールでは Pool の一覧すら見られず、組織管理者のロールにも Pool の権限は含まれない。
  • Pool ID は Google Cloud 全体で一意である。Essential Contacts は、Workforce Identity Federation のユーザーへ重要な通知を届けるために登録が要る。
Google Cloud コンソールの Workforce Identity 連携の一覧。Entra ID PoC という Workforce プールの下に Microsoft Entra ID の OIDC プロバイダが 1 つ並び、IAM プリンシパルの Pool ID は <POOL-ID> に伏せてある
組織に作成した Workforce Identity Pool と、その下にぶら下がる Provider。IAM プリンシパル列の Pool ID は <POOL-ID> に伏せた

Workforce Identity Federation とは

Workforce Identity Federation は、外部の IdP で認証した社員やパートナーが、シングルサインオン(SSO)で Google Cloud を使うための仕組みです。Google Cloud のコンソールでは「Workforce Identity 連携」と表示されます。

公式ドキュメントによると、ユーザーのアカウントは Google Cloud 側に保存されません。そのため、IdP から Google アカウントへ ID を同期するツール(Google Cloud Directory Sync など)が要りません。

サインインしたユーザーは、「コンソール(連携)」という専用のコンソールから Google Cloud を操作します。使えるのは Workforce Identity Federation に対応したプロダクトだけで、通常のコンソールとは画面も異なります。対応している IdP は、OIDC か SAML 2.0 に対応したもの(Entra ID、Okta など)です。

Workload Identity Federation との違い

2 つの違いは、ID の持ち主です。Workforce Identity Federation は人、Workload Identity Federation は CI や他クラウドのサーバーなどの処理を対象にします。

項目Workforce Identity FederationWorkload Identity Federation
対象社員・パートナーなどの人CI/CD や他クラウドの処理
Pool を置く場所組織プロジェクト
使い方人がブラウザでサインインし、コンソール(連携)や gcloud を使うプログラムが API を呼び出す
権限の付け方Pool 内のユーザーやグループに、IAM でロールを付けるリソースに直接付けるか、サービスアカウントの権限を借りる

私の環境では、GitHub Actions から Terraform を実行するために Workload Identity Federation を使っています。次がその Pool の定義で、置き場所はプロジェクトです。

resource "google_iam_workload_identity_pool" "github_pool" {
  project                   = var.project_id
  workload_identity_pool_id = "github-actions-pool"
  display_name              = "GitHub Actions Pool"
}

この CI では、特定のリポジトリからのリクエストだけに、サービスアカウントの権限を借りることを許可しています。なお公式ドキュメントでは、サービスアカウントを介さずにリソースへ直接権限を付ける方法も推奨されています。後で紹介する Workforce Identity Pool の定義では、プロジェクトではなく組織を指定します。

プロジェクトの Workload Identity 連携の画面。GitHub Actions Pool と、その下に GitHub Actions Provider が OIDC で有効になっている
Workload Identity 連携はプロジェクト配下の別メニューにある。Pool ID は本文の Terraform 定義と同じ汎用名で、Provider ID も環境を特定しないため、伏せた箇所は無い

Workforce Identity Pool・Provider・principal の関係

Workforce Identity Federation は 3 つの要素で組み立てます。Pool がユーザーの入れ物、Provider が信頼する IdP、principal が IAM で権限を付ける相手の書き方です。

要素役割
Workforce Identity Pool外部の ID をまとめる入れ物。組織に作り、Pool 単位や Pool 内の一部にまとめて権限を付けられる
Workforce Identity Pool ProviderPool がどの IdP を信頼するかを定義する。1 つの Pool に複数の IdP を登録できる
principalIAM でロールを付けるときの相手の表し方。個人やグループを Pool ID 付きで指定する

principal は次の形式で書きます。どちらも Pool ID が含まれるので、Pool を作らないと権限を付けられません。

# 1 人のユーザー
principal://iam.googleapis.com/locations/global/workforcePools/POOL_ID/subject/SUBJECT

# グループに属する全員
principalSet://iam.googleapis.com/locations/global/workforcePools/POOL_ID/group/GROUP_ID

作業の順番にも注意が必要です。IdP 側の設定には、Pool ID と Provider ID を含む URL を登録します。そのため、Pool を作って ID を決める → IdP 側を設定する → Provider を作る、の順で進めました。

Workforce プールの詳細画面。プール ID と IAM プリンシパルは <POOL-ID> に伏せてあり、下部のプロバイダ表に Microsoft Entra ID が 1 行並んでいる
Pool の詳細画面。IAM プリンシパルは principalSet://iam.googleapis.com/locations/global/workforcePools/<POOL-ID>/* の形になる。Pool ID は 3 箇所とも伏せた

Workforce Identity Pool を作る前に用意するもの

作る前に用意するものは 3 つあります。組織リソース、組織レベルの roles/iam.workforcePoolAdmin、Essential Contacts の 3 つです。

組織リソース

Workforce Identity Pool は組織に作るリソースです。組織リソースは、Google Cloud でプロジェクトやフォルダを束ねる最上位の単位を指します。私の環境には Cloud Identity で作った組織がすでにあったので、そのまま使いました。組織が無い場合は、先に組織を用意する必要があります。

組織レベルの権限

Pool の作成には、組織に対する roles/iam.workforcePoolAdmin が必要です。私は作成を CI のサービスアカウントに任せ、このロールを付けました。閲覧用には、取得と一覧だけを含む roles/iam.workforcePoolViewer を運用グループに付けて、作成と閲覧で権限を分けています。

Essential Contacts

Essential Contacts は、Google Cloud から組織への重要な通知を受け取る連絡先です。Cloud Identity のユーザーには Cloud Identity のメールアドレスで連絡が届きます。Workforce Identity Federation のユーザーへの連絡は Essential Contacts 経由になります。コンソールで Pool を作ると、Legal と Suspension のカテゴリを登録するよう求めるバナーが出ます。私は Terraform で、この 2 つに Security を加えた 3 カテゴリを登録しました。

組織の Essential Contacts 画面。停止・セキュリティ・法務の 3 カテゴリに連絡先が入り、技術・課金・サービスの更新情報は「なし」と警告が出ている。連絡先は <CONTACT-EMAIL> に伏せてある
Suspension・Security・Legal の 3 カテゴリに連絡先を登録した状態。宛先のメールアドレス 3 箇所は <CONTACT-EMAIL> に伏せた

Terraform で Workforce Identity Pool を作る

Pool は google_iam_workforce_pool リソース 1 つで作れます。Workload Identity Pool との一番の違いは、project ではなく parent に組織を指定する点です。

resource "google_iam_workforce_pool" "entra_poc" {
  parent            = "organizations/${var.organization_id}"
  location          = "global"
  workforce_pool_id = "entra-poc-example-com"
  display_name      = "Entra ID PoC"

  # サインインしたセッションの有効期間(900s〜43200s)
  session_duration = "3600s"

  # Pool ID は再取得できない可能性があるため削除を禁止する
  deletion_policy = "PREVENT"

  # 同じ apply でロールを付けてから作成する
  depends_on = [google_organization_iam_member.ci_workforce_pool_admin]
}

設定値のうち、判断が必要だったのは次の 3 つです。

  • workforce_pool_id: Google Cloud 全体で一意で、作る前に空きを確認する手段が無い。衝突を避けるため、組織のドメイン名を ID に含めた。人が読む名前は、一意の制約が無い display_name に書く。
  • session_duration: 公式ドキュメントでは 900 秒から 43,200 秒の範囲で、既定は 1 時間である。既定と同じ 3600s にした。
  • deletion_policy: 誤って destroy しないよう PREVENT にした。

新規リソースの 2 件だけに絞った terraform plan で、追加のみ(2 to add, 0 to change, 0 to destroy)であることを確認してから apply しました。

作成した Pool は、この後 IdP を Provider として登録する土台になります。

Workforce プロバイダの詳細画面。属性のマッピングで google.subject に assertion.oid、google.groups に assertion.groups が割り当てられている。テナント ID・クライアント ID・シークレットのサムプリントは伏せてある
作成した Pool の下に Provider を登録した状態。属性のマッピングなど Provider 側の設定は続きの記事で扱う。Pool ID・テナント ID・クライアント ID・シークレットのサムプリントは伏せた

Workforce Identity Pool の作成でつまずいた点

つまずいたのは権限と Essential Contacts の宛先の 2 点です。どちらも組織レベルの権限や設定が原因で、エラーが出るまで気づけませんでした。

組織のロールがあっても Pool の一覧が見られない

組織の閲覧ロール(roles/resourcemanager.organizationViewer)を持つアカウントで試しました。gcloud iam workforce-pools list を実行すると次のエラーになりました。コンソールの Workforce Identity Pools 画面も開けませんでした。

Permission 'iam.workforcePools.list' denied

組織の閲覧ロールだけでなく、組織管理者のロール(roles/resourcemanager.organizationAdmin)にも Pool の権限は含まれていません。作成する主体には workforcePoolAdmin、見るだけの人には workforcePoolViewer を別に付けてください。

Essential Contacts の宛先が組織ポリシーで弾かれる

最初は個人の Gmail アドレスを宛先にしたところ、apply が次のエラーで失敗しました。

Error 400: Contact email address <個人の Gmail アドレス> doesn't have
a domain that matches the Allowed Contact Domains org policy.

原因は、組織ポリシー essentialcontacts.allowedContactDomains が組織のドメインだけを許可していたことです。組織ポリシーは、組織全体に効く設定の制約を指します。私が設定した覚えは無く、組織を作った時期と更新日時が一致していたので、新しい組織に最初から入っているものと見られます。

組織のドメインのアドレスで、実際に受信できるよう転送設定があるものを宛先にして解決しました。組織レベルのリソースを足す前に、gcloud org-policies list --organization=ORGANIZATION_ID で制約を確認しておくことをおすすめします。

まとめ

Workforce Identity Federation は、社内 IdP の ID のまま Google Cloud を使うための、人向けの仕組みです。処理向けの Workload Identity Federation とは、対象も Pool の置き場所も違います。

  • 最初に作るのは組織の Workforce Identity Pool である。Pool ID は Google Cloud 全体で一意なので、衝突しない名前を先に決める。
  • 作成には組織レベルの workforcePoolAdmin が必要で、組織管理者や組織の閲覧ロールでは足りない。
  • Essential Contacts は組織ポリシーで宛先のドメインが制限されていることがある。登録前に確認する。

セッションの有効期間の範囲、ロールに含まれる権限、コンソールの画面構成は変わることがあります。進める前に公式ドキュメントで最新を確認してください。

次は Pool に IdP を Provider として登録し、実際にサインインします。Entra ID を使った手順は続きの記事で紹介します。