Skip to content

Instantly share code, notes, and snippets.

@sean-mcardle
Last active December 22, 2025 21:35
Show Gist options
  • Select an option

  • Save sean-mcardle/a915d86f2b9985607e3006ebcd91a0c9 to your computer and use it in GitHub Desktop.

Select an option

Save sean-mcardle/a915d86f2b9985607e3006ebcd91a0c9 to your computer and use it in GitHub Desktop.
Script for activating PIM roles. Meant to be used within the Azure shell when the PIM portal acts up again. Copy pasta. It utilizes REST APIs for role eligibility and activation to avoid DLL conflicts in the Identity Governance cmdlets (some of us just want to do our jobs instead of fight with your dependencies Microsoft).
function Out-SelectorMenu {
param (
[Parameter(ValueFromPipeline=$true)]
$InputObject,
[Parameter(Position=0)]
$Title,
$Selector
)
begin {
$_items = @()
}
process {
if ($InputObject) {
$_items += $InputObject
}
}
end {
Write-Host $Title
Write-Host ($_items | ForEach-Object {$index=0} {$_; $index++} | Format-Table @{Label="Index";Expression={$index}; Width=5 }, * | Out-String)
$selectionMade = $false
$selection = $null
do{
$selection = Read-Host -Prompt "Make a selection by index ('c' to cancel)#"
if ($selection -match '[0-9]+' -and [int]$selection -ge 0 -and [int]$selection -lt $_items.Count) {
$selectionMade = $true
break
} elseif ($selection -and $selection.Trim() -like 'c') {
break
}
} while ($true)
if ($selectionMade) {
return $_items[$selection] | Select-Object -ExcludeProperty 'Index'
}
}
}
$fmt_roleName = @{Name='Role';Expression={$_.roleDefinition.displayName}}
$fmt_roleScope = @{
Name='Scope';
Expression={
if($_.scopedResource) {
"$( if($_.scopedResource.type -like "administrativeUnits"){"AU"}else{$_.scopedResource.type}) : $($_.scopedResource.displayName)"
} else {
"Directory : /"
}
}
}
# Get the user id of the cloud shell user
$subjectId = & az ad signed-in-user show --query id
$subjectId = $subjectId.Trim('"')
if (-not $subjectId) {
Write-Error "Can't resolve Id of the signed-in user!`nThis is needed to resolve eligible role assignments.`nQuiting..."
return
}
$header = @{
Authorization = "Bearer $(ConvertFrom-SecureString -AsPlainText (Get-AzAccessToken).Token)"
}
# Load eligible roles for the signed-in user and prompt for selection
$eligibleRolesUri = "https://api.azrbac.mspim.azure.com/api/v2/privilegedAccess/aadroles/roleAssignments?`$expand=linkedEligibleRoleAssignment,subject,scopedResource,roleDefinition(`$expand=resource)&`$filter=(subject/id eq '$subjectId') and (assignmentState eq 'Eligible')&`$count=true"
$eligibleRolesRequest = Invoke-RestMethod -Uri $eligibleRolesUri -Headers $header
$roleCount = $eligibleRolesRequest | select -ExpandProperty count
$eligibleRoles = $eligibleRolesRequest | select -ExpandProperty value
$selectedRole = $eligibleRoles | select $fmt_roleName, $fmt_roleScope, roleDefinitionId, scopedResource, roleDefinition, subject | Out-SelectorMenu -Title "Select a role"
if (-not $selectedRole) {
Write-Host "No role selected."
return
}
$reason = Read-Host -Prompt "Reason for activating $($selectedRole.Role)"
if (-not $reason) {
$reason = "No reason entered."
}
function ActivateNow {
# Activate the specified role right now for 8 hours
param ($selectedRole, $reason)
$resourceId = $selectedRole.roleDefinition.resourceId
if ($selectedRole.scopedResource) {
$resourceId = $selectedRole.scopedResource.id
}
$uri = "https://api.azrbac.mspim.azure.com/api/v2/privilegedAccess/aadroles/roleAssignmentRequests"
$header = @{
Authorization = "Bearer $(ConvertFrom-SecureString -AsPlainText (Get-AzAccessToken).Token)"
}
$body = @"
{
"roleDefinitionId": "$($selectedRole.roleDefinitionId)",
"resourceId": "$resourceId",
"subjectId": "$subjectId",
"assignmentState": "Active",
"type": "UserAdd",
"reason": "$reason",
"ticketNumber": "",
"ticketSystem": "",
"schedule": {
"type": "Once",
"startDateTime": null,
"endDateTime": null,
"duration": "PT8H"
},
"scopedResourceId": ""
}
"@
$header = @{
Authorization = "Bearer $(ConvertFrom-SecureString -AsPlainText (Get-AzAccessToken).Token)"
}
Write-Host Activating role $selectedRole.Role $selectedRole.Scope
Invoke-RestMethod -Method POST -Uri $uri -Body $body -Headers $header -ContentType "application/json"
}
ActivateNow $selectedRole $reason
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment