Automating Azure AD PIM Role Activation

Automating Azure AD PIM Role Activation: What I Actually Use

If you’ve ever had to activate the same PIM roles every morning—Global Reader, Exchange Admin, SharePoint Admin—you know the drill. Log into the portal, click through the PIM blade, wait for MFA, type a justification, hit activate… then repeat for each role. It’s fine once or twice. But doing this daily? It gets old fast.

I hit that wall around mid-2023. I was managing a hybrid setup with multiple tenants, and activating roles manually became a bottleneck. So I built a PowerShell script that automates the whole thing using Microsoft Graph. It’s not magic, but it saves me 10–15 minutes every day—and keeps audit logs clean.

Why I Needed This

  • I manage couple of Microsoft M365 tenants (Exchange, SharePoint Online, Teams, etc… )
  • I run compliance reports every morning—Global Reader is a must.
  • Mailbox cleanup? Exchange Admin.
  • SharePoint site provisioning? Yep, another role.

Sure, here’s a more natural, conversational rephrasing that fits the tone of your humanized article:

Each tenant I manage enforces PIM roles as part of their security posture, so before I touch anything—whether it’s Exchange, SharePoint, or compliance settings—I have to activate the relevant roles. I used to do this manually, one tenant at a time, one role at a time. But as my workload grew and the number of tenants piled up, so did the number of daily activations. It started eating into my mornings more than I’d like to admit.

The tipping point? I ran a mailbox cleanup script without activating Exchange Admin. No errors, no warnings—just a silent fail. That was enough for me to stop winging it and build a proper automation.

What You’ll Need (No Surprises Here)

  • PowerShell Modules:
  Install-Module Microsoft.Graph -Scope CurrentUser -Force
  Install-Module MSAL.PS         -Scope CurrentUser -Force
  • Entra ID P1/P2 license: PIM won’t work without it.
  • App Registration:
    Create one, add delegated permissions, and grant admin consent.
  • Required API permissions:
    • User.Read
    • RoleEligibilitySchedule.Read.Directory
    • RoleAssignmentSchedule.ReadWrite.Directory

The Script That Does the Job

Here’s the core idea: authenticate via device code, grab all eligible roles, and activate them one by one with a justification comment. I run this on a dev VM—Windows 11, 16GB RAM, nothing fancy.

# Authenticate with Microsoft Graph
$token = Get-MsalToken -TenantId $TenantId -ClientId $ClientId -Scopes $scopes -DeviceCode
$accessToken = $token.AccessToken
$headers = @{ Authorization = "Bearer $accessToken"; "Content-Type" = "application/json" }

# Get current user info
$me = Invoke-RestMethod -Method GET -Headers $headers -Uri "https://graph.microsoft.com/v1.0/me"

# Fetch eligible roles
$eligibles = @()
$u = "https://graph.microsoft.com/v1.0/roleManagement/directory/roleEligibilitySchedules?`$filter=principalId eq '$($me.id)'&`$expand=roleDefinition"
while ($u) {
  $resp = Invoke-RestMethod -Method GET -Headers $headers -Uri $u
  $eligibles += $resp.value
  $u = $resp.'@odata.nextLink'
}

# Activate each role
foreach ($er in $eligibles) {
  $body = @{
    action           = "selfActivate"
    principalId      = $me.id
    roleDefinitionId = $er.roleDefinitionId
    directoryScopeId = $er.directoryScopeId ?? "/"
    justification    = "$Justification - $($er.roleDefinition.displayName) - $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')"
    scheduleInfo     = @{
      startDateTime = (Get-Date).ToUniversalTime().ToString("o")
      expiration    = @{ type = "afterDuration"; duration = "PT${DurationHours}H" }
    }
  }

  try {
    $resp = Invoke-RestMethod -Method POST -Headers $headers `
      -Uri "https://graph.microsoft.com/v1.0/roleManagement/directory/roleAssignmentScheduleRequests" `
      -Body ($body | ConvertTo-Json -Depth 10)
    Write-Host "Activated: $($er.roleDefinition.displayName)" -ForegroundColor Green
  } catch {
    $msg = $_.Exception.Message
    if ($msg -match 'AlreadyActive') {
      Write-Host "$($er.roleDefinition.displayName) already active—skipping." -ForegroundColor DarkGray
    } elseif ($msg -match 'MfaRule') {
      Write-Error "MFA required. Make sure your login was challenged."
    } elseif ($msg -match 'ApprovalRequired') {
      Write-Warning "Approval required—request pending."
    } else {
      throw
    }
  }
}

I’ve wrapped this in a param block so I can pass in TenantId, ClientId, and even filter by role names if needed.

Running It

Here’s how I run it on my end:

.\Activate-MyPIMRoles-REST.ps1 `
  -TenantId "12344-1e2f-XXX-990d-XXXXXX0ca114" `
  -ClientId "XXXXX-2c4d-XXXX-aaf7-XXXXXX3c5e35"

You’ll get a device code and a login URL. Authenticate with the user who has eligible PIM roles. The script takes care of the rest.

A Few Gotchas

  • MFA: If PIM enforces MFA, you’ll need to authenticate interactively. For unattended runs, use a service principal or managed identity—but only if MFA isn’t enforced at activation.
  • Approval workflows: If a role needs approval, the request will sit until someone approves it. No way around that.
  • Security trade-offs: If you’re activating the same role daily, maybe it shouldn’t be eligible. Just saying.
  • Scheduling: I’ve used Azure Automation and Windows Task Scheduler. Both work fine.

Final Thought

This script isn’t perfect, but it’s saved me hours of clicking through the portal. I still get audit logs, MFA prompts, and approval workflows when needed. But for roles I use daily, this is a no-brainer.

If you’ve built something similar—or hit weird edge cases like role scope mismatches or token expiry mid-run—drop a note. Always happy to trade war stories.

Ever tried activating PIM roles from a Logic App with managed identity? That’s next on my list…

PShivkumar

About the author: PShivkumar

With over 12 years of experience in IT and multiple certifications from Microsoft, our creator brings deep expertise in Exchange Server, Exchange Online, Windows OS, Teams, SharePoint, and virtualization. Scenario‑first guidance shaped by real incidents and recoveries Clear, actionable breakdowns of complex Microsoft ecosystems Focus on practicality, reliability, and repeatable workflows Whether supporting Microsoft technologies—server, client, or cloud—his work blends precision with creativity, making complex concepts accessible, practical, and engaging for professionals across the IT spectrum.

View all posts →

Comments

📝 Leave a Comment