Federal Modernization Workbook
Chapter 05 — PIM for Groups and the PRV Groups
A role reaches a person through a PRV group, so whoever controls the group’s members, owners and policy controls the role. That control belongs in a reviewed file, not in the admin center.
The groups behind the plan’s task A2.1, “PRV role-assignable groups hold the eligible assignments,” and the membership that task A3.3 later publishes through access packages. You start with Microsoft’s own PIM for Groups request samples, from the Microsoft Graph documentation, pinned in the repository, and send them unmodified to a fake Graph to see what they do and what they leave out. Then you add a module to examples/privileged-access for the rest: the PRV groups and their member and owner schedules as reviewed JSON, the two PIM policies each group carries, a read of the tenant before any write, findings, a plan with a diff, a dry run unless you pass -Apply, and guards that refuse the changes that lock people in or out. Lab 1 runs on a laptop with no tenant; Lab 2 uses a test tenant. A table at the end maps each output to the federal requirement it supports.
Jump to a slide (18)
Deck · Narrated deck (about 11 minutes, captions) · Script · Captions. Recorded on November 2, 2026 from the approved chapter.
Goal and audience
Goal. By the end of this chapter you can keep the PRV groups as code: one reviewed file says who may be a member or owner of each group, until when, on which ticket, and under which activation policy. From that file the code produces a plan of Graph requests and a diff a reviewer can read, and applies it only when asked. You can say, for each rule, whether it is Microsoft’s contract, Microsoft’s sample, or the program’s own design.
Audience. Developers who build the project’s write path for privileged groups, the identity engineers who own the PRV groups, and the ISSOs who review the changes. You should read PowerShell 7 and JSON, and know what an eligible assignment is. You don’t need a tenant until Lab 2.
What the PRV groups have to hold
Book 04 never assigns a privileged role to a person. It assigns the role to a role-assignable group named PRV-<tier>-<role>[-<scope>], such as PRV-T0-PrivRoleAdmin or PRV-T2-UserAdmin-Finance, so that the tier shows in every review, alert and audit record (Book 04, Chapter 04). Chapter 01 reads those groups and flags a group that holds a role under any other name (PA-INV-03). This chapter writes them.
Two Microsoft features meet in a PRV group, and they are independent of each other.1
- Role-assignable groups. Only a group created with
isAssignableToRoleset totruecan hold a Microsoft Entra role. The property is set at creation and can’t be changed; an existing group can’t be converted. A tenant can have at most 500 of them. Membership must be assigned, never dynamic, and a group can’t be a member. Creating one needs at least Privileged Role Administrator. Changing the credentials of a member or owner needs at least Privileged Authentication Administrator. The feature needs Microsoft Entra ID P1; just-in-time activation through PIM needs P2.2 - PIM for Groups. Just-in-time membership or ownership of a security or Microsoft 365 group, with policies like those for roles: approval, MFA, justification, a maximum activation time. Each group has two policies, one for membership and one for ownership. Any group can be managed except dynamic groups and groups synchronized from on-premises, and it doesn’t have to be role-assignable.3 4
Book 04 uses them together in two ways (Book 04, Chapter 04). For a Microsoft Entra role, the group holds an eligible role assignment and its members are active; the member activates the role, which keeps the activation on the role’s own settings. Learn recommends this pattern for roles with permissions in SharePoint, Exchange or Microsoft Purview, because activating group membership can take significant time to reach them.5 For privilege that isn’t an Entra role (an Azure role, Intune scope, an application), the members are eligible for the group through PIM for Groups and activate their membership. This chapter’s file carries both, as holds: entraRole or holds: azureRole.
In both patterns the group’s own state has to be governed: who is a member or owner, until when, and how membership or ownership is activated. In Graph that is three collections under identityGovernance/privilegedAccess/group, each read with a filter on the group, and one policy per access type:6
| What | Where | Note |
|---|---|---|
| Eligible members and owners | GET /identityGovernance/privilegedAccess/group/eligibilitySchedules?$filter=groupId eq '{id}' |
accessId is member or owner; the filter is required7 |
| Active members and owners | GET .../assignmentSchedules?$filter=groupId eq '{id}' |
assignmentType tells an activation from a standing assignment8 |
| Member and owner policies | GET /policies/roleManagementPolicyAssignments?$filter=scopeId eq '{id}' and scopeType eq 'Group'&$expand=policy($expand=rules) |
roleDefinitionId is member or owner; the policy ID starts with Group_9 |
| A change to a schedule | POST .../eligibilityScheduleRequests or .../assignmentScheduleRequests |
action adminAssign, adminUpdate, adminRemove and others10 11 |
| A change to a policy | PATCH /policies/roleManagementPolicies/{policyId}/rules/{ruleId} |
The rule’s @odata.type must be in the body12 13 |
Three facts from Learn shape the code. Eligible membership doesn’t appear in the group’s members list; only active membership does.14 PIM onboards a group the first time you create a schedule or update its policy, the policy IDs change when it does, and a group can’t be taken back out of PIM.15 And administrators with group management roles, or group owners, can change membership through the groups API and override what PIM set.16 17 So the code reads the tenant before every plan, takes policy IDs from that read, and treats anything it didn’t put there as drift.
The workbook’s outline also names the access packages that grant PRV membership with approval, expiry and review, the plan’s task A3.3. They aren’t built here (research gaps, row 58). The eligibility expiry this chapter sets matters to them: Learn warns that an access package’s expiration must not exceed the PIM group’s own expiry for eligible assignments, or people lose access while entitlement management still shows them assigned.1819
Which cloud, for these calls
For Microsoft 365 GCC (Moderate), every call goes to graph.microsoft.com, the worldwide host, and sign-in to login.microsoftonline.com. GCC High uses graph.microsoft.us and DoD dod-graph.microsoft.us.20 Every PIM for Groups API page read for this chapter lists the global service, US Government L4 and US Government L5 in its national cloud table,21 22 23 and Microsoft Entra ID Governance, which PIM needs, is available in GCC, GCC High and DoD.24 The module takes the cloud from Chapter 01’s table, by name, with no default.
Start with Microsoft’s sample
What Microsoft gives you
Learn has no end-to-end tutorial for PIM for Groups in Microsoft Graph. Its tutorial for roles ends by noting that you can assign an active role to the group and make members eligible through the PIM for Groups APIs, and leaves it there.25 What Microsoft publishes is a set of HTTP requests in the API reference and one how-to:
- Create eligibilityScheduleRequest: an administrator makes a principal eligible (Example 1), or extends an eligibility (Example 2).2627
- Create assignmentScheduleRequest: an administrator assigns active membership for two hours (Example 1), or a user activates an eligible membership (Example 2).2829
- Update rules in PIM by using Microsoft Graph: six rule updates (activation duration, enablement rules, approval, and expiration for eligible and active assignments), with the permission for groups,
RoleManagementPolicy.ReadWrite.AzureADGroup.30
The pinned copy
The requests exist only inside those pages, so the repository pins their source, unmodified, in examples/third_party/graph-pim-for-groups-pages: the three pages from microsoftgraph/microsoft-graph-docs-contrib at commit a693031 (October 30, 2026), retrieved October 30, 2026, with the repository’s licenses (documentation CC BY 4.0, code MIT).31 snapshot.json records each file’s SHA-256, checked against the upstream git blob hashes; a unit test checks them, and the weekly source watch reports new commits to each page. The pages’ permission tables and SDK snippets are include files that aren’t copied; this chapter cites the rendered pages for them.
tests/PimForGroupsSampleHarness.ps1 extracts the http requests from the pinned pages at test time and sends them, as published, to the chapter’s fake Graph, New-PaPgFixtureInvoker. The fake answers the declared reads from tests/fixtures/ch05/tenant.json and checks a schedule request the way Learn says PIM does: a known group, member or owner, a documented action, and under an expiration rule an end within the policy’s maximum.32 It also refuses a schedule that has already ended; that rule is the fake’s own (research gaps, row 57). Nothing is installed, nothing signs in, and nothing leaves the machine.
What it leaves to you
Each row is pinned by a test in the first block of tests/PimForGroups.Tests.ps1, and the example’s side by the second.
| Microsoft’s sample, as published | Why it matters | What examples/privileged-access adds |
|---|---|---|
An adminAssign request with accessId, principalId, groupId, action, scheduleInfo and justification |
— | Kept as the model: every request the plan writes has those fields |
Example 1 is titled an ownership request but sends accessId member |
Copy the example for an owner and you grant membership | accessId comes from the file’s member or owner list, never from a template |
| Says the eligibility expires after two hours; the end is about a day after the start | The comment and the request disagree | The end comes from the file, and the fake checks it against the policy’s maximum |
| Dated 2023: sent today, the fake refuses both admin examples because the schedule has ended | A copied example fails, or worse, gets its dates edited by hand | Start is the run’s time; end is the reviewed endDateTime |
action AdminAssign, while the page documents adminAssign; no ticketInfo |
Case-sensitivity isn’t stated (research gaps, row 51); no ticket ties the grant to a change | Documented values only; ticketInfo from the file, and a Warn for an entry with no ticket (PA-PG-06) |
| No read before the write | A second run grants twice, and nothing removes what the file no longer lists | Reads schedules and policies first; adminUpdate and adminRemove where they differ |
Hard-coded graph.microsoft.com |
Wrong for GCC High and DoD; the GCC High fake refuses it | Host from the cloud table |
Includes a selfActivate request |
A user action, not an administrator’s | The plan makes admin requests only; guard PA-PG-G7 refuses any self* action |
Every rule update targets a DirectoryRole_ policy, and the page says PIM for Groups is beta only |
The page predates v1.0 for groups, and gives no group policy ID | v1.0, with the Group_ policy ID read from roleManagementPolicyAssignments |
| Rule bodies, with a single user among the approvers | — for the shapes; one person as approver is a single point of failure | Same rule shapes; approvers are the tier’s PIM-Approvers-<tier> group (Design guidance) |
The verdict. Keep Microsoft’s request and rule shapes; the plan writes nothing else. Don’t run the samples as published: they are single requests with stale dates and no read of what is already there, and one of them is labeled for the wrong access type.
The code: examples/privileged-access
This chapter adds its own module, powershell/PimGroups/PimGroups.psm1, its own call list, config/calls-ch05.json, the tier policy, config/prv-group-policy.json, and the entry script Invoke-PaPimGroups.ps1. It imports Chapter 01’s module only for the cloud table and changes nothing in it. Notes for developers are in examples/privileged-access/docs/ch05.md.
The desired state
prv-groups.json is the reviewed file. It names the approver group for each tier and lists each PRV group with its ID (absent for a group still to be created), tier, what it holds, and its member and owner entries, each active or eligible, with a principal ID, a name for the diff, a type, an end date and a ticket. Read-PaPrvGroupConfig refuses a name where an object ID belongs, an unknown tier, and a duplicate group.
config/prv-group-policy.json sets the policy for each access type and tier. It is Design guidance: member activation of 4 hours for T0 and 8 for the rest, eligibility of 90, 180, 180 and 365 days, and approval for T0 and T1, from Book 04, Appendix B (Appendix B); owner activation of one hour with approval, from the example in Learn’s PIM deployment plan.33 Two Learn pages differ on the longest activation: the Graph overview says activation is always time-bound for at most eight hours, and the settings page says one to 24.34 35 The code follows the stricter and flags anything over eight hours. Every member and owner policy also selects the authentication context c1, Chapter 03’s activation gate: Book 04 requires it for PIM for Groups as it does for PIM role settings (Book 04, Chapter 10). As in Chapter 04’s role files, the enablement rules then ask for justification and a ticket (justification only for read-only members), not MFA. Learn says to create and enable the context’s Conditional Access policy before PIM selects it; if no policy targets the context, activation falls back to MFA, but not when the policy is off, report-only or excludes the user.36 So, as in Chapter 04, -Apply refuses a plan that selects c1 unless you pass -ActivationGateChecked, a person’s statement that PIM-Activation-c1 is On. Learn says c1 prompts on every activation only if its Conditional Access policy sets sign-in frequency to Every time, and even then a 10-minute window applies across Microsoft Entra roles, Azure resource roles and PIM for Groups.37 Learn’s release notes list that reauthentication as generally available since April 2026, while the PIM deployment plan still marks “Require Conditional Access context” as public preview; the chapter treats it as preview, the stricter reading.38 39
The read and the findings
Get-PaPgTenantState reads the role-assignable groups, the groups named PRV-*, and for each group in the file its schedules and its two policies. Like Chapter 01’s reader, it sends only declared calls, only to the cloud’s own host, and follows every page. Test-PaPrvGroupConfig checks the file before any read, as a pre-merge check; Test-PaPgTenant checks the tenant.
| Rule | Severity | What it flags | Source |
|---|---|---|---|
| PA-PG-01 | Finding | A name that isn’t PRV-<tier>-<role>[-<scope>], or whose tier differs from the group’s |
Design guidance (Book 04, Chapter 04) |
| PA-PG-02 | Finding; Warn; Info | A group that holds an Entra role but isn’t role-assignable (Finding); another PRV group that isn’t (Warn); a group not created yet (Info) | Learn: only role-assignable groups hold roles, and the property can’t be changed;40 role-assignable recommended for sensitive groups41 |
| PA-PG-03 | Finding | A dynamic group, or one synchronized from on-premises | Learn: PIM for Groups can’t manage them42 |
| PA-PG-04 | Warn; Finding | 450 or more role-assignable groups (Warn); 500 (Finding) | Learn: at most 500;43 the Warn threshold is Design guidance |
| PA-PG-05 | Finding | A group as a member or owner, or a service principal made eligible | Learn: no active nesting in a role-assignable group,44 nesting in PIM for Groups not recommended, and service principals can’t be eligible;45 Design guidance to allow no group at all, because an eligible group hides its people from the review |
| PA-PG-06 | Finding; Warn | An entry with no end, or one already ended (Finding); one with no ticket (Warn) | Learn: zero permanently active assignments except emergency accounts;46 Design guidance for eligibility and tickets |
| PA-PG-07 | Finding | Eligible owners with no active owner; any owner on a T0 group | Learn: the last active owner can’t be removed, so an activated owner’s deactivation fails and, after 30 days, PIM stops trying;4748 Design guidance that T0 groups have no owners, since owners manage membership |
| PA-PG-08 | Finding; Warn | A policy rule that differs from the reviewed setting (Finding on T0 and T1 and on any expiration rule, Warn otherwise); activation over 8 hours; an authentication context outside c1 to c99; approval with no approver group; a group approving itself; eligible members activating into an Entra role without approval (Warn) |
Learn: approval recommended for groups that elevate into Entra roles;49 approvers can’t approve their own requests;50 Design guidance for the settings |
| PA-PG-09 | Finding; Warn | A schedule the file doesn’t grant (Finding); a role-assignable or PRV-* group the file doesn’t list (Warn) |
Design guidance: anything outside the file is unreviewed |
Activations, assignmentType activated, aren’t standing state: the code leaves them out of both the findings and the plan.
The plan, the dry run and -Apply
New-PaPimGroupPlan turns the differences into requests, in a fixed order: groups to create, then policy rules, so the rules are in force before anyone is granted, then grants and updates, then removals. Each operation carries its call ID, method, URI, body, its least-privileged permission and one diff line. diff.txt is the diff; plan.json is the exact requests.
Invoke-PaPgPlan is a dry run unless you pass -Apply. With -Apply it refuses to start if any guard fails, or if the plan selects an authentication context and -ActivationGateChecked wasn’t passed; then it sends each request through a declared write call on the cloud’s own host, and stops at the first error. The guards are Design guidance, each tied to a rule above:
| Guard | Refuses |
|---|---|
| PA-PG-G1 | A T0 or T1 policy losing approval, or its approvers |
| PA-PG-G2 | An expiration rule that allows permanent grants, or a grant with no end |
| PA-PG-G3 | A group set as its own approver |
| PA-PG-G4 | Eligible owners with no active owner (Learn’s deactivation trap) |
| PA-PG-G5 | A group as a holder, or an eligible service principal |
| PA-PG-G6 | More removals than -MaxRemovals (default 5), the sign of a wrong or truncated file |
| PA-PG-G7 | A self-service action in the plan |
A group the file lists without an ID becomes a POST /groups with isAssignableToRole true, securityEnabled true and assigned membership; rerun the plan once it exists to add its schedules and policy. Learn’s pages differ on what else such a group needs: the group resource says under isAssignableToRole that visibility must be Hidden and under visibility that role-assignable groups are always Private,51 the Create group example says Private, and one note says a role-assignable group can’t have an owner while another says owners can be delegated.52 53 54 The code sets neither visibility nor owners (research gaps, row 56).
Least privilege per call
| Call | Least-privileged application permission | Delegated role |
|---|---|---|
List groups (isAssignableToRole, PRV-*) |
Group.ReadBasic.All; Learn’s table names Group-NestingSupport.ReadWrite.All as least privileged, a write permission, so the code takes the first read-only one (research gaps, row 52)55 |
— |
| List eligibilitySchedules | PrivilegedEligibilitySchedule.Read.AzureADGroup56 |
Global Reader or Privileged Role Administrator for role-assignable groups |
| List assignmentSchedules | PrivilegedAssignmentSchedule.Read.AzureADGroup57 |
Same |
| List roleManagementPolicyAssignments (groups) | RoleManagementPolicy.Read.AzureADGroup58 |
— |
| Create eligibilityScheduleRequest | PrivilegedEligibilitySchedule.ReadWrite.AzureADGroup59 |
Privileged Role Administrator for role-assignable groups |
| Create assignmentScheduleRequest | PrivilegedAssignmentSchedule.ReadWrite.AzureADGroup60 |
Same |
| Update unifiedRoleManagementPolicyRule (groups) | RoleManagementPolicy.ReadWrite.AzureADGroup61 |
Privileged Role Administrator, per the how-to62 |
| Create group (role-assignable) | Group.Create, and RoleManagement.ReadWrite.Directory to set isAssignableToRole63 64 |
At least Privileged Role Administrator65 |
The read task needs the first four and nothing that ends in ReadWrite. The plan lists the permissions its own operations need, so the app that applies it holds those and no more. Design guidance: create the PRV groups by hand, as a Privileged Role Administrator, and keep RoleManagement.ReadWrite.Directory off the pipeline’s app; the code only plans the creation. One Learn statement needs Lab 2: the role-assignable groups page says managing their membership through Graph needs RoleManagement.ReadWrite.Directory, while the PIM for Groups request pages name only the AzureADGroup permissions (research gaps, row 53).
The tests
Pester 5 under PowerShell 7. This chapter’s are the 40 in tests/PimForGroups.Tests.ps1: 10 for Microsoft’s samples as published, and 30 for the module (calls and permissions, refused calls and hosts, paging with page sizes of 1, 2 and 50, each finding, the plan’s order and its empty result once the tenant matches, the dry run, -Apply against the fake, each guard, and the entry script’s manifest). The kit’s 330 tests pass, with no module, tenant or network.
The commands below send Microsoft’s pinned requests to a fake, and run the example against a fictional tenant served by the same fake. They show what the code does, not that a tenant accepts the same requests. Review the code and the plan, and run Lab 2 in a test tenant, before -Apply touches production.
Lab 1: fixtures, no tenant
You need PowerShell 7.1 or later with Pester 5. Work in examples/privileged-access.
Every command in this lab, in order, from examples/privileged-access. Each step below says what it does and what to look for.
# Step 1: Run Microsoft's samples against the fake
Invoke-Pester -Path tests/PimForGroups.Tests.ps1 -FullNameFilter '*as published*' -Output None -PassThru |
Select-Object PassedCount, FailedCount
# Step 2: Send Learn's Example 1 yourself
Import-Module ./powershell/PimGroups/PimGroups.psm1
. ./tests/PimForGroupsSampleHarness.ps1
$learn = Get-PgLearnRequest -Page eligibility
$learn[0].Title; $learn[0].Body.accessId
(Invoke-PgLearnRequest -Request $learn[0] -Fixture tests/fixtures/ch05/tenant.json -Policy).Status
# Step 3: List the permissions
(Get-PaPgRequiredPermission -Task pim-groups-read).GraphPermissions -join ', '
# Step 4: Plan against the fictional tenant, as a dry run
./Invoke-PaPimGroups.ps1 -Cloud gcc -FixturePath tests/fixtures/ch05/tenant.json `
-DesiredPath tests/fixtures/ch05/inputs/prv-groups.json -AsOf 2026-10-30 -OutputPath out/pim-groups
# Step 5: Read the findings
Get-Content out/pim-groups/findings.json -Raw | ConvertFrom-Json | Format-Table Rule, Severity, Object
# Step 6: Read the diff
Get-Content out/pim-groups/diff.txt
(Get-Content out/pim-groups/plan.json -Raw | ConvertFrom-Json).Permissions -join ', '
# Step 7: See a guard refuse
./Invoke-PaPimGroups.ps1 -Cloud gcc -FixturePath tests/fixtures/ch05/tenant.json `
-DesiredPath tests/fixtures/ch05/inputs/prv-groups.json -AsOf 2026-10-30 -OutputPath out/pim-groups-guard -MaxRemovals 2 -Apply
# Step 8: Apply to the fake
./Invoke-PaPimGroups.ps1 -Cloud gcc -FixturePath tests/fixtures/ch05/tenant.json `
-DesiredPath tests/fixtures/ch05/inputs/prv-groups.json -AsOf 2026-10-30 -OutputPath out/pim-groups-apply -Apply
./Invoke-PaPimGroups.ps1 -Cloud gcc -FixturePath tests/fixtures/ch05/tenant.json `
-DesiredPath tests/fixtures/ch05/inputs/prv-groups.json -AsOf 2026-10-30 -OutputPath out/pim-groups-apply -Apply -ActivationGateChecked
# Step 9: Run the tests
Invoke-Pester -Path tests
# After the steps
Remove-Item -Recurse -Force outRun Microsoft’s samples against the fake:
Invoke-Pester -Path tests/PimForGroups.Tests.ps1 -FullNameFilter '*as published*' -Output None -PassThru | Select-Object PassedCount, FailedCountWhat the terminal shows, run on the kit’s fixtures (the same output as text) PassedCount 10,FailedCount 0.Send Learn’s Example 1 yourself:
Import-Module ./powershell/PimGroups/PimGroups.psm1 . ./tests/PimForGroupsSampleHarness.ps1 $learn = Get-PgLearnRequest -Page eligibility $learn[0].Title; $learn[0].Body.accessId (Invoke-PgLearnRequest -Request $learn[0] -Fixture tests/fixtures/ch05/tenant.json -Policy).StatusWhat the terminal shows, run on the kit’s fixtures (the same output as text) Example 1: An admin creates an eligible group ownership request for a principal, thenmember, then400 Bad Request from the fake: the schedule ended at 2023-02-07T19:56:00.0000000Z, before the fake's clock.List the permissions:
(Get-PaPgRequiredPermission -Task pim-groups-read).GraphPermissions -join ', 'What the terminal shows, run on the kit’s fixtures (the same output as text) Group.ReadBasic.All, PrivilegedAssignmentSchedule.Read.AzureADGroup, PrivilegedEligibilitySchedule.Read.AzureADGroup, RoleManagementPolicy.Read.AzureADGroup. Nothing ends inReadWrite.Plan against the fictional tenant, as a dry run:
./Invoke-PaPimGroups.ps1 -Cloud gcc -FixturePath tests/fixtures/ch05/tenant.json ` -DesiredPath tests/fixtures/ch05/inputs/prv-groups.json -AsOf 2026-10-30 -OutputPath out/pim-groupsPIM for Groups: 11 Finding, 3 Warn, 0 Info Plan: 10 change(s) (3 assignment, 2 eligibility, 5 policy rule) Guards: all passed Activation gate: the plan selects an authentication context; -Apply also needs -ActivationGateChecked Dry run: nothing sent. Review diff.txt and plan.json, then rerun with -Apply Written to out/pim-groups (manifest.json lists every request and file hash)What the terminal shows, run on the kit’s fixtures (the same output as text) Read the findings:
Get-Content out/pim-groups/findings.json -Raw | ConvertFrom-Json | Format-Table Rule, Severity, ObjectWhat the terminal shows, run on the kit’s fixtures (the same output as text) On
PRV-T0-PrivRoleAdmin: a permanent active member,ben.ops, whom the file doesn’t grant (PA-PG-06 and PA-PG-09); an eligible owner,cara.cloud, with no active owner (PA-PG-07 and PA-PG-09); and a member policy that activates without approval, for 8 hours instead of 4, and with MFA instead of the authentication contextc1(four PA-PG-08: the duration, the enablement rules, the context and the approval). Every other policy in the fixture already selectsc1. OnPRV-T1-AzureOwner-SubWorkload: the groupHelpdesk-Admins-Legacynested as an eligible member (PA-PG-05 and PA-PG-09), an owner policy that doesn’t require eligibility to expire (PA-PG-08), and a Warn because the group isn’t role-assignable (PA-PG-02). Two Warns for groups the file doesn’t list (PA-PG-09). Cara’s activated membership of the Azure group isn’t reported: it’s an activation, not standing state.Read the diff:
Get-Content out/pim-groups/diff.txt (Get-Content out/pim-groups/plan.json -Raw | ConvertFrom-Json).Permissions -join ', 'What the terminal shows, run on the kit’s fixtures (the same output as text) Five policy rule changes (
~), three of them the member policy ofPRV-T0-PrivRoleAdminmoving from MFA toc1, Eve’s membership extended from December 31 to April 28 and Ben granted membership ofPRV-T1-ExchangeAdminon CHG-1005, then three removals (-). The plan needsPrivilegedAssignmentSchedule.ReadWrite.AzureADGroup, PrivilegedEligibilitySchedule.ReadWrite.AzureADGroup, RoleManagementPolicy.ReadWrite.AzureADGroup.See a guard refuse:
./Invoke-PaPimGroups.ps1 -Cloud gcc -FixturePath tests/fixtures/ch05/tenant.json ` -DesiredPath tests/fixtures/ch05/inputs/prv-groups.json -AsOf 2026-10-30 -OutputPath out/pim-groups-guard -MaxRemovals 2 -ApplyWhat the terminal shows, run on the kit’s fixtures (the same output as text) Refusing to apply: PA-PG-G6: 3 removals is more than 2; review them and rerun with a higher -MaxRemovals. Nothing is sent.Apply to the fake:
./Invoke-PaPimGroups.ps1 -Cloud gcc -FixturePath tests/fixtures/ch05/tenant.json ` -DesiredPath tests/fixtures/ch05/inputs/prv-groups.json -AsOf 2026-10-30 -OutputPath out/pim-groups-apply -Apply ./Invoke-PaPimGroups.ps1 -Cloud gcc -FixturePath tests/fixtures/ch05/tenant.json ` -DesiredPath tests/fixtures/ch05/inputs/prv-groups.json -AsOf 2026-10-30 -OutputPath out/pim-groups-apply -Apply -ActivationGateCheckedWhat the terminal shows, run on the kit’s fixtures (the same output as text) The first command stops before any write:
The plan sets an authentication context: confirm its Conditional Access policy is On (Chapter 03), then pass -ActivationGateChecked. The second prints the same first three lines, thenApplied: 10 sent, 0 failed. The fake records the requests and doesn’t change its tenant.Run the tests:
Invoke-Pester -Path testsWhat the terminal shows, run on the kit’s fixtures (the same output as text)
Expected result: 330 tests passing, and each row of the gap table seen with your own eyes.
When you’re done, delete out:
Remove-Item -Recurse -Force outLab 2: test tenant
Use a test tenant in the worldwide or GCC cloud with Microsoft Entra ID P2 or Governance licenses and fictional people, never production. The lab changes PIM settings and group membership, so it ends by removing what it made. Learn says a group can’t be taken back out of PIM once onboarded,66 so use groups made for the lab. Work in examples/privileged-access. You’ll replace: <tenant-id> (the test tenant’s ID), <reader-app-id>, <writer-app-id> and <thumbprint> (the two apps from step 2 and the certificate’s thumbprint; if each app has its own certificate, use its thumbprint), <lab-group-id> and <approvers-group-id> (the groups from step 1), <user1-object-id>, <user1-upn>, <user2-object-id> and <user2-upn> (the two test users), <end-date-1> and <end-date-2> (their end dates, as yyyy-MM-dd, within 180 days) and <ticket-1> and <ticket-2>.
Every command in this lab, in order, from examples/privileged-access. Each step below says what it does and what to look for.
# Step 1: Make the lab groups by hand
@'
{
"approverGroups": { "T1": "<approvers-group-id>" },
"groups": [
{
"displayName": "PRV-T1-LabTest",
"id": "<lab-group-id>",
"tier": "T1",
"holds": "entraRole",
"member": {
"active": [],
"eligible": [
{ "principalId": "<user1-object-id>", "principalName": "<user1-upn>", "principalType": "user", "endDateTime": "<end-date-1>T00:00:00Z", "ticket": "<ticket-1>" },
{ "principalId": "<user2-object-id>", "principalName": "<user2-upn>", "principalType": "user", "endDateTime": "<end-date-2>T00:00:00Z", "ticket": "<ticket-2>" }
]
},
"owner": { "active": [], "eligible": [] }
}
]
}
'@ | Set-Content prv-groups.json
# Step 3: Plan as the reader
Connect-MgGraph -Environment Global -TenantId <tenant-id> -ClientId <reader-app-id> -CertificateThumbprint <thumbprint>
./Invoke-PaPimGroups.ps1 -Cloud gcc -DesiredPath prv-groups.json -OutputPath out/pim-groups-test -TenantId <tenant-id>
# Step 3: Plan as the reader
Get-Content out/pim-groups-test/findings.json -Raw | ConvertFrom-Json | Format-Table Rule, Severity, Object
Get-Content out/pim-groups-test/diff.txt
# Step 4: Apply as the writer
Connect-MgGraph -Environment Global -TenantId <tenant-id> -ClientId <writer-app-id> -CertificateThumbprint <thumbprint>
./Invoke-PaPimGroups.ps1 -Cloud gcc -DesiredPath prv-groups.json -OutputPath out/pim-groups-test -TenantId <tenant-id> -Apply -ActivationGateChecked
# Step 5: Rerun the plan
./Invoke-PaPimGroups.ps1 -Cloud gcc -DesiredPath prv-groups.json -OutputPath out/pim-groups-test -TenantId <tenant-id>
# Step 5: Rerun the plan
$d = Get-Content prv-groups.json -Raw | ConvertFrom-Json
$d.groups[0].member.eligible = @($d.groups[0].member.eligible | Select-Object -First 1)
$d | ConvertTo-Json -Depth 6 | Set-Content prv-groups.json
./Invoke-PaPimGroups.ps1 -Cloud gcc -DesiredPath prv-groups.json -OutputPath out/pim-groups-test -TenantId <tenant-id> -Apply
# Step 6: Back it out
$d = Get-Content prv-groups.json -Raw | ConvertFrom-Json
$d.groups[0].member.active = @(); $d.groups[0].member.eligible = @()
$d | ConvertTo-Json -Depth 6 | Set-Content prv-groups.json
./Invoke-PaPimGroups.ps1 -Cloud gcc -DesiredPath prv-groups.json -OutputPath out/pim-groups-test -TenantId <tenant-id> -Apply
# Step 6: Back it out
Remove-Item -Recurse -Force out/pim-groups-testMake the lab groups by hand. As a Privileged Role Administrator, create a role-assignable security group
PRV-T1-LabTestand a security groupPIM-Approvers-T1with two test approvers, as Learn’s procedure describes.67 Put their IDs, and two test users with end dates within 180 days and tickets, in your ownprv-groups.json, in the shape oftests/fixtures/ch05/inputs/prv-groups.json:@' { "approverGroups": { "T1": "<approvers-group-id>" }, "groups": [ { "displayName": "PRV-T1-LabTest", "id": "<lab-group-id>", "tier": "T1", "holds": "entraRole", "member": { "active": [], "eligible": [ { "principalId": "<user1-object-id>", "principalName": "<user1-upn>", "principalType": "user", "endDateTime": "<end-date-1>T00:00:00Z", "ticket": "<ticket-1>" }, { "principalId": "<user2-object-id>", "principalName": "<user2-upn>", "principalType": "user", "endDateTime": "<end-date-2>T00:00:00Z", "ticket": "<ticket-2>" } ] }, "owner": { "active": [], "eligible": [] } } ] } '@ | Set-Content prv-groups.jsonRegister two apps with certificates. The reader gets the four permissions from Lab 1, step 3. The writer gets those four and the three from Lab 1, step 6. Grant admin consent. Nothing else. For each app:
- Open Entra ID > App registrations > New registration, name the app and select Register.
- In the app, open Certificates & secrets > Certificates > Upload certificate and upload the certificate’s public key.
- Open API permissions > Add a permission > Microsoft Graph > Application permissions and select
Group.ReadBasic.All,PrivilegedAssignmentSchedule.Read.AzureADGroup,PrivilegedEligibilitySchedule.Read.AzureADGroupandRoleManagementPolicy.Read.AzureADGroup; for the writer, alsoPrivilegedAssignmentSchedule.ReadWrite.AzureADGroup,PrivilegedEligibilitySchedule.ReadWrite.AzureADGroupandRoleManagementPolicy.ReadWrite.AzureADGroup. Select Add permissions, then Grant admin consent for your tenant.
Plan as the reader:
Connect-MgGraph -Environment Global -TenantId <tenant-id> -ClientId <reader-app-id> -CertificateThumbprint <thumbprint> ./Invoke-PaPimGroups.ps1 -Cloud gcc -DesiredPath prv-groups.json -OutputPath out/pim-groups-test -TenantId <tenant-id>Check two things in the run: the group rows carry
isAssignableToRole(research gaps, row 52), and no PA-PG-08 Warn says a policy wasn’t read. The plan should show the policy rules and two grants.Get-Content out/pim-groups-test/findings.json -Raw | ConvertFrom-Json | Format-Table Rule, Severity, Object Get-Content out/pim-groups-test/diff.txtApply as the writer. Review
diff.txt. The lab group’s policies selectc1, so first confirm that the test tenant’sPIM-Activation-c1policy is On (Chapter 03, Lab 2);-ActivationGateCheckedis your statement that it is. Then sign in as the writer and apply:Connect-MgGraph -Environment Global -TenantId <tenant-id> -ClientId <writer-app-id> -CertificateThumbprint <thumbprint> ./Invoke-PaPimGroups.ps1 -Cloud gcc -DesiredPath prv-groups.json -OutputPath out/pim-groups-test -TenantId <tenant-id> -Apply -ActivationGateCheckedThen open ID Governance > Privileged Identity Management > Groups >
PRV-T1-LabTestand compare the member settings and assignments with the file. Record whether each request succeeded with theAzureADGrouppermissions alone (research gaps, row 53) and whether the v1.0 rule update on theGroup_policy took effect (row 55).Rerun the plan. It should report
Plan: 0 change(s)../Invoke-PaPimGroups.ps1 -Cloud gcc -DesiredPath prv-groups.json -OutputPath out/pim-groups-test -TenantId <tenant-id>Then remove one user from the file and apply: the
adminRemoverequest has noscheduleInfo(research gaps, row 51); record the result. The first three lines keep only the first user:$d = Get-Content prv-groups.json -Raw | ConvertFrom-Json $d.groups[0].member.eligible = @($d.groups[0].member.eligible | Select-Object -First 1) $d | ConvertTo-Json -Depth 6 | Set-Content prv-groups.json ./Invoke-PaPimGroups.ps1 -Cloud gcc -DesiredPath prv-groups.json -OutputPath out/pim-groups-test -TenantId <tenant-id> -ApplyBack it out. Empty both lists in your file and apply, so no schedule remains:
$d = Get-Content prv-groups.json -Raw | ConvertFrom-Json $d.groups[0].member.active = @(); $d.groups[0].member.eligible = @() $d | ConvertTo-Json -Depth 6 | Set-Content prv-groups.json ./Invoke-PaPimGroups.ps1 -Cloud gcc -DesiredPath prv-groups.json -OutputPath out/pim-groups-test -TenantId <tenant-id> -ApplyDelete
PRV-T1-LabTestandPIM-Approvers-T1(a role-assignable group is soft-deleted and can be restored for 30 days68), remove the permissions, delete both apps and their certificates, and deleteout/pim-groups-test: it names the tenant’s privileged holders.Remove-Item -Recurse -Force out/pim-groups-test
Verified facts
| Item | Value | US Government clouds | Stage | Source |
|---|---|---|---|---|
| Role-assignable groups | isAssignableToRole set only at creation; immutable; at most 500 per tenant; assigned membership only; no group members; Privileged Role Administrator to create; Privileged Authentication Administrator to change members’ and owners’ credentials; P1, and P2 for PIM |
Entra ID Governance in GCC, GCC High and DoD | GA | 69 70 |
| PIM for Groups | Membership and ownership; two policies per group; not for dynamic or on-premises groups; role-assignable not required, but recommended for sensitive groups | Same | GA | 71 |
| Last active owner | Can’t be removed; an activated owner’s deactivation is retried for up to 30 days, then stops | — | — | 72 |
| Nesting | No group as an active member of a role-assignable group; a group can be an eligible member | — | — | 73 74 |
| Service principals | Can’t be eligible for PIM for Groups; time-limited active is allowed; nesting groups in PIM for Groups isn’t recommended | — | — | 75 |
| Onboarding | Automatic on the first schedule request or policy update; policy IDs change; no offboarding | — | — | 76 |
| Eligible membership | Not in the group’s members relationship until activated |
— | — | 77 |
| Activation length | At most 8 hours (Graph overview); 1 to 24 hours (settings page) | — | — | 78 79 |
| Reauthentication on activation | With an authentication context: sign-in frequency Every time on its Conditional Access policy; a 10-minute window across Microsoft Entra roles, Azure resource roles and PIM for Groups | — | GA in the release notes (April 2026); public preview in the deployment plan; treated as preview | 80 81 82 |
| Approvers | No default approvers; select at least two; can’t approve their own requests; service principals can’t approve; 24 hours to approve | — | — | 83 84 |
| Create eligibilityScheduleRequest | POST .../group/eligibilityScheduleRequests; PrivilegedEligibilitySchedule.ReadWrite.AzureADGroup; Privileged Role Administrator for role-assignable groups |
L4 and L5 | v1.0 | 85 |
| Create assignmentScheduleRequest | POST .../group/assignmentScheduleRequests; PrivilegedAssignmentSchedule.ReadWrite.AzureADGroup |
L4 and L5 | v1.0 | 86 |
| List eligibilitySchedules, assignmentSchedules | $filter on groupId or principalId required; PrivilegedEligibilitySchedule.Read.AzureADGroup, PrivilegedAssignmentSchedule.Read.AzureADGroup |
L4 and L5 | v1.0 | 87 88 |
| List roleManagementPolicyAssignments (groups) | scopeId the group, scopeType Group, roleDefinitionId member or owner; RoleManagementPolicy.Read.AzureADGroup |
L4 and L5 | v1.0 | 89 |
| Update unifiedRoleManagementPolicyRule (groups) | PATCH /policies/roleManagementPolicies/{id}/rules/{id}; RoleManagementPolicy.ReadWrite.AzureADGroup; @odata.type required in the body; 17 rules per policy |
— | v1.0 | 90 91 92 |
isValidationOnly |
On both request types; documented for checking an activation before submitting it | — | v1.0 | 93 |
| List groups | Learn’s least-privileged column: Group-NestingSupport.ReadWrite.All; read-only alternative Group.ReadBasic.All |
— | v1.0 | 94 |
| Create group | Group.Create (application); RoleManagement.ReadWrite.Directory to set isAssignableToRole |
— | v1.0 | 95 96 |
| Graph hosts | graph.microsoft.com (worldwide and GCC), graph.microsoft.us (GCC High), dod-graph.microsoft.us (DoD) |
— | — | 97 |
Where Learn’s pages differ, recorded so a later edit doesn’t loosen the code:
- Activation length. Eight hours in the Graph overview, 24 in the settings page. The code caps at eight (research gaps, row 54).
- v1.0 or beta. The PIM for Groups API pages are v1.0. The Update rules how-to says PIM for Groups is beta only, and the PIM for Groups settings page shows a beta request.98 99 The deployment plan still links PIM for Groups as a preview.100 The code uses v1.0 (research gaps, row 55).
- Permissions for role-assignable groups.
RoleManagement.ReadWrite.Directoryon the role-assignable groups page; theAzureADGrouppermissions on the PIM for Groups pages. The code declares the latter and Lab 2 checks it (research gaps, row 53). - Creating a role-assignable group.
visibilityHiddenorPrivate(the group resource page gives both101), and whether it can have owners, differ across three pages; Learn’s own PowerShell for it signs in withGroup.ReadWrite.Allonly.102 The code declares bothGroup.CreateandRoleManagement.ReadWrite.Directory(research gaps, row 56). - The rule cmdlet.
Update-MgPolicyRoleManagementPolicyRulelists only theDirectorypermissions and no application support, while the API page listsRoleManagementPolicy.ReadWrite.AzureADGroupfor applications.103 104 The code calls the REST API (research gaps, row 59).
Federal requirements and evidence
The PRV groups’ file, the check and the plan are the evidence for the plan’s task A2.1. Each row names the command or file that shows it. Every control named is in the NIST SP 800-53B Moderate baseline.105
| What the output proves | Requirement it supports | KSI it aligns to | Who keeps it |
|---|---|---|---|
Microsoft’s samples, and Learn’s Example 1 sent by hand, run against the fake, and the kit’s own code passes its tests: Lab 1, steps 1, 2 and 9 (Invoke-Pester, Invoke-PgLearnRequest) |
CM-3(2), testing and validation of changes | KSI-CMT-VTD | The repository’s test runs |
Reading needs four read permissions and nothing that writes: Lab 1, step 3 (Get-PaPgRequiredPermission -Task pim-groups-read) |
AC-6, least privilege for the identity that reads | KSI-IAM-ELP | Identity engineering, with the app’s consent record |
What a run would change, as a diff and as the exact requests, with nothing sent: diff.txt and plan.json from Lab 1, step 4 |
CM-3, configuration change control: the change is reviewed before it is made | KSI-CMT-LMC, KSI-CMT-RMV | The pull request, with the diff attached |
Every PRV group is named for its tier, role-assignable, assigned rather than dynamic or synchronized, holds no group, and has no eligible service principal: PA-PG-01, 02, 03 and 05 in findings.json, Lab 1, step 5 |
AC-6(5), privileged accounts restricted to defined roles; MS.AAD.7.5v1, highly privileged roles provisioned only through a PAM system (BOD 25-01);106 the naming rule is design guidance | KSI-IAM-JIT | The ISSO |
Every grant has an end and a ticket, Tier 0 groups have no owners, Tier 0 and Tier 1 activation needs approval, and no group approves itself: PA-PG-06, 07 and 08 in findings.json |
AC-6, least privilege in time; AC-5, separation of duties; MS.AAD.7.4v1, no permanent active assignment to a highly privileged role (BOD 25-01)107 | KSI-IAM-JIT | The ISSO |
A schedule the file doesn’t grant, and a privileged group the file doesn’t list: PA-PG-09 in findings.json |
AC-2, account management: access nobody reviewed is found | KSI-IAM-JIT | The ISSO |
The write permissions a run needs are exactly those of its own operations: Lab 1, step 6, diff.txt and the Permissions list in plan.json |
AC-6 for the identity that applies; CM-3 | KSI-IAM-ELP, KSI-CMT-LMC | Identity engineering |
A plan with more removals than allowed is refused before anything is sent: Lab 1, step 7, Refusing to apply: PA-PG-G6 |
CM-3: an unsafe change is stopped (the guards are design guidance) | KSI-CMT-LMC | The repository’s test runs |
An apply refuses to select c1 without a person’s statement that its policy is On, then sends each request in order and records the result: Lab 1, step 8, the refusal, then results.json and manifest.json in out/pim-groups-apply |
CM-3, approved changes implemented and recorded | KSI-CMT-LMC | The ISSO, beside the files the manifest lists |
The groups are made by hand by a Privileged Role Administrator, so the pipeline’s app never holds RoleManagement.ReadWrite.Directory, and the reviewed file names each holder with an end date and a ticket: Lab 2, step 1, prv-groups.json |
AC-6 and AC-6(5) (keeping the permission off the pipeline is design guidance) | KSI-IAM-ELP, KSI-IAM-JIT | Identity engineering, in the repository |
A live plan of the test tenant, as the reader app: Lab 2, step 3, out/pim-groups-test/findings.json and diff.txt |
CM-3 | KSI-CMT-LMC | Identity engineering |
The writer applies the reviewed diff: Lab 2, step 4, results.json and manifest.json |
CM-3; AC-5, a reader and a writer that are different identities | KSI-CMT-LMC, KSI-IAM-JIT | The ISSO |
A second plan finds nothing to change, and removing a holder from the file removes the grant: Lab 2, step 5, Plan: 0 change(s), then the apply’s results.json |
CM-4(2), verification of controls after the change; AC-2, accounts removed according to policy | KSI-CMT-VTD, KSI-IAM-JIT | The ISSO |
| The back-out empties the file and applies it, so no schedule remains, and the lab folder is deleted: Lab 2, step 6 | CM-3: the rollback is a recorded change | KSI-CMT-RMV | Identity engineering |
KSIs are FedRAMP 20x indicators for cloud service providers.108 The agency authorizes its own system and lines this evidence up with what its providers report against those indicators; it doesn’t report KSIs itself (Book 00, Appendix B). Book 04, Chapter 10 carries the control-by-control mapping.
Dangers
| Danger | What happens | The guard |
|---|---|---|
| A sample copied as published | An ownership grant becomes a membership, or a 2023 date fails, or is edited by hand | Requests come from the file; tests pin the sample’s mismatches |
| A change made in the admin center or the groups API | The tenant drifts from the file and nobody reviews it | Every run reads first; PA-PG-09 and a removal in the plan |
| Approval dropped on a T0 or T1 group | A less-privileged admin who can reset a member’s credentials activates on their behalf, the case Learn warns about109 | PA-PG-08; guard G1 |
| A permanent member or owner | Standing privilege through the group | PA-PG-06; guard G2 |
| Eligible owner, no active owner | The owner activates and can’t be deactivated | PA-PG-07; guard G4 |
| A group nested in a PRV group | Its people hold the role and the review shows a group | PA-PG-05; guard G5 |
| A truncated or wrong file | The plan removes everyone | Removals come last; guard G6 stops more than five |
| A non-role-assignable group used for a role | It can’t hold the role, and can’t be converted | PA-PG-02 Finding; the plan creates groups as role-assignable |
| The 500-group limit | New PRV groups can’t be created | PA-PG-04 Warn at 450 |
A pipeline app with RoleManagement.ReadWrite.Directory |
It can assign any directory role | Group creation is planned, not routinely applied; the plan lists only its own permissions |
| Names in output | diff.txt and findings.json name privileged holders |
Treat the run folder as evidence; delete lab copies |
Checklist
Footnotes
Microsoft Learn, “Privileged Identity Management (PIM) for Groups,” https://learn.microsoft.com/entra/id-governance/privileged-identity-management/concept-pim-for-groups (accessed Oct 30, 2026).↩︎
Microsoft Learn, “Use Microsoft Entra groups to manage role assignments,” https://learn.microsoft.com/entra/identity/role-based-access-control/groups-concept (accessed Oct 30, 2026).↩︎
Microsoft Learn, “Privileged Identity Management (PIM) for Groups,” https://learn.microsoft.com/entra/id-governance/privileged-identity-management/concept-pim-for-groups (accessed Oct 30, 2026).↩︎
Microsoft Learn, “Govern membership and ownership of groups by using PIM for Groups,” https://learn.microsoft.com/graph/api/resources/privilegedidentitymanagement-for-groups-api-overview?view=graph-rest-1.0 (accessed Oct 30, 2026).↩︎
Microsoft Learn, “Privileged Identity Management (PIM) for Groups,” https://learn.microsoft.com/entra/id-governance/privileged-identity-management/concept-pim-for-groups (accessed Oct 30, 2026).↩︎
Microsoft Learn, “Govern membership and ownership of groups by using PIM for Groups,” https://learn.microsoft.com/graph/api/resources/privilegedidentitymanagement-for-groups-api-overview?view=graph-rest-1.0 (accessed Oct 30, 2026).↩︎
Microsoft Learn, “List eligibilitySchedules” (privilegedAccessGroup), https://learn.microsoft.com/graph/api/privilegedaccessgroup-list-eligibilityschedules?view=graph-rest-1.0 (accessed Oct 30, 2026).↩︎
Microsoft Learn, “List assignmentSchedules” (privilegedAccessGroup), https://learn.microsoft.com/graph/api/privilegedaccessgroup-list-assignmentschedules?view=graph-rest-1.0 (accessed Oct 30, 2026).↩︎
Microsoft Learn, “List roleManagementPolicyAssignments,” permissions for PIM for Groups and Examples 3 and 4, https://learn.microsoft.com/graph/api/policyroot-list-rolemanagementpolicyassignments?view=graph-rest-1.0 (accessed Oct 30, 2026).↩︎
Microsoft Learn, “Create eligibilityScheduleRequest” (privilegedAccessGroup), https://learn.microsoft.com/graph/api/privilegedaccessgroup-post-eligibilityschedulerequests?view=graph-rest-1.0 (accessed Oct 30, 2026).↩︎
Microsoft Learn, “Create assignmentScheduleRequest” (privilegedAccessGroup), https://learn.microsoft.com/graph/api/privilegedaccessgroup-post-assignmentschedulerequests?view=graph-rest-1.0 (accessed Oct 30, 2026).↩︎
Microsoft Learn, “Update unifiedRoleManagementPolicyRule,” permissions for PIM for Groups, https://learn.microsoft.com/graph/api/unifiedrolemanagementpolicyrule-update?view=graph-rest-1.0 (accessed Oct 30, 2026).↩︎
Microsoft Learn, “Update rules in PIM by using Microsoft Graph,” https://learn.microsoft.com/graph/how-to-pim-update-rules (accessed Oct 30, 2026).↩︎
Microsoft Learn, “Govern membership and ownership of groups by using PIM for Groups,” https://learn.microsoft.com/graph/api/resources/privilegedidentitymanagement-for-groups-api-overview?view=graph-rest-1.0 (accessed Oct 30, 2026).↩︎
Microsoft Learn, “Govern membership and ownership of groups by using PIM for Groups,” https://learn.microsoft.com/graph/api/resources/privilegedidentitymanagement-for-groups-api-overview?view=graph-rest-1.0 (accessed Oct 30, 2026).↩︎
Microsoft Learn, “Create eligibilityScheduleRequest” (privilegedAccessGroup), https://learn.microsoft.com/graph/api/privilegedaccessgroup-post-eligibilityschedulerequests?view=graph-rest-1.0 (accessed Oct 30, 2026).↩︎
Microsoft Learn, “Bring groups into Privileged Identity Management,” https://learn.microsoft.com/entra/id-governance/privileged-identity-management/groups-discover-groups (accessed Oct 30, 2026).↩︎
Microsoft Learn, “Assign eligible group membership and ownership in access packages via Privileged Identity Management for Groups,” https://learn.microsoft.com/entra/id-governance/entitlement-management-access-package-eligible (accessed Oct 30, 2026).↩︎
Microsoft Learn, “Using groups managed by Privileged Identity Management with access packages,” shorter PIM duration, https://learn.microsoft.com/entra/id-governance/entitlement-management-access-package-pim-reference (accessed Nov 9, 2026).↩︎
Microsoft Learn, “Microsoft Graph national cloud deployments,” https://learn.microsoft.com/graph/deployments (accessed Oct 30, 2026).↩︎
Microsoft Learn, “Create eligibilityScheduleRequest” (privilegedAccessGroup), https://learn.microsoft.com/graph/api/privilegedaccessgroup-post-eligibilityschedulerequests?view=graph-rest-1.0 (accessed Oct 30, 2026).↩︎
Microsoft Learn, “Create assignmentScheduleRequest” (privilegedAccessGroup), https://learn.microsoft.com/graph/api/privilegedaccessgroup-post-assignmentschedulerequests?view=graph-rest-1.0 (accessed Oct 30, 2026).↩︎
Microsoft Learn, “List roleManagementPolicyAssignments,” permissions for PIM for Groups and Examples 3 and 4, https://learn.microsoft.com/graph/api/policyroot-list-rolemanagementpolicyassignments?view=graph-rest-1.0 (accessed Oct 30, 2026).↩︎
Microsoft Learn, “Microsoft Entra feature availability,” other Microsoft Entra products, https://learn.microsoft.com/entra/identity/authentication/feature-availability (accessed Oct 30, 2026).↩︎
Microsoft Learn, “Assign privileged roles using PIM for Microsoft Entra roles APIs,” conclusion, https://learn.microsoft.com/graph/tutorial-assign-azureadroles (accessed Oct 30, 2026).↩︎
Microsoft Learn, “Create eligibilityScheduleRequest” (privilegedAccessGroup), https://learn.microsoft.com/graph/api/privilegedaccessgroup-post-eligibilityschedulerequests?view=graph-rest-1.0 (accessed Oct 30, 2026).↩︎
Microsoft Learn, “Extend or renew PIM for groups assignments,” admin initiated extension, https://learn.microsoft.com/entra/id-governance/privileged-identity-management/groups-renew-extend (accessed Nov 9, 2026).↩︎
Microsoft Learn, “Create assignmentScheduleRequest” (privilegedAccessGroup), https://learn.microsoft.com/graph/api/privilegedaccessgroup-post-assignmentschedulerequests?view=graph-rest-1.0 (accessed Oct 30, 2026).↩︎
Microsoft Learn, “Activate your group membership or ownership in Privileged Identity Management,” activate a role, and PIM for Groups and ownership deactivation, https://learn.microsoft.com/entra/id-governance/privileged-identity-management/groups-activate-roles (accessed Nov 9, 2026).↩︎
Microsoft Learn, “Update rules in PIM by using Microsoft Graph,” https://learn.microsoft.com/graph/how-to-pim-update-rules (accessed Oct 30, 2026).↩︎
Microsoft, microsoftgraph/microsoft-graph-docs-contrib,
api-reference/v1.0/api/privilegedaccessgroup-post-eligibilityschedulerequests.md,api-reference/v1.0/api/privilegedaccessgroup-post-assignmentschedulerequests.mdandconcepts/how-to-pim-update-rules.mdat commita69303123e9701eecbf56568d152ece936a97f1e(October 30, 2026; the pages last changed October 24, 2025 and August 29, 2025), documentation CC BY 4.0 and code MIT, https://github.com/microsoftgraph/microsoft-graph-docs-contrib/tree/a69303123e9701eecbf56568d152ece936a97f1e (accessed Oct 30, 2026); pinned copy inexamples/third_party/graph-pim-for-groups-pages.↩︎Microsoft Learn, “Govern membership and ownership of groups by using PIM for Groups,” https://learn.microsoft.com/graph/api/resources/privilegedidentitymanagement-for-groups-api-overview?view=graph-rest-1.0 (accessed Oct 30, 2026).↩︎
Microsoft Learn, “Plan a Privileged Identity Management deployment,” understand PIM and plan and implement PIM for Groups, https://learn.microsoft.com/entra/id-governance/privileged-identity-management/pim-deployment-plan (accessed Oct 30, 2026).↩︎
Microsoft Learn, “Govern membership and ownership of groups by using PIM for Groups,” https://learn.microsoft.com/graph/api/resources/privilegedidentitymanagement-for-groups-api-overview?view=graph-rest-1.0 (accessed Oct 30, 2026).↩︎
Microsoft Learn, “Configure PIM for Groups settings,” https://learn.microsoft.com/entra/id-governance/privileged-identity-management/groups-role-settings (accessed Oct 30, 2026).↩︎
Microsoft Learn, “Configure PIM for Groups settings,” on activation, require Microsoft Entra Conditional Access authentication context, https://learn.microsoft.com/entra/id-governance/privileged-identity-management/groups-role-settings (accessed Oct 31, 2026).↩︎
Microsoft Learn, “Configure PIM for Groups settings,” on activation, require Microsoft Entra Conditional Access authentication context, https://learn.microsoft.com/entra/id-governance/privileged-identity-management/groups-role-settings (accessed Oct 31, 2026).↩︎
Microsoft Learn, “Microsoft Entra releases and announcements,” April 2026, General Availability - Enforce Conditional Access policies like MFA on every PIM activation, https://learn.microsoft.com/entra/fundamentals/whats-new (accessed Oct 31, 2026).↩︎
Microsoft Learn, “Plan a Privileged Identity Management deployment,” overview and plan testing (Conditional Access context marked public preview), https://learn.microsoft.com/entra/id-governance/privileged-identity-management/pim-deployment-plan (accessed Oct 31, 2026).↩︎
Microsoft Learn, “Use Microsoft Entra groups to manage role assignments,” https://learn.microsoft.com/entra/identity/role-based-access-control/groups-concept (accessed Oct 30, 2026).↩︎
Microsoft Learn, “Privileged Identity Management (PIM) for Groups,” https://learn.microsoft.com/entra/id-governance/privileged-identity-management/concept-pim-for-groups (accessed Oct 30, 2026).↩︎
Microsoft Learn, “Privileged Identity Management (PIM) for Groups,” https://learn.microsoft.com/entra/id-governance/privileged-identity-management/concept-pim-for-groups (accessed Oct 30, 2026).↩︎
Microsoft Learn, “Use Microsoft Entra groups to manage role assignments,” https://learn.microsoft.com/entra/identity/role-based-access-control/groups-concept (accessed Oct 30, 2026).↩︎
Microsoft Learn, “Use Microsoft Entra groups to manage role assignments,” https://learn.microsoft.com/entra/identity/role-based-access-control/groups-concept (accessed Oct 30, 2026).↩︎
Microsoft Learn, “Plan a Privileged Identity Management deployment,” understand PIM and plan and implement PIM for Groups, https://learn.microsoft.com/entra/id-governance/privileged-identity-management/pim-deployment-plan (accessed Oct 30, 2026).↩︎
Microsoft Learn, “Plan a Privileged Identity Management deployment,” understand PIM and plan and implement PIM for Groups, https://learn.microsoft.com/entra/id-governance/privileged-identity-management/pim-deployment-plan (accessed Oct 30, 2026).↩︎
Microsoft Learn, “Privileged Identity Management (PIM) for Groups,” https://learn.microsoft.com/entra/id-governance/privileged-identity-management/concept-pim-for-groups (accessed Oct 30, 2026).↩︎
Microsoft Learn, “Activate your group membership or ownership in Privileged Identity Management,” activate a role, and PIM for Groups and ownership deactivation, https://learn.microsoft.com/entra/id-governance/privileged-identity-management/groups-activate-roles (accessed Nov 9, 2026).↩︎
Microsoft Learn, “Use Microsoft Entra groups to manage role assignments,” https://learn.microsoft.com/entra/identity/role-based-access-control/groups-concept (accessed Oct 30, 2026).↩︎
Microsoft Learn, “Approve activation requests for group members and owners,” https://learn.microsoft.com/entra/id-governance/privileged-identity-management/groups-approval-workflow (accessed Oct 30, 2026).↩︎
Microsoft Learn, “group resource type,”
isAssignableToRoleandvisibility, https://learn.microsoft.com/graph/api/resources/group?view=graph-rest-1.0 (accessed Oct 31, 2026).↩︎Microsoft Learn, “group resource type,”
isAssignableToRole, https://learn.microsoft.com/graph/api/resources/group?view=graph-rest-1.0 (accessed Oct 30, 2026).↩︎Microsoft Learn, “Create group,” permissions and Example 3, https://learn.microsoft.com/graph/api/group-post-groups?view=graph-rest-1.0 (accessed Oct 30, 2026).↩︎
Microsoft Learn, “Use Microsoft Entra groups to manage role assignments,” https://learn.microsoft.com/entra/identity/role-based-access-control/groups-concept (accessed Oct 30, 2026).↩︎
Microsoft Learn, “List groups,” permissions, https://learn.microsoft.com/graph/api/group-list?view=graph-rest-1.0 (accessed Oct 30, 2026).↩︎
Microsoft Learn, “List eligibilitySchedules” (privilegedAccessGroup), https://learn.microsoft.com/graph/api/privilegedaccessgroup-list-eligibilityschedules?view=graph-rest-1.0 (accessed Oct 30, 2026).↩︎
Microsoft Learn, “List assignmentSchedules” (privilegedAccessGroup), https://learn.microsoft.com/graph/api/privilegedaccessgroup-list-assignmentschedules?view=graph-rest-1.0 (accessed Oct 30, 2026).↩︎
Microsoft Learn, “List roleManagementPolicyAssignments,” permissions for PIM for Groups and Examples 3 and 4, https://learn.microsoft.com/graph/api/policyroot-list-rolemanagementpolicyassignments?view=graph-rest-1.0 (accessed Oct 30, 2026).↩︎
Microsoft Learn, “Create eligibilityScheduleRequest” (privilegedAccessGroup), https://learn.microsoft.com/graph/api/privilegedaccessgroup-post-eligibilityschedulerequests?view=graph-rest-1.0 (accessed Oct 30, 2026).↩︎
Microsoft Learn, “Create assignmentScheduleRequest” (privilegedAccessGroup), https://learn.microsoft.com/graph/api/privilegedaccessgroup-post-assignmentschedulerequests?view=graph-rest-1.0 (accessed Oct 30, 2026).↩︎
Microsoft Learn, “Update unifiedRoleManagementPolicyRule,” permissions for PIM for Groups, https://learn.microsoft.com/graph/api/unifiedrolemanagementpolicyrule-update?view=graph-rest-1.0 (accessed Oct 30, 2026).↩︎
Microsoft Learn, “Update rules in PIM by using Microsoft Graph,” https://learn.microsoft.com/graph/how-to-pim-update-rules (accessed Oct 30, 2026).↩︎
Microsoft Learn, “Create group,” permissions and Example 3, https://learn.microsoft.com/graph/api/group-post-groups?view=graph-rest-1.0 (accessed Oct 30, 2026).↩︎
Microsoft Learn, “group resource type,”
isAssignableToRole, https://learn.microsoft.com/graph/api/resources/group?view=graph-rest-1.0 (accessed Oct 30, 2026).↩︎Microsoft Learn, “Use Microsoft Entra groups to manage role assignments,” https://learn.microsoft.com/entra/identity/role-based-access-control/groups-concept (accessed Oct 30, 2026).↩︎
Microsoft Learn, “Govern membership and ownership of groups by using PIM for Groups,” https://learn.microsoft.com/graph/api/resources/privilegedidentitymanagement-for-groups-api-overview?view=graph-rest-1.0 (accessed Oct 30, 2026).↩︎
Microsoft Learn, “Create a role-assignable group in Microsoft Entra ID,” https://learn.microsoft.com/entra/identity/role-based-access-control/groups-create-eligible (accessed Oct 30, 2026).↩︎
Microsoft Learn, “Use Microsoft Entra groups to manage role assignments,” https://learn.microsoft.com/entra/identity/role-based-access-control/groups-concept (accessed Oct 30, 2026).↩︎
Microsoft Learn, “Use Microsoft Entra groups to manage role assignments,” https://learn.microsoft.com/entra/identity/role-based-access-control/groups-concept (accessed Oct 30, 2026).↩︎
Microsoft Learn, “Microsoft Entra feature availability,” other Microsoft Entra products, https://learn.microsoft.com/entra/identity/authentication/feature-availability (accessed Oct 30, 2026).↩︎
Microsoft Learn, “Privileged Identity Management (PIM) for Groups,” https://learn.microsoft.com/entra/id-governance/privileged-identity-management/concept-pim-for-groups (accessed Oct 30, 2026).↩︎
Microsoft Learn, “Privileged Identity Management (PIM) for Groups,” https://learn.microsoft.com/entra/id-governance/privileged-identity-management/concept-pim-for-groups (accessed Oct 30, 2026).↩︎
Microsoft Learn, “Privileged Identity Management (PIM) for Groups,” https://learn.microsoft.com/entra/id-governance/privileged-identity-management/concept-pim-for-groups (accessed Oct 30, 2026).↩︎
Microsoft Learn, “Use Microsoft Entra groups to manage role assignments,” https://learn.microsoft.com/entra/identity/role-based-access-control/groups-concept (accessed Oct 30, 2026).↩︎
Microsoft Learn, “Plan a Privileged Identity Management deployment,” understand PIM and plan and implement PIM for Groups, https://learn.microsoft.com/entra/id-governance/privileged-identity-management/pim-deployment-plan (accessed Oct 30, 2026).↩︎
Microsoft Learn, “Govern membership and ownership of groups by using PIM for Groups,” https://learn.microsoft.com/graph/api/resources/privilegedidentitymanagement-for-groups-api-overview?view=graph-rest-1.0 (accessed Oct 30, 2026).↩︎
Microsoft Learn, “Govern membership and ownership of groups by using PIM for Groups,” https://learn.microsoft.com/graph/api/resources/privilegedidentitymanagement-for-groups-api-overview?view=graph-rest-1.0 (accessed Oct 30, 2026).↩︎
Microsoft Learn, “Govern membership and ownership of groups by using PIM for Groups,” https://learn.microsoft.com/graph/api/resources/privilegedidentitymanagement-for-groups-api-overview?view=graph-rest-1.0 (accessed Oct 30, 2026).↩︎
Microsoft Learn, “Configure PIM for Groups settings,” https://learn.microsoft.com/entra/id-governance/privileged-identity-management/groups-role-settings (accessed Oct 30, 2026).↩︎
Microsoft Learn, “Configure PIM for Groups settings,” on activation, require Microsoft Entra Conditional Access authentication context, https://learn.microsoft.com/entra/id-governance/privileged-identity-management/groups-role-settings (accessed Oct 31, 2026).↩︎
Microsoft Learn, “Microsoft Entra releases and announcements,” April 2026, General Availability - Enforce Conditional Access policies like MFA on every PIM activation, https://learn.microsoft.com/entra/fundamentals/whats-new (accessed Oct 31, 2026).↩︎
Microsoft Learn, “Plan a Privileged Identity Management deployment,” overview and plan testing (Conditional Access context marked public preview), https://learn.microsoft.com/entra/id-governance/privileged-identity-management/pim-deployment-plan (accessed Oct 31, 2026).↩︎
Microsoft Learn, “Configure PIM for Groups settings,” https://learn.microsoft.com/entra/id-governance/privileged-identity-management/groups-role-settings (accessed Oct 30, 2026).↩︎
Microsoft Learn, “Approve activation requests for group members and owners,” https://learn.microsoft.com/entra/id-governance/privileged-identity-management/groups-approval-workflow (accessed Oct 30, 2026).↩︎
Microsoft Learn, “Create eligibilityScheduleRequest” (privilegedAccessGroup), https://learn.microsoft.com/graph/api/privilegedaccessgroup-post-eligibilityschedulerequests?view=graph-rest-1.0 (accessed Oct 30, 2026).↩︎
Microsoft Learn, “Create assignmentScheduleRequest” (privilegedAccessGroup), https://learn.microsoft.com/graph/api/privilegedaccessgroup-post-assignmentschedulerequests?view=graph-rest-1.0 (accessed Oct 30, 2026).↩︎
Microsoft Learn, “List eligibilitySchedules” (privilegedAccessGroup), https://learn.microsoft.com/graph/api/privilegedaccessgroup-list-eligibilityschedules?view=graph-rest-1.0 (accessed Oct 30, 2026).↩︎
Microsoft Learn, “List assignmentSchedules” (privilegedAccessGroup), https://learn.microsoft.com/graph/api/privilegedaccessgroup-list-assignmentschedules?view=graph-rest-1.0 (accessed Oct 30, 2026).↩︎
Microsoft Learn, “List roleManagementPolicyAssignments,” permissions for PIM for Groups and Examples 3 and 4, https://learn.microsoft.com/graph/api/policyroot-list-rolemanagementpolicyassignments?view=graph-rest-1.0 (accessed Oct 30, 2026).↩︎
Microsoft Learn, “Update unifiedRoleManagementPolicyRule,” permissions for PIM for Groups, https://learn.microsoft.com/graph/api/unifiedrolemanagementpolicyrule-update?view=graph-rest-1.0 (accessed Oct 30, 2026).↩︎
Microsoft Learn, “Update rules in PIM by using Microsoft Graph,” https://learn.microsoft.com/graph/how-to-pim-update-rules (accessed Oct 30, 2026).↩︎
Microsoft Learn, “Rules in PIM - Mapping guide,” https://learn.microsoft.com/graph/identity-governance-pim-rules-overview (accessed Oct 30, 2026).↩︎
Microsoft Learn, “privilegedAccessGroupEligibilityScheduleRequest resource type” and “privilegedAccessGroupAssignmentScheduleRequest resource type,”
isValidationOnly, https://learn.microsoft.com/graph/api/resources/privilegedaccessgroupeligibilityschedulerequest?view=graph-rest-1.0 (accessed Oct 30, 2026).↩︎Microsoft Learn, “List groups,” permissions, https://learn.microsoft.com/graph/api/group-list?view=graph-rest-1.0 (accessed Oct 30, 2026).↩︎
Microsoft Learn, “Create group,” permissions and Example 3, https://learn.microsoft.com/graph/api/group-post-groups?view=graph-rest-1.0 (accessed Oct 30, 2026).↩︎
Microsoft Learn, “group resource type,”
isAssignableToRole, https://learn.microsoft.com/graph/api/resources/group?view=graph-rest-1.0 (accessed Oct 30, 2026).↩︎Microsoft Learn, “Microsoft Graph national cloud deployments,” https://learn.microsoft.com/graph/deployments (accessed Oct 30, 2026).↩︎
Microsoft Learn, “Update rules in PIM by using Microsoft Graph,” https://learn.microsoft.com/graph/how-to-pim-update-rules (accessed Oct 30, 2026).↩︎
Microsoft Learn, “Configure PIM for Groups settings,” https://learn.microsoft.com/entra/id-governance/privileged-identity-management/groups-role-settings (accessed Oct 30, 2026).↩︎
Microsoft Learn, “Plan a Privileged Identity Management deployment,” understand PIM and plan and implement PIM for Groups, https://learn.microsoft.com/entra/id-governance/privileged-identity-management/pim-deployment-plan (accessed Oct 30, 2026).↩︎
Microsoft Learn, “group resource type,”
isAssignableToRoleandvisibility, https://learn.microsoft.com/graph/api/resources/group?view=graph-rest-1.0 (accessed Oct 31, 2026).↩︎Microsoft Learn, “Create a role-assignable group in Microsoft Entra ID,” https://learn.microsoft.com/entra/identity/role-based-access-control/groups-create-eligible (accessed Oct 30, 2026).↩︎
Microsoft Learn, “Update-MgPolicyRoleManagementPolicyRule” (Microsoft Graph PowerShell v1.0), https://learn.microsoft.com/powershell/module/microsoft.graph.identity.signins/update-mgpolicyrolemanagementpolicyrule?view=graph-powershell-1.0 (accessed Oct 30, 2026).↩︎
Microsoft Learn, “Update unifiedRoleManagementPolicyRule,” permissions for PIM for Groups, https://learn.microsoft.com/graph/api/unifiedrolemanagementpolicyrule-update?view=graph-rest-1.0 (accessed Oct 30, 2026).↩︎
National Institute of Standards and Technology, SP 800-53B Moderate baseline, release 5.2.0 OSCAL profile (includes AC-2, AC-5, AC-6, AC-6(5), CM-3, CM-3(2) and CM-4(2)), https://github.com/usnistgov/oscal-content/blob/main/nist.gov/SP800-53/rev5/json/NIST_SP-800-53_rev5_MODERATE-baseline_profile.json (accessed Nov 2, 2026).↩︎
Cybersecurity and Infrastructure Security Agency, “BOD 25-01: Implementing Secure Practices for Cloud Services Required Configurations,” Microsoft Entra ID policies MS.AAD.7.4v1 and MS.AAD.7.5v1, https://www.cisa.gov/resources-tools/services/bod-25-01-implementing-secure-practices-cloud-services-required-configurations (accessed Nov 2, 2026).↩︎
Cybersecurity and Infrastructure Security Agency, “BOD 25-01: Implementing Secure Practices for Cloud Services Required Configurations,” Microsoft Entra ID policies MS.AAD.7.4v1 and MS.AAD.7.5v1, https://www.cisa.gov/resources-tools/services/bod-25-01-implementing-secure-practices-cloud-services-required-configurations (accessed Nov 2, 2026).↩︎
FedRAMP, “Key Security Indicators,” FedRAMP Consolidated Rules for 2026, indicator statements and “Related SP 800-53 Controls” for KSI-CMT-LMC, KSI-CMT-RMV, KSI-CMT-VTD, KSI-IAM-ELP and KSI-IAM-JIT, https://www.fedramp.gov/2026/reference/key-security-indicators/ (accessed Nov 2, 2026).↩︎
Microsoft Learn, “Use Microsoft Entra groups to manage role assignments,” https://learn.microsoft.com/entra/identity/role-based-access-control/groups-concept (accessed Oct 30, 2026).↩︎









