Public/Grant-KritTcmGraphPermission.ps1
|
function Grant-KritTcmGraphPermission { <# .SYNOPSIS Grant Microsoft Graph application permissions to the TCM service principal so TCM can impersonate calls to workload endpoints during snapshot / monitor runs. .DESCRIPTION Reproduces the documented PowerShell snippet from https://learn.microsoft.com/en-us/graph/utcm-authentication-setup as a typed, idempotent function with structured output. Pass an array of Graph application permission names (e.g. 'User.ReadWrite.All', 'Policy.Read.All'). The function looks up each AppRole on the Microsoft Graph service principal then creates the AppRoleAssignment on the TCM SP. Already- granted permissions are detected via existing AppRoleAssignment query and skipped. For Exchange Online permissions, additional configuration via Application Access Policies is required — see Microsoft docs link in the warning output. .PARAMETER Permissions Array of Graph application permission display names (the .Value field on AppRole). .EXAMPLE Grant-KritTcmGraphPermission -Permissions 'User.ReadWrite.All','Policy.Read.All' -WhatIf Grant-KritTcmGraphPermission -Permissions 'User.ReadWrite.All','Policy.Read.All' .OUTPUTS Per-permission PSCustomObject (Permission, Granted, AlreadyExisted, Error). #> [CmdletBinding(SupportsShouldProcess, ConfirmImpact='Medium')] param( [Parameter(Mandatory, ValueFromPipeline)][string[]]$Permissions ) begin { $tcmAppId = Get-KritTcmConstant -Name TcmServicePrincipalAppId $graphAppId = Get-KritTcmConstant -Name MsGraphAppId $graphSp = Get-MgServicePrincipal -Filter "AppId eq '$graphAppId'" -ErrorAction Stop if (-not $graphSp) { throw "Microsoft Graph service principal not found in tenant (AppId $graphAppId)." } $tcmSp = Get-MgServicePrincipal -Filter "AppId eq '$tcmAppId'" -ErrorAction Stop if (-not $tcmSp) { throw "TCM service principal not found. Run Initialize-KritTcmServicePrincipal first." } $existingAssignments = @(Get-MgServicePrincipalAppRoleAssignment -ServicePrincipalId $tcmSp.Id -All -ErrorAction Stop) } process { foreach ($perm in $Permissions) { $row = [ordered]@{ Action='Grant-TcmGraphPermission'; Permission=$perm; TcmSpObjectId=$tcmSp.Id Granted=$false; AlreadyExisted=$false; Error=$null Timestamp=(Get-Date).ToUniversalTime().ToString('o') } try { $appRole = $graphSp.AppRoles | Where-Object { $_.Value -eq $perm -and $_.AllowedMemberTypes -contains 'Application' } | Select-Object -First 1 if (-not $appRole) { $row.Error = "No application AppRole with value '$perm' on Microsoft Graph SP." [PSCustomObject]$row; continue } $already = $existingAssignments | Where-Object { $_.AppRoleId -eq $appRole.Id -and $_.ResourceId -eq $graphSp.Id } if ($already) { $row.AlreadyExisted = $true [PSCustomObject]$row; continue } if ($PSCmdlet.ShouldProcess($perm, "Grant Graph application permission to TCM SP")) { $body = @{ AppRoleId = $appRole.Id; ResourceId = $graphSp.Id; PrincipalId = $tcmSp.Id } New-MgServicePrincipalAppRoleAssignment -ServicePrincipalId $tcmSp.Id -BodyParameter $body -ErrorAction Stop | Out-Null $row.Granted = $true } } catch { $row.Error = $_.Exception.Message } [PSCustomObject]$row } } end { Write-Verbose "For Exchange Online permissions also configure: https://learn.microsoft.com/en-us/exchange/permissions-exo/application-rbac" } } |