はじめに
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 のユーザーへ重要な通知を届けるために登録が要る。

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 Federation | Workload 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 の定義では、プロジェクトではなく組織を指定します。

Workforce Identity Pool・Provider・principal の関係
Workforce Identity Federation は 3 つの要素で組み立てます。Pool がユーザーの入れ物、Provider が信頼する IdP、principal が IAM で権限を付ける相手の書き方です。
| 要素 | 役割 |
| Workforce Identity Pool | 外部の ID をまとめる入れ物。組織に作り、Pool 単位や Pool 内の一部にまとめて権限を付けられる |
| Workforce Identity Pool Provider | Pool がどの IdP を信頼するかを定義する。1 つの Pool に複数の IdP を登録できる |
| principal | IAM でロールを付けるときの相手の表し方。個人やグループを 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 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 カテゴリを登録しました。

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 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 を使った手順は続きの記事で紹介します。

