Workforce Identity Federationの仕組み|認証と認可は別で動く

「Workforce Identity Federation」「How It Works」の文字。右側に上から下へ、Entra IDの発行機からgroups claimのカードが落ち、IAPの門で緑と赤のレーンに分かれ、下にIAMのルールブックと空の引き出しが並ぶ図 認証・IAM

サインインできても、入れるかはGoogle Cloudが別に決めている

Microsoft Entra ID のアカウントで、Google Cloud 上のアプリを開けるようにできます。ただし「Entra ID でサインインできた」は「アプリを見られる」を意味しません。

認証と認可が、別のシステムで動いているからです。私はこの構成を Terraform で組んだあと、仕組みを人に説明する機会がありました。そこで「どこで誰が判定しているのか」が伝わりにくいと分かったので、整理し直したのがこの記事です。

設定手順ではなく、中で何が起きているかを扱います。

本記事のまとめ

  • 認証は Entra ID、認可は Google Cloud の IAM。判定しているのはアプリではなく IAP(Identity-Aware Proxy。アプリの手前で通すか止めるかを決める Google Cloud の仕組み)である。
  • プールは利用者名簿ではない。Google Cloud 側に利用者もグループも登録しない。
  • 所属グループは保存されず、アクセスのたびにトークンで運ばれてくる。
  • プール ID は後から変えられない。構築前に決めておく必要がある。

入れないときの切り分けは、「Entra IDでサインインは通るのにGoogle Cloudが403|原因はグループ」で扱います。

Cloud Run の「It's running!」画面。リビジョン名とサービス名は黒塗りで <SERVICE-NAME> のラベルに伏せてあり、GCP プロジェクトも塗られている
アプリ側に認証を実装していないので、通ったあとに出るのは Cloud Run の既定ページのまま。サービス名とリビジョン名は伏せた

認証と認可の違い|身分証の提示と、入室許可の判断

認証と認可は、別のシステムが別のタイミングで行っています。この 2 つはよく混ざりますが、担い手が違います。

答える問い例えるなら担い手
認証この人は誰か受付で身分証を見せて本人確認するEntra ID
認可その人はこれを見てよいかどの部屋に入れるかを入館ルールで決めるGoogle Cloud の IAM

大事なのは、身分証そのものに「どの部屋に入れるか」は書かれていないということです。サインインは通ったうえで「権限がありません」と止められることがあります(HTTP 403)。これは故障ではなく、認証と認可が分かれていることの現れです。

この分担には利点があります。パスワード、多要素認証、アカウントの有効と無効は、すべて Entra ID 側の設定がそのまま適用されます。Google Cloud 側は認証に関与せず、利用者のパスワードを持ちません。

この橋渡しをするのが、Google Cloud の Workforce Identity 連携(Workforce Identity Federation)です。詳しくは Google Cloud の公式ドキュメント 「Workforce Identity 連携の概要」にまとまっています。

この設定は IAP のページではなく、Cloud Run のサービス一覧で対象のサービスを開き、「セキュリティ」タブを選ぶと出ます。

Cloud Run のセキュリティタブ。「認証が必要」が選ばれ、Identity and Access Management と Identity-Aware Proxy の両方にチェックが入っている。下に「IAM と IAP の両方が有効になっている場合は、常に IAP チェックが適用されます」という注記がある
アプリ側にあるのは「認証が必要」という設定だけで、誰を通すかのリストは持たない。サービス名とプロジェクト番号が出ていた上部のヘッダーは切り落とした

登場人物と、それぞれが決めていること

ルールを持つのが IAM、判定するのが IAP です。役割が分かれているので、まず誰が何を決めているかを並べます。

登場人物何を決めているかどこにあるか
Entra IDこの人が本人かどうか。どのグループに所属しているか利用者側のテナント
Workforce Identity 連携(プール)Entra ID から届いた情報を、Google Cloud が扱える形に読み替えるGoogle Cloud 組織
IAPアプリの手前で、通すか止めるかを判定するGoogle Cloud プロジェクト
IAM誰に何を許可するかのルールを保持するGoogle Cloud プロジェクト
アプリ(Cloud Run)—(判定に関与しない)Google Cloud プロジェクト

アプリは「誰が来たか」を知ることはできますが、許否の判断には関わりません。そのためアプリ側に認証の仕組みを実装する必要がありません。既存のアプリをそのまま置けるのが、この構成を選ぶ理由のひとつになります。

この一覧はWorkforce Identity 連携のページで組織を選ぶと出ます。見出しは「Workload Identity プール」と表示されますが、ここに並ぶのは Workforce のプールです。見分けるなら、表示名ではなくログイン URL が auth.cloud.google/signin で始まるかを見てください。

Google Cloud コンソールのプール一覧。プールが 1 つと、その下に Microsoft Entra ID の Provider が 1 つ並ぶだけで、利用者の一覧は無い。プール ID は 2 箇所とも黒塗りで <POOL-ID> のラベルに伏せてある
プールの下に並ぶのは Provider だけで、利用者の一覧はどこにもない。コンソールの見出しは「Workload Identity プール」と出るが、並んでいるのは Workforce のプール。クリックすると拡大できる

Workforce Identityプールに利用者は登録しない

プールは利用者名簿ではありません。ここが一番誤解されるところです。

Google Cloud は Entra ID のアカウントをそのまま理解できません。そこで「Entra ID から来た人を受け入れる窓口」を Google Cloud 側に 1 つ置きます。これが Workforce Identity プールです。プールは「どの Entra ID テナントを信頼するか」を知っているだけです。

中身
プール本体が持つものプール ID、表示名、サインインセッションの有効期間、誤削除防止の設定
プールの下の Provider が持つものどの Entra ID テナントを信頼するか、クライアント ID とシークレット、属性の読み替え規則
プールに登録しないもの利用者とグループ

Google Cloud 側にグループを作る作業は存在しません。グループの実体は Entra ID 側にあり、そこが唯一の正本です。これが、利用者の追加と削除が Entra ID 側の操作だけで済む理由です。同じ名簿を 2 か所に持たないので、二重管理が起きません。

Workload Identityとは別物

名前がよく似た別の機能があり、会話や資料で混ざります。Workforce は人間の利用者、Workload は CI/CD などのマシンが対象です。GitHub Actions から Google Cloud へキーなしで認証する構成は Workload のほうで、この記事で扱うものとは別系統です。

プールIDは後から変えられない

プール ID は Google Cloud 全体で一意で、他の組織を含めて重複できません(公式ドキュメント)。調べた時点では、空きを事前に確認する方法は見つかりませんでした。作成後に ID を変更できないため、変えるなら作り直しになり、Entra ID 側の設定もアクセス許可もすべて再設定になります。

理由は、プール ID がサインイン用の URL と、Entra ID 側に登録する戻り先の URL に埋まるからです。Terraform の出力を見ると、どちらも組み立て規則が決まっています。

サインイン用の URL: https://auth.cloud.google/signin/locations/global/workforcePools/<プール ID>/providers/<Provider ID>?continueUrl=...

Entra ID 側に登録する戻り先の URL: https://auth.cloud.google/signin-callback/locations/global/workforcePools/<プール ID>/providers/<Provider ID>

プール ID を変えると、この 2 つの URL が両方変わります。Entra ID 側の登録も直す必要があるため、命名は構築前にすり合わせておくことをおすすめします。

この画面は、同じ Workforce Identity 連携のページでプールを開き、プロバイダの名前をクリックすると出る「プロバイダの詳細」です。

Workforce Identity プロバイダの詳細画面。表示名・リダイレクト URL・発行元の URI・クライアント ID・レスポンスタイプ・属性のマッピングが並び、利用者の一覧は無い。プール ID、プロバイダ ID、テナント ID、クライアント ID、シークレットのサムプリントは黒塗りでラベルに伏せてある
プロバイダが持つのは「どの IdP を信頼するか」と「どのクレームをどの属性に読み替えるか」だけ。利用者の一覧はどこにもない。識別子は伏せた

アクセス1回で何が起きているか

所属グループは、アクセスのたびに Entra ID から届きます。先に用語を 2 つ決めておきます。

ID トークンは、サインインが成功したときに Entra ID が発行する署名付きの小さなデータです。改変すると署名が合わなくなるため、受け取った側は「確かに Entra ID が発行したもの」と判定できます。

クレームは、その ID トークンに入っている「この利用者はこういう属性を持つ」という申し立て 1 項目です。「主張」という意味の語です。中身はこうなっています(値はすべて架空の例で、実環境のものではありません)。

{
  "iss": "https://login.microsoftonline.com/8f4c2b17-5a93-4d6e-b0c1-7e2d9a84f531/v2.0",
  "aud": "a37d9e42-6c18-4b05-9f73-2e8c41d6b907",
  "iat": 1790880000,
  "exp": 1790883600,
  "oid": "5d2a7c64-91e3-4f80-a6b5-c83f107e9d42",
  "name": "山田 太郎",
  "preferred_username": "taro.yamada@example.com",
  "groups": [
    "2b85f3d1-47ac-4e29-8d60-1f9c53a7b0e8",
    "7e14c9a6-3d58-42b7-95f1-6a0b82dc43fe"
  ]
}

oid は利用者のオブジェクト ID で、テナント内で変わらない識別子です。groups は所属グループのオブジェクト ID の一覧で、表示名ではありません。見てのとおりグループ名も部署名も入っておらず、並んでいるのは ID だけです。

残りは出どころと宛先です。iss が発行元の Entra ID テナント、aud が受け取り手として登録されたクライアント ID、iat と exp が発行時刻と有効期限を表します。

この ID トークンが、アクセスのたびに次の順で運ばれてきます。矢印に振った番号は、このあとの表と同じ番号です。

Workforce Identity 連携でアクセス 1 回に起きる 11 ステップのシーケンス図。利用者、IAP、プール、Entra ID、IAM、アプリの間で認可コードと ID トークンが往復する
アクセス 1 回の流れ。クリックすると拡大できる

各ステップで起きていることは次のとおりです。

#起きていること
1利用者がアプリの URL を開く。IAP が「まだ認証されていない」と判定する
2IAP がサインイン用の URL へ転送する。この URL にプール ID と Provider ID が含まれる
3転送された利用者のブラウザがプールへサインインを要求する。このために専用の OAuth クライアントが必要
4プールが、信頼先として登録された Entra ID テナントへ転送する
5利用者が Entra ID でサインインする。多要素認証などは Entra ID 側の設定に従う
6Entra ID が引換券(認可コード)を、事前登録された戻り先 URL へ返す。トークン自体をブラウザに流す方式は使わない
7プールが、引換券をクライアント ID とクライアントシークレットと引き換えに ID トークンを受け取る
8足りない属性を補うため、Entra ID の別のエンドポイントから得た情報をマージする
9読み替え規則に従って、oid と groups を Google Cloud 側の属性として組み立てる
10IAP が IAM を評価する。届いたグループ一覧と、許可設定に書かれたグループを照合する
11許可ならアプリを表示する。不許可なら 403

#7 がクライアントシークレットを使う箇所です。ここで使うため、シークレットの有効期限が切れると全利用者がこの段階で止まります。IAP 側の設定については Google Cloud の公式ドキュメント 「Workforce Identity 連携で IAP を使用する」に手順があります。

#4 と #5 のあいだで、画面は Microsoft に切り替わります。Google アカウントでログイン済みのブラウザでも、Google を選ぶ画面は出ません。アプリごとに認証元が 1 つに固定されているためです。実際の画面はCloud RunをEntra IDで認証|IAP×Workforce Identity Federationに載せています。

この番号は、入れないときに「どこが切れたか」を指す目印になります。症状と番号の対応は別記事にまとめました。

まとめ

Workforce Identity 連携は、Entra ID が本人確認した結果を毎回トークンで受け取り、Google Cloud の IAM と照合する仕組みです。名簿を持ち合うのではありません。

  • 認証は Entra ID、認可は Google Cloud の IAM。判定しているのはアプリではなく IAP なので、アプリ側に認証を実装しなくてよい。
  • プールに利用者とグループは登録しない。Google Cloud 側にグループを作る作業は存在せず、Entra ID 側が唯一の正本になる。
  • 所属グループは保存されず、アクセスのたびに ID トークンで運ばれてくる。
  • プール ID はサインイン URL と戻り先 URL に埋まるため、後から変えられない。構築前に決めておく。

なお、コンソールの画面構成やタブの名前、プール ID の制約は変わります。実際に設定するときは、最新を公式ドキュメントで確認してください。

ここまでが「正しく動いているときに何が起きているか」です。サインインは通るのに 403 で止まる、あるいは特定の人だけ入れない、という状態になったら、「Entra IDでサインインは通るのにGoogle Cloudが403|原因はグループ」で症状ごとの切り分けを扱っています。