Private/RoleManagement/Invoke-PIMActivationWithAuthContextToken.ps1
|
function Invoke-PIMActivationWithAuthContextToken { <# .SYNOPSIS Performs immediate PIM role activation using a pre-obtained authentication context token. .DESCRIPTION Makes direct REST API calls to activate PIM roles immediately after obtaining the correct authentication context token, eliminating timing issues. .PARAMETER ActivationParams Hashtable containing the activation request parameters. .PARAMETER RoleType Type of role being activated ('Entra' or 'Group'). .PARAMETER AuthContextToken The authentication context token to use for the activation. #> [CmdletBinding()] param( [Parameter(Mandatory)] [hashtable]$ActivationParams, [Parameter(Mandatory)] [ValidateSet('Entra', 'Group')] [string]$RoleType, [Parameter(Mandatory)] [string]$AuthContextToken ) try { Write-Verbose "Performing immediate activation with authentication context token" # Prepare REST API headers with the authentication context token $headers = @{ 'Authorization' = "Bearer $AuthContextToken" 'Content-Type' = 'application/json' } # Convert activation parameters to the format expected by Microsoft Graph REST API $restParams = @{ Action = "selfActivate" PrincipalId = $ActivationParams.principalId Justification = $ActivationParams.justification ScheduleInfo = @{ StartDateTime = (Get-Date).ToUniversalTime().ToString("yyyy-MM-dd'T'HH:mm:ss.fff'Z'") Expiration = @{ Type = "AfterDuration" Duration = $ActivationParams.scheduleInfo.expiration.duration } } } # Add role-specific parameters and determine the correct REST API endpoint $apiUri = "" switch ($RoleType) { 'Entra' { $restParams.RoleDefinitionId = $ActivationParams.roleDefinitionId $restParams.DirectoryScopeId = if ([string]::IsNullOrEmpty($ActivationParams.directoryScopeId)) { "/" } else { $ActivationParams.directoryScopeId } $apiUri = "https://graph.microsoft.com/v1.0/roleManagement/directory/roleAssignmentScheduleRequests" # Add ticket info only if present and required if ($ActivationParams.ContainsKey('ticketInfo') -and $ActivationParams.ticketInfo) { $restParams.TicketInfo = $ActivationParams.ticketInfo } } 'Group' { $restParams.GroupId = $ActivationParams.groupId $restParams.AccessId = $ActivationParams.accessId $apiUri = "https://graph.microsoft.com/v1.0/identityGovernance/privilegedAccess/group/assignmentScheduleRequests" # Add ticket info only if present and required if ($ActivationParams.ContainsKey('ticketInfo') -and $ActivationParams.ticketInfo) { $restParams.TicketInfo = $ActivationParams.ticketInfo } } } Write-Verbose "Submitting immediate PIM activation request" Write-Verbose "API URI: $apiUri" Write-Verbose "Parameters: $($restParams | ConvertTo-Json -Depth 5 -Compress)" # Submit activation request using direct REST API call - IMMEDIATE execution $requestBody = $restParams | ConvertTo-Json -Depth 5 $activationStartTime = Get-Date $response = Invoke-RestMethod -Uri $apiUri -Headers $headers -Method Post -Body $requestBody -ErrorAction Stop $activationDuration = (Get-Date) - $activationStartTime Write-Verbose "PIM activation successful with authentication context - Response ID: $($response.Id) (completed in $($activationDuration.TotalSeconds) seconds)" return @{ Success = $true; Response = $response; IsAzureResource = $false } } catch { # Enhanced error handling for authentication context activations Write-Verbose "Authentication context activation failed: $($_.Exception.Message)" $errorDetails = $null # Capture error details from REST API responses if ($_.Exception -is [System.Net.WebException]) { $webException = $_.Exception if ($webException.Response) { try { $responseStream = $webException.Response.GetResponseStream() $reader = New-Object System.IO.StreamReader($responseStream) $responseBody = $reader.ReadToEnd() $reader.Close() # Try to parse the error response try { $errorResponse = $responseBody | ConvertFrom-Json if ($errorResponse -and $errorResponse.error) { $errorDetails = $errorResponse.error.message if ($errorResponse.error.code -eq "RoleAssignmentRequestAcrsValidationFailed") { Write-Verbose "Authentication context validation failed - token may be invalid or expired" } } else { $errorDetails = $responseBody } } catch { $errorDetails = $responseBody } } catch { $errorDetails = $webException.Message } } } # Fallback to standard PowerShell error details if (-not $errorDetails -and $_.ErrorDetails -and $_.ErrorDetails.Message) { $errorDetails = $_.ErrorDetails.Message } return @{ Success = $false; Error = $_; ErrorDetails = $errorDetails; IsAzureResource = $false } } } |