Private/Resolve-IntuneScopedPermissionImpact.ps1

function Resolve-IntuneScopedPermissionImpact {
    [CmdletBinding()]
    [OutputType([object[]])]
    param(
        [AllowEmptyCollection()] [object[]] $RoleAssignment,
        [ValidateSet('Unknown', 'LegacyMerged', 'Scoped')] [string] $TenantMode = 'Unknown'
    )

    $assignments = @($RoleAssignment)
    $permissionRecords = [System.Collections.Generic.List[object]]::new()
    $tagNames = @{
        '*' = 'All scope tags'
        '0' = 'Default'
        '?' = 'Unknown scope tag context'
    }

    foreach ($assignment in $assignments) {
        foreach ($tag in @(Get-IntuneAccessProperty $assignment 'ScopeTags' @())) {
            $tagId = [string] (Get-IntuneAccessProperty $tag 'Id')
            if (-not [string]::IsNullOrWhiteSpace($tagId)) {
                $tagNames[$tagId] = [string] (Get-IntuneAccessProperty $tag 'DisplayName' "Scope tag $tagId")
            }
        }

        foreach ($action in @(Get-IntuneAccessProperty $assignment 'Permissions' @())) {
            $metadata = ConvertFrom-IntuneAccessActionName -Action $action
            $scopeTagDataState = [string] (Get-IntuneAccessProperty $assignment 'ScopeTagDataState' 'Available')
            $scopeTagIds = if ($scopeTagDataState -eq 'Missing') {
                @('?')
            }
            else {
                $observedIds = @(Get-IntuneAccessProperty (Get-IntuneAccessProperty $assignment 'RawIds') 'ScopeTagIds' @())
                if ($observedIds.Count -eq 0) { @('*') } else { @($observedIds | ForEach-Object { [string] $_ }) }
            }

            $permissionRecords.Add([PSCustomObject] @{
                Assignment          = $assignment
                AssignmentId        = [string] (Get-IntuneAccessProperty $assignment 'Id')
                AssignmentName      = [string] (Get-IntuneAccessProperty $assignment 'Name')
                Applicability       = [string] (Get-IntuneAccessProperty $assignment 'Applicability' 'NotEvaluated')
                ScopeTagDataState   = $scopeTagDataState
                ScopeTagIds         = $scopeTagIds
                RawAction           = [string] $action
                Resource            = $metadata.Resource
                Operation           = $metadata.Operation
            })
        }
    }

    $rows = [System.Collections.Generic.List[object]]::new()
    foreach ($resourceGroup in @($permissionRecords | Group-Object Resource)) {
        $resourceRecords = @($resourceGroup.Group)
        $knownTagIds = @(
            $resourceRecords |
                Where-Object { $_.Applicability -eq 'Confirmed' -and $_.ScopeTagDataState -ne 'Missing' } |
                ForEach-Object ScopeTagIds |
                Where-Object { $_ -ne '*' } |
                Select-Object -Unique
        )
        $hasUnknownTagContext = @($resourceRecords | Where-Object ScopeTagDataState -EQ 'Missing').Count -gt 0
        $hasAllTagContext = @($resourceRecords | Where-Object {
            $_.Applicability -eq 'Confirmed' -and
            $_.ScopeTagDataState -ne 'Missing' -and
            '*' -in $_.ScopeTagIds
        }).Count -gt 0
        $contexts = if ($knownTagIds.Count -gt 0) {
            @($knownTagIds)
        }
        elseif ($hasAllTagContext -or -not $hasUnknownTagContext) {
            @('*')
        }
        else {
            @()
        }
        if ($hasUnknownTagContext) { $contexts += '?' }

        foreach ($tagId in @($contexts | Select-Object -Unique)) {
            foreach ($actionGroup in @($resourceRecords | Group-Object RawAction)) {
                $actionRecords = @($actionGroup.Group)
                $confirmedActionRecords = @($actionRecords | Where-Object Applicability -EQ 'Confirmed')
                $uncertainActionRecords = @($actionRecords | Where-Object Applicability -NE 'Confirmed')

                if ($tagId -eq '?') {
                    $legacySources = @()
                    $scopedSources = @()
                    $legacyState = 'NotEvaluated'
                    $scopedState = 'NotEvaluated'
                }
                else {
                    $legacySources = @($confirmedActionRecords)
                    $scopedSources = @($confirmedActionRecords | Where-Object {
                        $_.ScopeTagDataState -ne 'Missing' -and
                        ('*' -in $_.ScopeTagIds -or $tagId -in $_.ScopeTagIds)
                    })
                    $unknownScopedSource = @($confirmedActionRecords | Where-Object ScopeTagDataState -EQ 'Missing').Count -gt 0

                    $legacyState = if ($legacySources.Count -gt 0) {
                        'Allowed'
                    }
                    elseif ($uncertainActionRecords.Count -gt 0) {
                        'NotEvaluated'
                    }
                    else {
                        'NotGranted'
                    }

                    $scopedState = if ($scopedSources.Count -gt 0) {
                        'Allowed'
                    }
                    elseif ($unknownScopedSource -or $uncertainActionRecords.Count -gt 0) {
                        'NotEvaluated'
                    }
                    else {
                        'NotGranted'
                    }
                }

                $change = if ($legacyState -eq 'NotEvaluated' -or $scopedState -eq 'NotEvaluated') {
                    'NotEvaluated'
                }
                elseif ($legacyState -eq 'Allowed' -and $scopedState -eq 'NotGranted') {
                    'PermissionReduction'
                }
                else {
                    'NoChange'
                }

                $effectiveState = switch ($TenantMode) {
                    'LegacyMerged' { $legacyState }
                    'Scoped' { $scopedState }
                    default { 'NotEvaluated' }
                }

                $rows.Add([PSCustomObject] @{
                    PSTypeName       = 'IntuneAccess.ScopedPermissionImpactRow'
                    Resource         = $resourceGroup.Name
                    ScopeTagId        = $tagId
                    ScopeTagName      = if ($tagNames.ContainsKey($tagId)) { $tagNames[$tagId] } else { "[Unresolved scope tag: $tagId]" }
                    RawAction         = $actionGroup.Name
                    Operation         = $actionRecords[0].Operation
                    LegacyState       = $legacyState
                    ScopedState       = $scopedState
                    EffectiveState    = $effectiveState
                    Change            = $change
                    LegacyGrantedBy   = @($legacySources | ForEach-Object Assignment)
                    ScopedGrantedBy   = @($scopedSources | ForEach-Object Assignment)
                    UncertainSources  = @($uncertainActionRecords | ForEach-Object Assignment)
                })
            }
        }
    }

    return @($rows | Sort-Object Resource, ScopeTagName, Operation)
}