Activate PIM roles from PowerShell with Microsoft Graph
The portal is fine for occasional use, but if you activate roles every day, a few lines of Graph PowerShell are faster. Here's how to list eligible roles and activate one.
On this page
Privileged Identity Management is the right way to handle admin roles: nobody holds them permanently, and every elevation is time-boxed and justified. The downside is clicks. If you activate roles several times a day, scripting it with the Microsoft Graph PowerShell SDK saves real time.
Connect with the right scopes
Connect-MgGraph -Scopes "RoleEligibilitySchedule.Read.Directory",
"RoleAssignmentSchedule.ReadWrite.Directory"
$me = Get-MgUser -UserId (Get-MgContext).AccountList your eligible roles
$eligible = Get-MgRoleManagementDirectoryRoleEligibilityScheduleInstance -Filter "principalId eq '$($me.Id)'" -ExpandProperty RoleDefinition
$eligible | Select-Object @{n="Role";e={$_.RoleDefinition.DisplayName}}, DirectoryScopeId, EndDateTimeActivate one
Activation is a role assignment schedule request with the action selfActivate. The duration uses ISO 8601 format, so PT2H means two hours:
$role = $eligible | Where-Object { $_.RoleDefinition.DisplayName -eq "Exchange Administrator" }
$params = @{
Action = "selfActivate"
PrincipalId = $me.Id
RoleDefinitionId = $role.RoleDefinitionId
DirectoryScopeId = $role.DirectoryScopeId
Justification = "Investigating mail flow issue"
ScheduleInfo = @{
StartDateTime = Get-Date
Expiration = @{ Type = "AfterDuration"; Duration = "PT2H" }
}
}
New-MgRoleManagementDirectoryRoleAssignmentScheduleRequest -BodyParameter $paramsCheck the result, extend or end early
The request returns a status straight away. Provisioned means the role is active. PendingApproval means the role's PIM settings require an approver, and nothing happens until they respond.
# Requests you've made, newest first
Get-MgRoleManagementDirectoryRoleAssignmentScheduleRequest -Filter "principalId eq '$($me.Id)'" |
Sort-Object CreatedDateTime -Descending |
Select-Object -First 5 Action, Status, RoleDefinitionId, CreatedDateTime
# Finished early? Deactivate rather than leave it running
$params.Action = "selfDeactivate"
$params.Remove("ScheduleInfo"); $params.Remove("Justification")
New-MgRoleManagementDirectoryRoleAssignmentScheduleRequest -BodyParameter $paramsDeactivating when you're done is good practice. It shortens the window in which a stolen session could use the role, and it shows up in the audit log as a deliberate action.
Wrap it in a function
Once it works, put it in your PowerShell profile so activation becomes one command:
function Enable-PimRole {
param([Parameter(Mandatory)][string]$Role,
[string]$Reason = "Planned admin work",
[int]$Hours = 1)
$me = Get-MgUser -UserId (Get-MgContext).Account
$r = Get-MgRoleManagementDirectoryRoleEligibilityScheduleInstance -Filter "principalId eq '$($me.Id)'" -ExpandProperty RoleDefinition |
Where-Object { $_.RoleDefinition.DisplayName -eq $Role }
if (-not $r) { throw "Not eligible for $Role" }
New-MgRoleManagementDirectoryRoleAssignmentScheduleRequest -BodyParameter @{
Action = "selfActivate"; PrincipalId = $me.Id
RoleDefinitionId = $r.RoleDefinitionId; DirectoryScopeId = $r.DirectoryScopeId
Justification = $Reason
ScheduleInfo = @{ StartDateTime = Get-Date; Expiration = @{ Type = "AfterDuration"; Duration = "PT$($Hours)H" } }
}
}
Enable-PimRole -Role "Intune Administrator" -Reason "Deploying compliance policy" -Hours 2Things that trip people up
- Role settings still apply. If the role needs approval, a ticket number or a shorter maximum duration, the request fails with an error that says so. Read it rather than retrying.
- MFA and authentication context. If the role requires MFA or a Conditional Access authentication context on activation, your Graph session must satisfy it. You may need to reconnect so you're prompted.
- Propagation. An activated role can take a minute or two to take effect in some admin portals. Sign out and back in if a portal doesn't see it.
- Deactivate when done. Use the action
selfDeactivatewith the same role and scope to end the activation early.
| Error or symptom | What it usually means |
|---|---|
| Activation rejected for duration | You asked for longer than the role's maximum activation duration in PIM settings. Ask for less. |
| Justification or ticket required | The role settings require them. Add Justification or TicketInfo to the request. |
| Authentication context or ACRS validation error | The role requires a Conditional Access authentication context. Activate in the portal, or reconnect so your token satisfies that context. See PIM with authentication context. |
| Role active but the portal still says no | Your existing token predates the activation. Sign out and back in, or wait a few minutes. |
| Insufficient privileges on the request | Your Graph session lacks RoleAssignmentSchedule.ReadWrite.Directory. Reconnect with the scope. |
Can I use this for Azure resource roles too?
Not with these cmdlets. Azure resource roles use the Azure PIM APIs in Az PowerShell, such as New-AzRoleAssignmentScheduleRequest, with the same idea of an eligible schedule and a self-activation request.
Does scripting bypass MFA or approval?
No. The request is checked against the same role settings as the portal. If the role needs approval, the request waits for it.
Can a service principal activate a role?
PIM is designed for people. Workload identities should hold only the narrow permissions they need, granted directly, and be monitored instead.
This post was last checked against Microsoft's documentation over six months ago. The approach should still hold, but check the linked sources for anything that has changed before you act on it.
Next in Locking down admin access · part 3 of 6Require phishing-resistant MFA on every PIM activation →