Private/Get-CatalogResource.ps1
|
function Get-CatalogResource { <# .SYNOPSIS Finds a resource (any type) in a catalog by originId, with its scopes and roles. With -AddIfMissing it's added to the catalog first and polled until it shows up. .NOTES Internal helper. A resource in a catalog can be shared by many access packages - this module never removes a resource from a catalog. #> [CmdletBinding()] param( [Parameter(Mandatory = $true)] [string]$CatalogId, [Parameter(Mandatory = $true)] [object]$Spec, [Parameter(Mandatory = $false)] [switch]$AddIfMissing, [Parameter(Mandatory = $false)] [int]$MaxRetries = 6 ) $baseUri = "https://graph.microsoft.com/v1.0/identityGovernance/entitlementManagement" # originId can be a URL (SharePoint) - quote-escape for OData, then URL-encode $filterValue = [uri]::EscapeDataString(($Spec.OriginId -replace "'", "''")) $resourceUri = "$baseUri/catalogs/$CatalogId/resources?`$filter=originId eq '$filterValue'&`$expand=scopes" $findResource = { @(Get-GraphPagedResult -Uri $resourceUri | Where-Object { $_.id -and $_.originSystem -eq $Spec.OriginSystem }) | Select-Object -First 1 } $resource = & $findResource $addedToCatalog = $false if (-not $resource -and $AddIfMissing) { $body = @{ requestType = 'adminAdd' resource = @{ originId = $Spec.OriginId originSystem = $Spec.OriginSystem } catalog = @{ id = $CatalogId } } | ConvertTo-Json -Depth 5 try { Invoke-MgGraphRequest -Method POST -Uri "$baseUri/resourceRequests" ` -Body $body -ContentType 'application/json' -ErrorAction Stop | Out-Null $addedToCatalog = $true } catch { return [PSCustomObject]@{ Resource = $null; Roles = @(); AddedToCatalog = $false; Error = "Could not add resource to catalog: $($_.Exception.Message)" } } # The resource can take a few seconds to show up in the catalog $retries = 0 do { Start-Sleep -Seconds ([Math]::Min(2 * [Math]::Pow(2, $retries), 30)) $resource = & $findResource $retries++ } while (-not $resource -and $retries -lt $MaxRetries) } if (-not $resource) { $msg = if ($AddIfMissing) { "Resource was requested into the catalog but didn't show up after $MaxRetries retries" } else { 'Resource is not in the catalog' } return [PSCustomObject]@{ Resource = $null; Roles = @(); AddedToCatalog = $addedToCatalog; Error = $msg } } # Roles via resourceRoles - the documented way for every resource type $rolesUri = "$baseUri/catalogs/$CatalogId/resourceRoles?`$filter=(originSystem eq '$($Spec.OriginSystem)' and resource/id eq '$($resource.id)')&`$expand=resource" $roles = @() $retries = 0 do { try { $roles = @(Get-GraphPagedResult -Uri $rolesUri | Where-Object { $_.originId }) } catch { $roles = @() } if ($roles.Count -gt 0 -or -not $addedToCatalog) { break } Start-Sleep -Seconds 2 $retries++ } while ($retries -lt $MaxRetries) return [PSCustomObject]@{ Resource = $resource Roles = $roles AddedToCatalog = $addedToCatalog Error = $null } } |