Public/Initialize-KritTcmServicePrincipal.ps1
|
function Initialize-KritTcmServicePrincipal { <# .SYNOPSIS Idempotently provision the TCM + companion M365 Admin Services service principals in the connected tenant. .DESCRIPTION Microsoft Tenant Configuration Management (TCM) APIs require two service principals present in the target tenant before any snapshot/monitor call: - Tenant Configuration Management (AppId 03b07b79-c5bc-4b5e-9bfa-13acf4a99998) - M365 Admin Services (AppId 6b91db1b-f05b-405a-a0b2-e3f60b28d645) This function checks for each via Get-MgServicePrincipal and creates only those missing. Re-runnable safely — already-present SPs return unchanged. .PARAMETER WhatIf Standard ShouldProcess — show what would be created without writing. .EXAMPLE Connect-MgGraph -Scopes Application.ReadWrite.All,AppRoleAssignment.ReadWrite.All Initialize-KritTcmServicePrincipal -WhatIf Initialize-KritTcmServicePrincipal .OUTPUTS PSCustomObject with TcmSp, M365AdminSp, AlreadyExisted, Created lists. #> [CmdletBinding(SupportsShouldProcess, ConfirmImpact='Medium')] param() if (-not (Get-Command Get-MgServicePrincipal -ErrorAction SilentlyContinue)) { throw 'Microsoft.Graph.Applications module not imported. Run Import-Module Microsoft.Graph.Applications + Connect-MgGraph first.' } $ctx = Get-MgContext -ErrorAction SilentlyContinue if (-not $ctx) { throw 'Not connected to Microsoft Graph. Run Connect-MgGraph -Scopes Application.ReadWrite.All,AppRoleAssignment.ReadWrite.All' } $result = [ordered]@{ Action = 'Initialize-KritTcmServicePrincipal' Tenant = $ctx.TenantId Timestamp = (Get-Date).ToUniversalTime().ToString('o') TcmSp = $null M365AdminSp = $null AlreadyExisted = @() Created = @() Errors = @() } foreach ($pair in @( @{ Name = 'Tenant Configuration Management'; AppId = (Get-KritTcmConstant -Name TcmServicePrincipalAppId); Key='TcmSp' } @{ Name = 'M365 Admin Services'; AppId = (Get-KritTcmConstant -Name M365AdminServicesAppId); Key='M365AdminSp' } )) { try { $existing = Get-MgServicePrincipal -Filter "AppId eq '$($pair.AppId)'" -ErrorAction Stop if ($existing) { $result.($pair.Key) = @{ AppId=$pair.AppId; ObjectId=$existing.Id; Existed=$true; DisplayName=$existing.DisplayName } $result.AlreadyExisted += $pair.Name continue } if ($PSCmdlet.ShouldProcess($pair.Name, "Create service principal (AppId=$($pair.AppId))")) { $sp = New-MgServicePrincipal -AppId $pair.AppId -ErrorAction Stop $result.($pair.Key) = @{ AppId=$pair.AppId; ObjectId=$sp.Id; Existed=$false; DisplayName=$sp.DisplayName } $result.Created += $pair.Name } } catch { $result.Errors += @{ Sp=$pair.Name; Error=$_.Exception.Message } } } [PSCustomObject]$result } |