invoke-EntraIDPimElevations.ps1


<#PSScriptInfo
 
.VERSION 1.1
 
.GUID 78e7abb6-aeae-4486-81e8-9b61e8b2e3e3
 
.AUTHOR JanKetilSkanke
 
.COMPANYNAME
 
.COPYRIGHT
 
.TAGS
 
.LICENSEURI
 
.PROJECTURI
 
.ICONURI
 
.EXTERNALMODULEDEPENDENCIES Microsoft.Graph.Users, Microsoft.Graph.Identity.Governance
 
.REQUIREDSCRIPTS
 
.EXTERNALSCRIPTDEPENDENCIES
 
.RELEASENOTES
 
 
.PRIVATEDATA
 
#>


<#
.SYNOPSIS
    Name: invoke-EntraIDPimElevations.ps1
    Script to activate Eligible roles in Entra ID PIM for a user
 
.DESCRIPTION
    Script to activate Eligible roles in Entra ID PIM for a user
 
.PARAMETER RolesToActivate
    Comma separated list of roles to activate, Example -RolesToActivate "Global Reader, Intune Administrator"
 
.PARAMETER Justification
    Justification for activating the roles
 
.PARAMETER ActivationDuration
    Duration in hours for the activation, default is 8 hours
 
.PARAMETER GetAvailableRoles
    Switch to get all available eligible roles for the user
 
.EXAMPLE
  invoke-EntraIDPimElevations.ps1 -RolesToActivate "Global Reader, Intune Administrator" -Justification "Testing" -ActivationDuration 4
  invoke-EntraIDPimElevations.ps1 -GetAvailableRoles
 
.NOTES
    Version: 1.1
    Author: Jan Ketil Skanke (@JankeSkanke)
    Creation Date: 2023-12-13
    Purpose/Change: Initial script development
    Author: Jan Ketil Skanke
    Contact: @JankeSkanke
    Created: 2023-12-13
    Version history:
    1.1.0 - (2023-12-13) Script Created
#>

#Requires -Modules Microsoft.Graph.Identity.Governance, Microsoft.Graph.Users
param (
    [Parameter(Mandatory=$true, ParameterSetName='ActivateRoles', HelpMessage="Specifies the roles to activate.")]
    [ValidateNotNullOrEmpty()]
    [string]$RolesToActivate,
    [Parameter(Mandatory=$true, ParameterSetName='ActivateRoles', HelpMessage="Specifies justification for activation.")]
    [ValidateNotNullOrEmpty()]
    [ValidateLength(6, 200)]
    [string]$Justification,
    [Parameter(Mandatory=$false, ParameterSetName='ActivateRoles', HelpMessage="Specifies the duration of the activation.")]
    [int]$ActivationDuration = 8,
    [Parameter(Mandatory=$true, ParameterSetName='GetRoles', HelpMessage="Get all available eligible roles for the user.")]
    [switch]$GetAvailableRoles
)
# Clear out any existing tokens
Disconnect-MgGraph -ErrorAction SilentlyContinue | Out-Null
# Connect to Graph
try {
    Connect-MgGraph -NoWelcome -ErrorAction Stop
    # Get auth context
    $MyContext = Get-MgContext
    $Me = (Get-MgUser -UserId $MyContext.Account).Id
    Write-Output "Connected as $($MyContext.Account)"     
}
catch {
    Write-Warning "Failed to connect to Graph: $($_.Exception.Message), exiting script"
    exit
}

# Try to get all eligible roles for user
try {
    $myRoles = Get-MgRoleManagementDirectoryRoleEligibilitySchedule -ExpandProperty RoleDefinition -All -Filter "principalId eq '$Me'" -ErrorAction Stop
    if($myRoles.count -eq 0) {
        Write-Warning "No eligible roles found, exiting script"
        exit
    }
}
catch {
    Write-Warning "Failed to get eligible roles: $($_.Exception.Message), exiting script"
    exit
}

if ($GetAvailableRoles) {
    Write-Output "You have $($myroles.count) eligible roles and they are:"
    Write-Output $($myRoles.RoleDefinition.DisplayName | Sort-Object | Format-Table)
    exit
}
if ($RolesToActivate ) {
    $MyRolesNames = $myRoles.RoleDefinition.DisplayName
    $Roles = $RolesToActivate.Split(",") | ForEach-Object { $_.Trim() }
    foreach ($role in $Roles) {
        if ($role -notin $MyRolesNames) {
            Write-Warning "Role $role is not eligible for you to activate, exiting script"
            exit
        }
    }
    Write-Host "You are about to activate the following roles:" -ForegroundColor Green
    Write-Output $Roles | Sort-Object | Format-Table
    Write-Output "This will be active for $($ActivationDuration) hours"
    Write-Host "Are you sure you want to continue? (Y/N)" -ForegroundColor Yellow
    $answer = Read-Host
    if ($answer -ne "Y") {
        Write-Output "Exiting script"
        exit
    }
}


Write-Output "Activating roles: $RolesToActivate"
Write-Output "Reason: $Justification"
# Convert the roles to an array
$Roles = $RolesToActivate.Split(",") | ForEach-Object { $_.Trim() }

# Activate the roles
foreach ($role in $Roles) {
    $myRole = $myroles | Where-Object {$_.RoleDefinition.DisplayName -eq $role}
    #Write-Output $myRole
    $params = @{
        Action = "selfActivate"
        PrincipalId = $myRole.PrincipalId
        RoleDefinitionId = $myRole.RoleDefinitionId
        DirectoryScopeId = $myRole.DirectoryScopeId
        Justification = "Enable $role role with reason $Justification"
        ScheduleInfo = @{
            StartDateTime = Get-Date
            Expiration = @{
                Type = "AfterDuration"
                Duration = "PT$($ActivationDuration)H"
            }
        }
    }
    try {
        $Activation = New-MgRoleManagementDirectoryRoleAssignmentScheduleRequest -BodyParameter $params -ErrorAction Stop
        Write-Output "Activated role $($role) for $($ActivationDuration) hours from UTC $($Activation.ScheduleInfo.StartDateTime) and will expire at UTC $($Activation.ScheduleInfo.StartDateTime.AddHours($ActivationDuration))" 
    }
    catch {
        <#Do this if a terminating exception happens#>
        Write-Warning "Error activating role $($role): $($_.Exception.Message)"
        
    }
}