If you live in Microsoft Entra PIM, you click. A lot. Every workday starts the same way — open the portal, find the right role, type a justification, pick a duration, activate, repeat for the next role. After about the fourth click I started looking for a PowerShell shortcut. When I couldn’t find one that handled directory roles, PIM for Groups, and Azure Resources from the same prompt, I wrote my own.
Why a single activation script?
Most PIM helpers I’ve seen on GitHub solve one slice of the problem. They activate Entra directory roles, or PIM for Groups, or Azure Resource roles — but not all three. In real consulting work I move between all three scopes during the same task. Switching tools mid-flow breaks concentration and adds friction.
The script I’ll share here does three things in one flow:
- Lists eligible and active assignments across Entra directory roles, PIM for Groups (member and owner), and Azure Resources PIM
- Activates one or more roles in a single interactive selection — with a justification, duration, and optional ticket reference
- Deactivates active roles the same way
It also reads policy maximum durations before sending the request, so you get a heads-up if your “8h” exceeds what the role’s policy allows.
Authentication that respects your existing session
A small detail that turned out to matter more than I expected: the script never forces a new login if a usable Graph session already exists. It detects the active context, validates the required scopes, and asks before reauthenticating:
Existing Microsoft Graph session detected:
Account : marius@contoso.onmicrosoft.com
Tenant : 1c0b4f...
What do you want to do?
[C] Continue with this session (default)
[S] Switch account / sign in as someone else
[Q] Quit
On macOS, where the localhost redirect for interactive auth is unreliable, it falls back to device code automatically. And when the script needs Azure (for Azure Resources PIM), it verifies that the Az session matches the Graph identity — same UPN, same tenant — before reusing it. Cross-tenant token leakage is a real risk when consultants juggle multiple customers; this check has saved me twice.
Typical usage
Three patterns cover most days:
# Interactive — pick from a grid, type duration and justification
./Activate-EntraPimRoles.ps1
# Non-interactive — single role, named directly
./Activate-EntraPimRoles.ps1 -Action Activate -Target Directory `
-Roles 'Global Reader' -Duration 2h -Justification 'Change #1234'
# Show what's currently active
./Activate-EntraPimRoles.ps1 -Action ListActive
For the interactive flow, Microsoft.PowerShell.ConsoleGuiTools gives you a multi-select grid — space to toggle, enter to confirm. If the module isn’t installed, the script falls back to a numbered list. Either works.
Duration parsing — small thing, big quality-of-life
The PIM API expects ISO 8601 duration (PT1H30M). I never type that. The script accepts whatever I’d actually type:
30m, 90m, 1h, 1h30m, 2,5h, 0.5h, 1d, 01:30:00, PT45M
Where to get it
Update: The full script is now maintained on GitHub as part of my EntraGate work. Source and latest version: maskovli/entragate — Activate-EntraPimRoles.ps1
Pull requests welcome. If you find an edge case in your tenant — multi-AU scopes, role exclusions, weird policy shapes — open an issue.