Microsoft Entra PIM for Groups:List assignmentScheduleInstances をアプリケーション権限で取得する方法(403/404対策)

Microsoft Entra PIM for Groups で Microsoft Graph の「List assignmentScheduleInstances」をアプリケーション権限(クライアント資格情報フロー)で呼ぶと、403/404 で詰まることがあります。実はこの API はアプリ権限でも利用でき、いくつかの前提条件を満たすかどうかで結果が大きく変わります。

目次

この記事の前提:何が「動かない」と見えているのか

本記事で扱うのは、次のような状況です。

  • Entra ロール(ディレクトリ ロール)の PIM では、アプリケーション権限で /roleManagement/directory/roleAssignmentScheduleInstances を呼べている。
  • 同じ発想で PIM グループ(Azure AD / Microsoft Entra グループ)の「現在アクティブな割り当て」を取得しようとすると、アプリケーション権限だと失敗し、委任権限(ユーザー トークン)だと成功する。
  • ドキュメントには PrivilegedAssignmentSchedule.Read.AzureADGroup を付ければアプリ権限でも呼べると書かれているのに、実環境では 403/404 や空結果になり「権限が無い」ように見える。

結論:PIM グループでもアプリケーション権限で利用できる

List assignmentScheduleInstances は PIM for Groups(PIM グループ)でもアプリケーション権限で利用できます。ただし、権限設定・トークンの中身・グループ側の状態のいずれかが欠けると、403/404/空配列になって「動かない」と誤解しやすいのが落とし穴です。

チェック観点満たしていないと起きやすい症状まず見るポイント
管理者同意(Admin consent)403 Forbidden(insufficient privileges)API のアクセス許可が「管理者の同意済み」になっているか
トークンが app-only(roles クレーム)になっているか403 / 401、または「権限が入っていない」JWT の roles に必要な権限が入っているか
対象グループが PIM for Groups の管理対象か404 / 空配列(権限エラーに見える)ポータルでグループが PIM の「Groups」に表示されるか
アクティブ割り当てが存在するか200 OK だが value が空ポータルや別 API で割り当てがあるか

まず整理:Entra ロールの PIM と、PIM for Groups は API も権限も別

「どちらも PIM だから同じエンドポイントで取れるはず」と考えると混乱します。実際には、Entra ロールと PIM グループは Microsoft Graph 上で入口が分かれています。

対象代表エンドポイント取得できるもの最小のアプリ権限(例)注意点
Entra ロール(ディレクトリ ロール)のアクティブ割り当てGET /roleManagement/directory/roleAssignmentScheduleInstancesテナント内のアクティブなロール割り当てインスタンスRoleAssignmentSchedule.Read.Directoryフィルター無しでも呼べるが、件数が多い場合は $filter で絞ると運用が楽
PIM for Groups(PIM グループ)のアクティブ割り当てGET /identityGovernance/privilegedAccess/group/assignmentScheduleInstancesグループのメンバー/オーナーのアクティブ割り当てインスタンスPrivilegedAssignmentSchedule.Read.AzureADGroupこの API は $filter が必須(groupId か principalId でスコープする)

特に PIM グループ側は、API の仕様として $filter(eq)で groupId または principalId を必ず指定します。フィルター無しで呼ぶと「アプリ権限がダメなのかも?」ではなく、単に要求条件を満たしていないだけ、というケースがあります。

呼び出しの基本:List assignmentScheduleInstances の正しい URL とフィルター

PIM グループの「現在アクティブな割り当て(スケジュール インスタンス)」を取得する基本形は次の 2 パターンです。

特定グループのアクティブ割り当てを一覧する(groupId で絞る)

GET https://graph.microsoft.com/v1.0/identityGovernance/privilegedAccess/group/assignmentScheduleInstances?$filter=groupId eq '{グループのObjectId}'

特定ユーザー(principal)のアクティブ割り当てを一覧する(principalId で絞る)

GET https://graph.microsoft.com/v1.0/identityGovernance/privilegedAccess/group/assignmentScheduleInstances?$filter=principalId eq '{ユーザーのObjectId}'

ポイントは「ObjectId(GUID)で指定する」ことです。UPN やメール アドレスを入れても一致しないため、結果が空になりやすいです(空配列は正常応答なので、エラーと誤認しがちです)。

前提条件を深掘り:なぜ 403/404 に見えるのか

ここからは、アプリケーション権限で呼ぶときに詰まりやすい 4 つの前提条件を、実務での見落としポイント付きで整理します。

管理者同意(admin consent)が「付与済み」になっている

アプリケーション権限は、追加しただけでは有効化されません。テナント管理者による管理者同意(Grant admin consent)が完了して初めて、クライアント資格情報フローでその権限がトークンに載ります。

  • アプリ登録(App registration)→「API のアクセス許可」
  • Microsoft Graph → アプリケーションのアクセス許可 に PrivilegedAssignmentSchedule.Read.AzureADGroup を追加
  • 画面上部の「管理者の同意を付与」などで、状態が同意済みになることを確認

よくある落とし穴は「権限を追加した後に、トークンを取り直していない」ことです。クライアント資格情報フローのトークンはキャッシュされることがあるため、権限変更後は必ず新しいトークンで再試験します。

トークンが “roles” クレームを持っている(app-only の証拠)

委任権限(delegated)では scp(スコープ)に権限が入るのに対し、アプリケーション権限(app-only)では roles に権限(アプリ ロール)が入ります。見た目が似ていても、トークンの種類が違うと Graph 側の判定も変わります。

確認方法はシンプルで、取得したアクセストークンを JWT デコーダー(例:jwt.ms)で開き、次の点を見ます。

  • roles に PrivilegedAssignmentSchedule.Read.AzureADGroup が含まれている
  • scp だけが入っている場合は「委任トークン」なので、同じ結果にはなりません

「クライアント資格情報フローで取っているはずなのに roles が無い」という場合、典型的には次のどちらかです。

  • scope に https://graph.microsoft.com/.default を指定していない(別リソースのトークンになっている)
  • 管理者同意が完了しておらず、Graph のアプリ ロールが割り当てられていない

対象グループが PIM for Groups の管理対象になっている(オンボード済み)

PIM for Groups は、すべてのグループが自動的に「PIM 管理対象」になっているわけではありません。PIM で管理する対象として有効化(オンボード)されていないと、API で「PIM の割り当て」を探しても見つからず、結果が返らない/404 になるケースがあります。

ポータル側では、一般に次の導線で「Discover groups」から管理対象に取り込む操作を行います。

  • Microsoft Entra admin center → ID Governance → Privileged Identity Management → Groups
  • Discover groups で対象グループを選び、Manage groups を実行

また、API 観点では「明示的なオンボード API」があるわけではなく、割り当て作成やポリシー更新などの操作をきっかけに自動オンボードされます。つまり、一覧系 API を叩く前に、対象グループが “PIM で管理される状態” に入っているかが重要です。

「現在アクティブな割り当て」が本当に存在している

assignmentScheduleInstances は “アクティブな割り当てのインスタンス” を返します。対象ユーザーがそのグループに対して PIM のアクティブ割り当てを持っていない場合、応答は 200 OK でも value が空になります。

  • 「空配列=エラー」ではなく、「今はアクティブが無い」ことを表す正常応答
  • Eligible(資格)だけで、まだ Activate していないユーザーはここに出ないことがある

まずはポータルの PIM(Groups)で Active assignments / Eligible assignments を見て、「アクティブがある前提」が正しいかを確認すると、切り分けが一気に楽になります。

実装例:クライアント資格情報フローでトークン取得→API 呼び出し

ここでは REST だけで再現できる、最小構成の流れを載せます。Graph Explorer は委任トークンになりやすいため、アプリケーション権限の検証には Postman や cURL を使うのが確実です。

アクセストークンを取得する(client credentials)

POST https://login.microsoftonline.com/{tenantId}/oauth2/v2.0/token
Content-Type: application/x-www-form-urlencoded

client_id={clientId}
&client_secret={clientSecret}
&grant_type=client_credentials
&scope=https%3A%2F%2Fgraph.microsoft.com%2F.default

取得した access_token をデコードし、roles に必要な権限が入っていることを確認します。

ユーザーのアクティブ割り当てを取得する(principalId フィルター)

GET https://graph.microsoft.com/v1.0/identityGovernance/privilegedAccess/group/assignmentScheduleInstances?$filter=principalId eq '{userObjectId}'
Authorization: Bearer {access_token}

特定グループのアクティブ割り当てを取得する(groupId フィルター)

GET https://graph.microsoft.com/v1.0/identityGovernance/privilegedAccess/group/assignmentScheduleInstances?$filter=groupId eq '{groupObjectId}'
Authorization: Bearer {access_token}

レスポンスには、accessId(member/owner)や assignmentType(assigned/activated)などが含まれ、アクティブ割り当ての状態把握に使えます。

レスポンス項目の読み方:何が分かるのか

assignmentScheduleInstances の 1 レコードは「いま有効な割り当て」を表すインスタンスです。特に現場でよく見るのは次のプロパティです。

プロパティ意味運用での使いどころ
principalId割り当て対象のユーザー(または principal)の ObjectId誰が有効な権限を持っているかの突合
groupId対象グループの ObjectIdどのグループに対する割り当てか
accessIdmember / owner など、付与される関係「メンバー」か「所有者」かの判定
assignmentTypeassigned(直接割り当て)/ activated(資格の活性化)“常時付与” か “JIT” かを分析
startDateTime / endDateTime有効期間いつからいつまで有効か。期限切れの検知

たとえば「activated」が多いグループは JIT 運用が徹底できている、などの監査観点の指標にもなります。

トラブルシュート:403 / 404 / 空配列 を最短で切り分ける

エラーや空結果のパターンは似ていますが、原因はだいたい決まっています。まずは下の表で “当たり” を付け、確認作業を一直線にします。

症状ありがちな原因確認ポイント対処
401 Unauthorizedトークンが無効 / aud が違う / 期限切れAuthorization ヘッダー、トークン有効期限、audトークンを取り直し、Graph 用(graph.microsoft.com)であることを確認
403 Forbidden管理者同意が未完了、または roles に権限が無いアプリ登録の同意状態、JWT の roles管理者同意→新しいトークンで再試験
404 Not Foundエンドポイントの打ち間違い / グループが PIM 管理対象でない等URL が /identityGovernance/privilegedAccess/group になっているか正しい URL に修正。必要ならグループを PIM 管理対象へ
200 OK だが value が空割り当てが無い / フィルターが一致していないprincipalId/groupId が GUID か、アクティブ割り当てがあるかObjectId を正しく指定。ポータルで Active assignments を確認
400 Bad Request$filter が無い/プロパティが誤りPIM グループ側は $filter 必須groupId または principalId で eq フィルターを付ける

オンボード状態の確認と「管理対象にする」手順

「PIM グループとして管理されているか」は、API の前段で必ず確認したいポイントです。運用で迷わないために、ポータルと API の両面での考え方をまとめます。

ポータルで確認する(最も早い)

  • ID Governance → Privileged Identity Management → Groups に対象グループが表示されるか
  • 表示されない場合は Discover groups から検索し、Manage groups を実行する
  • Dynamic groups やオンプレ同期グループは PIM for Groups の管理対象にできない点も要注意

API での考え方:明示的なオンボード API は無く、操作がトリガーになる

Graph の PIM for Groups では、割り当て作成やポリシー更新などの操作により、必要に応じて自動オンボードが行われます。つまり「一覧を取る前に、少なくとも一度 PIM の管理対象として扱われる状態に入っている」ことが重要です。

手元の検証で「一覧が返らない」場合は、次のような “PIM 側の操作が通るか” を先に確認すると、オンボード未完了の切り分けになります。

  • assignmentSchedules(スケジュール)を一覧できるか
  • policy(ルール)を参照できるか
  • (検証環境なら)テスト用の割り当てスケジュールを 1 件作る

実務で効く小ワザ:原因特定を速くするチェックリスト

最後に、現場で「次の一手」を迷わないためのチェックリストを載せます。作業者が変わっても同じ基準で切り分けできるようになります。

チェック項目推奨アクション判断基準
API のアクセス許可が admin consent 済みポータルで同意状態を確認し、同意後に新トークンで再実行「同意済み」になっている
トークンに roles が入っているJWT をデコードして roles を確認PrivilegedAssignmentSchedule.Read.AzureADGroup が含まれる
対象グループが PIM 管理対象Groups 画面に表示されるか、Discover groups から管理対象にするPIM の Groups に出てくる
フィルター条件が正しいprincipalId / groupId を GUID で指定空配列か、期待通りの value が返る
期待しているのが「アクティブ」か「資格」かEligible と Active を混同しない“今有効” を取りたいなら scheduleInstances が適切

よくある質問

委任権限だと動くのに、アプリ権限だと動かないのはなぜ?

委任権限は「ユーザーの権限+アプリのスコープ」で動き、トークンも scp 中心になります。一方アプリ権限は、管理者がアプリそのものに権限を付与し、トークンは roles で評価されます。どちらのトークンで試しているかが混ざると、同じ API でも結果が変わります。

403 が出るとき、最初に見るべき 1 点は?

まずは「管理者同意が付与済みか」と「トークンの roles に権限が入っているか」です。ここが揃っていない限り、他の切り分けをしても戻ってきます。

200 OK で空配列なのはバグ?

多くの場合は仕様どおりです。アクティブ割り当てが無い、フィルターが一致していない、対象が PIM 管理対象になっていない、のいずれかで起きます。まずはポータルで Active assignments を見て、前提を固めてから API 側を追うと早いです。

まとめ:アプリ権限で “動く形” を作るための最短ルート

  • PIM グループの assignmentScheduleInstances は、アプリケーション権限でも利用できる。
  • ただし admin consent、トークンの roles クレーム、グループの PIM 管理対象化(オンボード)、そして アクティブ割り当ての存在 が揃わないと「動かない」に見える。
  • さらに PIM グループ側は $filter が必須 なので、groupId/principalId を GUID で指定する。

この 4 点をチェックリスト化しておくと、403/404/空配列の迷子から抜け出しやすくなります。

この記事を書いた人

実務の現場で詰まりがちなポイントを地図にするITブログ「IT trip」を運営。Windows/Office(Teams・Excel)からSQL、サーバ運用、ガジェットまで、再現性のある手順と“なぜそうなるか”を丁寧に解説します。読んだらすぐ試せること、そして迷った人の次の一歩が見えることを大切にしています。

コメント

コメントする

目次