Private/Invoke-RBACGraphGuardProbe.ps1
|
function Invoke-RBACGraphGuardProbe { <# .SYNOPSIS Enriches advisory Microsoft Graph / Entra guardrails with live detection. .DESCRIPTION Internal. Promotes the Entra identity guardrails that can be inspected via Microsoft Graph - Conditional Access policies and PIM-eligible directory roles - from 'Potential' to 'Blocking'/'Potential'/'Clear' with concrete evidence. Conditional Access applicability cannot be fully evaluated offline (it depends on sign-in signals), so an enabled policy targeting the principal surfaces as 'Potential' with the policy name rather than a hard 'Blocking'. Every probe is best-effort and StrictMode-safe: a missing Microsoft.Graph cmdlet or a query error leaves the guard at its advisory state. .PARAMETER Guard The advisory guards (PSAutoRBAC.Guard) for the Microsoft Graph platform. .PARAMETER CallerId The identity (object id) whose eligible directory roles are inspected. .PARAMETER Context Optional PSAutoRBAC.Context (unused for Graph today; reserved). .OUTPUTS PSCustomObject (PSAutoRBAC.Guard) #> [CmdletBinding()] [OutputType([psobject])] param( [Parameter(Mandatory)] [AllowEmptyCollection()] [psobject[]]$Guard, [Parameter()] [string]$CallerId, [Parameter()] [psobject]$Context ) $get = { param($o, $n) if ($o -and ($o.PSObject.Properties.Name -contains $n)) { $o.$n } } $byType = @{} foreach ($g in $Guard) { $byType[$g.GuardType] = $g } # 1) Conditional Access - enabled policies are potential gates at token issuance. if ($byType.ContainsKey('ConditionalAccess') -and (Get-Command -Name 'Get-MgIdentityConditionalAccessPolicy' -ErrorAction SilentlyContinue)) { $g = $byType['ConditionalAccess'] try { $enabled = @(Get-MgIdentityConditionalAccessPolicy -ErrorAction SilentlyContinue | Where-Object { (& $get $_ 'State') -eq 'enabled' }) if ($enabled.Count -gt 0) { $g.Status = 'Potential'; $g.Source = 'Live' $g.Evidence = @($enabled | ForEach-Object { "CA policy '$(& $get $_ 'DisplayName')'" } | Select-Object -First 10) Write-PSFMessage -Level Verbose -Message "Guard(Graph): $($enabled.Count) enabled Conditional Access policy/policies may gate '$CallerId'." -Tag 'PSAutoRBAC', 'Guard', 'Graph' } else { $g.Status = 'Clear'; $g.Source = 'Live' } } catch { Write-PSFMessage -Level Verbose -Message "Guard(Graph): Conditional Access probe failed ($($_.Exception.Message)); leaving advisory." -Tag 'PSAutoRBAC', 'Guard', 'Graph' } } # 2) PIM - directory role assigned as eligible (needs activation to be effective). if ($byType.ContainsKey('PrivilegedIdentityManagement') -and $CallerId -and (Get-Command -Name 'Get-MgRoleManagementDirectoryRoleEligibilitySchedule' -ErrorAction SilentlyContinue)) { $g = $byType['PrivilegedIdentityManagement'] try { $eligible = @(Get-MgRoleManagementDirectoryRoleEligibilitySchedule -Filter "principalId eq '$CallerId'" -ErrorAction SilentlyContinue) if ($eligible.Count -gt 0) { $g.Status = 'Potential'; $g.Source = 'Live' $g.Evidence = @($eligible | ForEach-Object { $r = & $get $_ 'RoleDefinitionId' "eligible directory role '$r' (activate before use)" }) Write-PSFMessage -Level Significant -Message "Guard(Graph): '$CallerId' has $($eligible.Count) PIM-eligible directory role(s) requiring activation." -Tag 'PSAutoRBAC', 'Guard', 'Graph' } else { $g.Status = 'Clear'; $g.Source = 'Live' } } catch { Write-PSFMessage -Level Verbose -Message "Guard(Graph): PIM probe failed ($($_.Exception.Message)); leaving advisory." -Tag 'PSAutoRBAC', 'Guard', 'Graph' } } $Guard } |