Public/Test-IntuneGroupRemoval.ps1
|
function Test-IntuneGroupRemoval { [CmdletBinding()] param( [Parameter()] [string]$UserPrincipalNames, [Parameter()] [string]$SimulateRemoveTargetGroup, [Parameter()] [string]$GroupNames, [Parameter()] [switch]$ExportToCSV, [Parameter()] [string]$ExportPath, [Parameter()] [string]$ScopeTagFilter ) Write-Host "Group Membership Removal Impact Analysis selected" -ForegroundColor Green # Get User Principal Name if ($UserPrincipalNames) { $simUpnInput = $UserPrincipalNames } else { Write-Host "Please enter the User Principal Name: " -ForegroundColor Cyan $simUpnInput = Read-Host } if ([string]::IsNullOrWhiteSpace($simUpnInput)) { Write-Host "No UPN provided. Please try again with a valid UPN." -ForegroundColor Red return } $simUpn = ($simUpnInput -split ',')[0].Trim() # Validate UPN format if ($simUpn -notmatch '^[^@\s]+@[^@\s]+\.[^@\s]+$') { Write-Host "Invalid UPN format: '$simUpn'. Expected: user@domain.com" -ForegroundColor Red return } # Get Target Group - SimulateRemoveTargetGroup takes precedence over GroupNames if ($SimulateRemoveTargetGroup) { $simGroupInput = $SimulateRemoveTargetGroup } elseif ($GroupNames) { $simGroupInput = $GroupNames } else { Write-Host "Please enter the Target Group name or Object ID: " -ForegroundColor Cyan Write-Host "Example: 'Marketing Team' or '12345678-1234-1234-1234-123456789012'" -ForegroundColor Gray $simGroupInput = Read-Host } if ([string]::IsNullOrWhiteSpace($simGroupInput)) { Write-Host "No group provided. Please try again." -ForegroundColor Red return } $simGroupInput = ($simGroupInput -split ',')[0].Trim() # Resolve user Write-Host "Looking up user: $simUpn" -ForegroundColor Yellow $simUserInfo = Get-UserInfo -UserPrincipalName $simUpn if (-not $simUserInfo.Success) { Write-Host "User not found: $simUpn" -ForegroundColor Red return } # Resolve target group Write-Host "Looking up group: $simGroupInput" -ForegroundColor Yellow $simTargetGroupId = $null $simTargetGroupName = $null if ($simGroupInput -match '^[0-9a-fA-F]{8}-([0-9a-fA-F]{4}-){3}[0-9a-fA-F]{12}$') { $simGroupInfo = Get-GroupInfo -GroupId $simGroupInput if (-not $simGroupInfo.Success) { Write-Host "No group found with ID: $simGroupInput" -ForegroundColor Red return } $simTargetGroupId = $simGroupInfo.Id $simTargetGroupName = $simGroupInfo.DisplayName } else { $simGroupUri = "$GraphEndpoint/v1.0/groups?`$filter=displayName eq '$simGroupInput'" $simGroupResponse = Invoke-MgGraphRequest -Uri $simGroupUri -Method Get if ($simGroupResponse.value.Count -eq 0) { Write-Host "No group found with name: $simGroupInput" -ForegroundColor Red return } elseif ($simGroupResponse.value.Count -gt 1) { Write-Host "Multiple groups found with name: $simGroupInput. Please use the Object ID instead:" -ForegroundColor Red foreach ($g in $simGroupResponse.value) { Write-Host " - $($g.displayName) (ID: $($g.id))" -ForegroundColor Yellow } return } $simTargetGroupId = $simGroupResponse.value[0].id $simTargetGroupName = $simGroupResponse.value[0].displayName } Write-Host "Target group: $simTargetGroupName (ID: $simTargetGroupId)" -ForegroundColor Green # Get user's current group memberships try { $simUserGroups = Get-GroupMemberships -ObjectId $simUserInfo.Id -ObjectType "User" $simCurrentGroupIds = @($simUserGroups | Where-Object { $_.id } | ForEach-Object { $_.id }) } catch { Write-Host "Error fetching group memberships: $($_.Exception.Message)" -ForegroundColor Red return } # Check if user is a member of the target group (required for removal simulation) $isMember = $simCurrentGroupIds -contains $simTargetGroupId if (-not $isMember) { Write-Host "`nUser '$simUpn' is NOT a member of '$simTargetGroupName'. Nothing to simulate." -ForegroundColor Red return } # Get target group's parent groups (transitive) $simTargetParentGroups = Get-TransitiveGroupMembership -GroupId $simTargetGroupId $simTargetAllGroupIds = @($simTargetGroupId) if ($simTargetParentGroups) { $simTargetAllGroupIds += $simTargetParentGroups.id } # Build simulated group set (current MINUS target and target's parents) $simSimulatedGroupIds = @($simCurrentGroupIds | Where-Object { $simTargetAllGroupIds -notcontains $_ }) Write-Host "Analyzing removal impact..." -ForegroundColor Yellow $totalCategories = 18 $currentCategory = 0 # Initialize delta collections $deltaPolicies = @{ DeviceConfigs = [System.Collections.ArrayList]::new() SettingsCatalog = [System.Collections.ArrayList]::new() CompliancePolicies = [System.Collections.ArrayList]::new() AppProtectionPolicies = [System.Collections.ArrayList]::new() AppConfigurationPolicies = [System.Collections.ArrayList]::new() AppsRequired = [System.Collections.ArrayList]::new() AppsAvailable = [System.Collections.ArrayList]::new() AppsUninstall = [System.Collections.ArrayList]::new() PlatformScripts = [System.Collections.ArrayList]::new() HealthScripts = [System.Collections.ArrayList]::new() AntivirusProfiles = [System.Collections.ArrayList]::new() DiskEncryptionProfiles = [System.Collections.ArrayList]::new() FirewallProfiles = [System.Collections.ArrayList]::new() EndpointDetectionProfiles = [System.Collections.ArrayList]::new() AttackSurfaceProfiles = [System.Collections.ArrayList]::new() AccountProtectionProfiles = [System.Collections.ArrayList]::new() DeploymentProfiles = [System.Collections.ArrayList]::new() ESPProfiles = [System.Collections.ArrayList]::new() CloudPCProvisioningPolicies = [System.Collections.ArrayList]::new() CloudPCUserSettings = [System.Collections.ArrayList]::new() } $conflictPolicies = [System.Collections.ArrayList]::new() # --- Device Configurations --- $currentCategory++ Write-Host "[$currentCategory/$totalCategories] Fetching Device Configurations..." -ForegroundColor Yellow $simDeviceConfigs = Get-IntuneEntities -EntityType "deviceConfigurations" foreach ($config in $simDeviceConfigs) { $assignments = Get-IntuneAssignments -EntityType "deviceConfigurations" -EntityId $config.id $delta = Resolve-SimulatedAssignmentDelta -Assignments $assignments -CurrentGroupIds $simCurrentGroupIds -SimulatedGroupIds $simSimulatedGroupIds -TargetGroupIds $simTargetAllGroupIds -IncludeReasons @("All Users") if ($delta.IsLostPolicy) { $config | Add-Member -NotePropertyName 'AssignmentReason' -NotePropertyValue $delta.CurrentStatus -Force [void]$deltaPolicies.DeviceConfigs.Add($config) } elseif ($delta.IsConflict) { [void]$conflictPolicies.Add([PSCustomObject]@{ Category = "Device Configuration"; PolicyName = if ($config.displayName) { $config.displayName } else { $config.name }; PolicyId = $config.id; ConflictType = "Currently included; removal would expose exclusion" }) } } # --- Settings Catalog --- $currentCategory++ Write-Host "[$currentCategory/$totalCategories] Fetching Settings Catalog Policies..." -ForegroundColor Yellow $simSettingsCatalog = Get-IntuneEntities -EntityType "configurationPolicies" foreach ($policy in $simSettingsCatalog) { $assignments = Get-IntuneAssignments -EntityType "configurationPolicies" -EntityId $policy.id $delta = Resolve-SimulatedAssignmentDelta -Assignments $assignments -CurrentGroupIds $simCurrentGroupIds -SimulatedGroupIds $simSimulatedGroupIds -TargetGroupIds $simTargetAllGroupIds -IncludeReasons @("All Users") if ($delta.IsLostPolicy) { $policy | Add-Member -NotePropertyName 'AssignmentReason' -NotePropertyValue $delta.CurrentStatus -Force [void]$deltaPolicies.SettingsCatalog.Add($policy) } elseif ($delta.IsConflict) { [void]$conflictPolicies.Add([PSCustomObject]@{ Category = "Settings Catalog"; PolicyName = if ($policy.displayName) { $policy.displayName } else { $policy.name }; PolicyId = $policy.id; ConflictType = "Currently included; removal would expose exclusion" }) } } # --- Compliance Policies --- $currentCategory++ Write-Host "[$currentCategory/$totalCategories] Fetching Compliance Policies..." -ForegroundColor Yellow $simCompliancePolicies = Get-IntuneEntities -EntityType "deviceCompliancePolicies" foreach ($policy in $simCompliancePolicies) { $assignments = Get-IntuneAssignments -EntityType "deviceCompliancePolicies" -EntityId $policy.id $delta = Resolve-SimulatedAssignmentDelta -Assignments $assignments -CurrentGroupIds $simCurrentGroupIds -SimulatedGroupIds $simSimulatedGroupIds -TargetGroupIds $simTargetAllGroupIds -IncludeReasons @("All Users") if ($delta.IsLostPolicy) { $policy | Add-Member -NotePropertyName 'AssignmentReason' -NotePropertyValue $delta.CurrentStatus -Force [void]$deltaPolicies.CompliancePolicies.Add($policy) } elseif ($delta.IsConflict) { [void]$conflictPolicies.Add([PSCustomObject]@{ Category = "Compliance Policy"; PolicyName = if ($policy.displayName) { $policy.displayName } else { $policy.name }; PolicyId = $policy.id; ConflictType = "Currently included; removal would expose exclusion" }) } } # --- App Protection Policies --- $currentCategory++ Write-Host "[$currentCategory/$totalCategories] Fetching App Protection Policies..." -ForegroundColor Yellow $simAppProtectionPolicies = Get-IntuneEntities -EntityType "deviceAppManagement/managedAppPolicies" foreach ($policy in $simAppProtectionPolicies) { $policyType = $policy.'@odata.type' $assignmentsUri = switch ($policyType) { "#microsoft.graph.androidManagedAppProtection" { "$GraphEndpoint/beta/deviceAppManagement/androidManagedAppProtections('$($policy.id)')/assignments" } "#microsoft.graph.iosManagedAppProtection" { "$GraphEndpoint/beta/deviceAppManagement/iosManagedAppProtections('$($policy.id)')/assignments" } "#microsoft.graph.windowsManagedAppProtection" { "$GraphEndpoint/beta/deviceAppManagement/windowsManagedAppProtections('$($policy.id)')/assignments" } default { $null } } if ($assignmentsUri) { try { $assignmentResponse = Invoke-MgGraphRequest -Uri $assignmentsUri -Method Get $assignments = @() foreach ($assignment in $assignmentResponse.value) { $assignmentReason = $null switch ($assignment.target.'@odata.type') { '#microsoft.graph.allLicensedUsersAssignmentTarget' { $assignmentReason = "All Users" } '#microsoft.graph.groupAssignmentTarget' { $assignmentReason = "Group Assignment" } '#microsoft.graph.exclusionGroupAssignmentTarget' { $assignmentReason = "Group Exclusion" } } if ($assignmentReason) { $rawFilterId = $assignment.target.deviceAndAppManagementAssignmentFilterId $rawFilterType = $assignment.target.deviceAndAppManagementAssignmentFilterType $effFilterId = $null $effFilterType = $null if ($rawFilterType -and $rawFilterType -ne 'none' -and $rawFilterId -and $rawFilterId -ne '00000000-0000-0000-0000-000000000000') { $effFilterId = $rawFilterId $effFilterType = $rawFilterType } $assignments += @{ Reason = $assignmentReason GroupId = $assignment.target.groupId FilterId = $effFilterId FilterType = $effFilterType } } } if ($assignments.Count -gt 0) { $delta = Resolve-SimulatedAssignmentDelta -Assignments $assignments -CurrentGroupIds $simCurrentGroupIds -SimulatedGroupIds $simSimulatedGroupIds -TargetGroupIds $simTargetAllGroupIds -IncludeReasons @("All Users") if ($delta.IsLostPolicy) { $policy | Add-Member -NotePropertyName 'AssignmentReason' -NotePropertyValue $delta.CurrentStatus -Force [void]$deltaPolicies.AppProtectionPolicies.Add($policy) } elseif ($delta.IsConflict) { [void]$conflictPolicies.Add([PSCustomObject]@{ Category = "App Protection Policy"; PolicyName = $policy.displayName; PolicyId = $policy.id; ConflictType = "Currently included; removal would expose exclusion" }) } } } catch { Write-Host "Error fetching assignments for policy $($policy.displayName): $($_.Exception.Message)" -ForegroundColor Red } } } # --- App Configuration Policies --- $currentCategory++ Write-Host "[$currentCategory/$totalCategories] Fetching App Configuration Policies..." -ForegroundColor Yellow $simAppConfigPolicies = Get-IntuneEntities -EntityType "deviceAppManagement/mobileAppConfigurations" foreach ($policy in $simAppConfigPolicies) { $assignments = Get-IntuneAssignments -EntityType "mobileAppConfigurations" -EntityId $policy.id $delta = Resolve-SimulatedAssignmentDelta -Assignments $assignments -CurrentGroupIds $simCurrentGroupIds -SimulatedGroupIds $simSimulatedGroupIds -TargetGroupIds $simTargetAllGroupIds -IncludeReasons @("All Users") if ($delta.IsLostPolicy) { $policy | Add-Member -NotePropertyName 'AssignmentReason' -NotePropertyValue $delta.CurrentStatus -Force [void]$deltaPolicies.AppConfigurationPolicies.Add($policy) } elseif ($delta.IsConflict) { [void]$conflictPolicies.Add([PSCustomObject]@{ Category = "App Configuration Policy"; PolicyName = if ($policy.displayName) { $policy.displayName } else { $policy.name }; PolicyId = $policy.id; ConflictType = "Currently included; removal would expose exclusion" }) } } # --- Applications --- $currentCategory++ Write-Host "[$currentCategory/$totalCategories] Fetching Applications..." -ForegroundColor Yellow $simAppUri = "$GraphEndpoint/beta/deviceAppManagement/mobileApps?`$filter=isAssigned eq true" $simAppResponse = Invoke-MgGraphRequest -Uri $simAppUri -Method Get $simAllApps = $simAppResponse.value while ($simAppResponse.'@odata.nextLink') { $simAppResponse = Invoke-MgGraphRequest -Uri $simAppResponse.'@odata.nextLink' -Method Get $simAllApps += $simAppResponse.value } $simTotalApps = $simAllApps.Count $simCurrentApp = 0 foreach ($app in $simAllApps) { if ($app.isFeatured -or $app.isBuiltIn) { continue } $simCurrentApp++ Write-Host "`rFetching Application $simCurrentApp of $simTotalApps" -NoNewline $appId = $app.id try { $assignmentsUri = "$GraphEndpoint/beta/deviceAppManagement/mobileApps('$appId')/assignments" $assignmentResponse = Invoke-MgGraphRequest -Uri $assignmentsUri -Method Get # Check current assignment status $currentExcluded = $false $currentIncluded = $false $simExcluded = $false $simIncluded = $false $currentAppIntent = $null $currentWinningTarget = $null foreach ($assignment in $assignmentResponse.value) { $targetType = $assignment.target.'@odata.type' $targetGroupId = $assignment.target.groupId if ($targetType -eq '#microsoft.graph.exclusionGroupAssignmentTarget') { if ($simCurrentGroupIds -contains $targetGroupId) { $currentExcluded = $true } if ($simSimulatedGroupIds -contains $targetGroupId) { $simExcluded = $true } } elseif ($targetType -eq '#microsoft.graph.allLicensedUsersAssignmentTarget') { $currentIncluded = $true $simIncluded = $true $currentAppIntent = $assignment.intent if (-not $currentWinningTarget) { $currentWinningTarget = $assignment.target } } elseif ($targetType -eq '#microsoft.graph.groupAssignmentTarget') { if ($simCurrentGroupIds -contains $targetGroupId) { $currentIncluded = $true $currentAppIntent = $assignment.intent if (-not $currentWinningTarget) { $currentWinningTarget = $assignment.target } } if ($simSimulatedGroupIds -contains $targetGroupId) { $simIncluded = $true } } } $currentHasApp = $currentIncluded -and -not $currentExcluded $simHasApp = $simIncluded -and -not $simExcluded if ($currentHasApp -and -not $simHasApp) { $filterSuffix = '' if ($currentWinningTarget) { $filterSuffix = Format-AssignmentFilter -FilterId $currentWinningTarget.deviceAndAppManagementAssignmentFilterId -FilterType $currentWinningTarget.deviceAndAppManagementAssignmentFilterType } $appWithReason = $app.PSObject.Copy() $appWithReason | Add-Member -NotePropertyName 'AssignmentReason' -NotePropertyValue "Group Assignment$filterSuffix" -Force $appWithReason | Add-Member -NotePropertyName 'AssignmentIntent' -NotePropertyValue $currentAppIntent -Force switch ($currentAppIntent) { "required" { [void]$deltaPolicies.AppsRequired.Add($appWithReason) } "available" { [void]$deltaPolicies.AppsAvailable.Add($appWithReason) } "uninstall" { [void]$deltaPolicies.AppsUninstall.Add($appWithReason) } } } elseif ($currentExcluded -and $simExcluded) { # Check if target group specifically includes this app while user is excluded foreach ($assignment in $assignmentResponse.value) { if ($assignment.target.'@odata.type' -eq '#microsoft.graph.groupAssignmentTarget' -and $simTargetAllGroupIds -contains $assignment.target.groupId -and $simCurrentGroupIds -notcontains $assignment.target.groupId) { $appName = if ($app.displayName) { $app.displayName } else { $app.name } [void]$conflictPolicies.Add([PSCustomObject]@{ Category = "Application ($($assignment.intent))"; PolicyName = $appName; PolicyId = $app.id; ConflictType = "Currently included; removal would expose exclusion" }) break } } } } catch { Write-Host "`nError fetching assignments for app $($app.displayName): $($_.Exception.Message)" -ForegroundColor Red } } Write-Host "`rFetching Application $simTotalApps of $simTotalApps" -NoNewline Start-Sleep -Milliseconds 100 Write-Host "" # --- Platform Scripts --- $currentCategory++ Write-Host "[$currentCategory/$totalCategories] Fetching Platform Scripts..." -ForegroundColor Yellow $simPlatformScripts = Get-IntuneEntities -EntityType "deviceManagementScripts" foreach ($script in $simPlatformScripts) { $assignments = Get-IntuneAssignments -EntityType "deviceManagementScripts" -EntityId $script.id $delta = Resolve-SimulatedAssignmentDelta -Assignments $assignments -CurrentGroupIds $simCurrentGroupIds -SimulatedGroupIds $simSimulatedGroupIds -TargetGroupIds $simTargetAllGroupIds -IncludeReasons @("All Users") if ($delta.IsLostPolicy) { $script | Add-Member -NotePropertyName 'AssignmentReason' -NotePropertyValue $delta.CurrentStatus -Force [void]$deltaPolicies.PlatformScripts.Add($script) } elseif ($delta.IsConflict) { [void]$conflictPolicies.Add([PSCustomObject]@{ Category = "Platform Script"; PolicyName = if ($script.displayName) { $script.displayName } else { $script.name }; PolicyId = $script.id; ConflictType = "Currently included; removal would expose exclusion" }) } } # --- Proactive Remediation Scripts --- $currentCategory++ Write-Host "[$currentCategory/$totalCategories] Fetching Proactive Remediation Scripts..." -ForegroundColor Yellow $simHealthScripts = Get-IntuneEntities -EntityType "deviceHealthScripts" foreach ($script in $simHealthScripts) { $assignments = Get-IntuneAssignments -EntityType "deviceHealthScripts" -EntityId $script.id $delta = Resolve-SimulatedAssignmentDelta -Assignments $assignments -CurrentGroupIds $simCurrentGroupIds -SimulatedGroupIds $simSimulatedGroupIds -TargetGroupIds $simTargetAllGroupIds -IncludeReasons @("All Users") if ($delta.IsLostPolicy) { $script | Add-Member -NotePropertyName 'AssignmentReason' -NotePropertyValue $delta.CurrentStatus -Force [void]$deltaPolicies.HealthScripts.Add($script) } elseif ($delta.IsConflict) { [void]$conflictPolicies.Add([PSCustomObject]@{ Category = "Proactive Remediation Script"; PolicyName = if ($script.displayName) { $script.displayName } else { $script.name }; PolicyId = $script.id; ConflictType = "Currently included; removal would expose exclusion" }) } } # --- Endpoint Security: Antivirus --- $currentCategory++ Write-Host "[$currentCategory/$totalCategories] Fetching Antivirus Policies..." -ForegroundColor Yellow $simProcessedAntivirusIds = [System.Collections.Generic.HashSet[string]]::new() $simConfigPoliciesForAntivirus = Get-IntuneEntities -EntityType "configurationPolicies" $simMatchingAntivirus = $simConfigPoliciesForAntivirus | Where-Object { $_.templateReference -and $_.templateReference.templateFamily -eq 'endpointSecurityAntivirus' } if ($simMatchingAntivirus) { foreach ($policy in $simMatchingAntivirus) { if ($simProcessedAntivirusIds.Add($policy.id)) { $assignments = Get-IntuneAssignments -EntityType "configurationPolicies" -EntityId $policy.id $delta = Resolve-SimulatedAssignmentDelta -Assignments $assignments -CurrentGroupIds $simCurrentGroupIds -SimulatedGroupIds $simSimulatedGroupIds -TargetGroupIds $simTargetAllGroupIds -IncludeReasons @("All Users") if ($delta.IsLostPolicy) { $policy | Add-Member -NotePropertyName 'AssignmentReason' -NotePropertyValue $delta.CurrentStatus -Force [void]$deltaPolicies.AntivirusProfiles.Add($policy) } elseif ($delta.IsConflict) { [void]$conflictPolicies.Add([PSCustomObject]@{ Category = "Endpoint Security - Antivirus"; PolicyName = if ($policy.displayName) { $policy.displayName } else { $policy.name }; PolicyId = $policy.id; ConflictType = "Currently included; removal would expose exclusion" }) } } } } $simAllIntentsForAntivirus = Get-IntuneEntities -EntityType "deviceManagement/intents" Add-IntentTemplateFamilyInfo -IntentPolicies $simAllIntentsForAntivirus $simMatchingIntentsAntivirus = $simAllIntentsForAntivirus | Where-Object { $_.templateReference -and $_.templateReference.templateFamily -eq 'endpointSecurityAntivirus' } if ($simMatchingIntentsAntivirus) { foreach ($policy in $simMatchingIntentsAntivirus) { if ($simProcessedAntivirusIds.Add($policy.id)) { $assignmentsResponse = Invoke-MgGraphRequest -Uri "$GraphEndpoint/beta/deviceManagement/intents/$($policy.id)/assignments" -Method Get $assignmentDetailsList = foreach ($assignment in $assignmentsResponse.value) { [PSCustomObject]@{ Reason = switch ($assignment.target.'@odata.type') { '#microsoft.graph.allLicensedUsersAssignmentTarget' { "All Users" } '#microsoft.graph.allDevicesAssignmentTarget' { "All Devices" } '#microsoft.graph.groupAssignmentTarget' { "Group Assignment" } '#microsoft.graph.exclusionGroupAssignmentTarget' { "Group Exclusion" } default { "Unknown" } } GroupId = if ($assignment.target.'@odata.type' -match "groupAssignmentTarget") { $assignment.target.groupId } else { $null } } } $delta = Resolve-SimulatedAssignmentDelta -Assignments $assignmentDetailsList -CurrentGroupIds $simCurrentGroupIds -SimulatedGroupIds $simSimulatedGroupIds -TargetGroupIds $simTargetAllGroupIds -IncludeReasons @("All Users") if ($delta.IsLostPolicy) { $policy | Add-Member -NotePropertyName 'AssignmentReason' -NotePropertyValue $delta.CurrentStatus -Force [void]$deltaPolicies.AntivirusProfiles.Add($policy) } elseif ($delta.IsConflict) { [void]$conflictPolicies.Add([PSCustomObject]@{ Category = "Endpoint Security - Antivirus"; PolicyName = if ($policy.displayName) { $policy.displayName } else { $policy.name }; PolicyId = $policy.id; ConflictType = "Currently included; removal would expose exclusion" }) } } } } # --- Endpoint Security: Disk Encryption --- $currentCategory++ Write-Host "[$currentCategory/$totalCategories] Fetching Disk Encryption Policies..." -ForegroundColor Yellow $simProcessedDiskEncIds = [System.Collections.Generic.HashSet[string]]::new() $simConfigPoliciesForDiskEnc = Get-IntuneEntities -EntityType "configurationPolicies" $simMatchingDiskEnc = $simConfigPoliciesForDiskEnc | Where-Object { $_.templateReference -and $_.templateReference.templateFamily -eq 'endpointSecurityDiskEncryption' } if ($simMatchingDiskEnc) { foreach ($policy in $simMatchingDiskEnc) { if ($simProcessedDiskEncIds.Add($policy.id)) { $assignments = Get-IntuneAssignments -EntityType "configurationPolicies" -EntityId $policy.id $delta = Resolve-SimulatedAssignmentDelta -Assignments $assignments -CurrentGroupIds $simCurrentGroupIds -SimulatedGroupIds $simSimulatedGroupIds -TargetGroupIds $simTargetAllGroupIds -IncludeReasons @("All Users") if ($delta.IsLostPolicy) { $policy | Add-Member -NotePropertyName 'AssignmentReason' -NotePropertyValue $delta.CurrentStatus -Force [void]$deltaPolicies.DiskEncryptionProfiles.Add($policy) } elseif ($delta.IsConflict) { [void]$conflictPolicies.Add([PSCustomObject]@{ Category = "Endpoint Security - Disk Encryption"; PolicyName = if ($policy.displayName) { $policy.displayName } else { $policy.name }; PolicyId = $policy.id; ConflictType = "Currently included; removal would expose exclusion" }) } } } } $simAllIntentsForDiskEnc = Get-IntuneEntities -EntityType "deviceManagement/intents" Add-IntentTemplateFamilyInfo -IntentPolicies $simAllIntentsForDiskEnc $simMatchingIntentsDiskEnc = $simAllIntentsForDiskEnc | Where-Object { $_.templateReference -and $_.templateReference.templateFamily -eq 'endpointSecurityDiskEncryption' } if ($simMatchingIntentsDiskEnc) { foreach ($policy in $simMatchingIntentsDiskEnc) { if ($simProcessedDiskEncIds.Add($policy.id)) { $assignmentsResponse = Invoke-MgGraphRequest -Uri "$GraphEndpoint/beta/deviceManagement/intents/$($policy.id)/assignments" -Method Get $assignmentDetailsList = foreach ($assignment in $assignmentsResponse.value) { [PSCustomObject]@{ Reason = switch ($assignment.target.'@odata.type') { '#microsoft.graph.allLicensedUsersAssignmentTarget' { "All Users" } '#microsoft.graph.allDevicesAssignmentTarget' { "All Devices" } '#microsoft.graph.groupAssignmentTarget' { "Group Assignment" } '#microsoft.graph.exclusionGroupAssignmentTarget' { "Group Exclusion" } default { "Unknown" } } GroupId = if ($assignment.target.'@odata.type' -match "groupAssignmentTarget") { $assignment.target.groupId } else { $null } } } $delta = Resolve-SimulatedAssignmentDelta -Assignments $assignmentDetailsList -CurrentGroupIds $simCurrentGroupIds -SimulatedGroupIds $simSimulatedGroupIds -TargetGroupIds $simTargetAllGroupIds -IncludeReasons @("All Users") if ($delta.IsLostPolicy) { $policy | Add-Member -NotePropertyName 'AssignmentReason' -NotePropertyValue $delta.CurrentStatus -Force [void]$deltaPolicies.DiskEncryptionProfiles.Add($policy) } elseif ($delta.IsConflict) { [void]$conflictPolicies.Add([PSCustomObject]@{ Category = "Endpoint Security - Disk Encryption"; PolicyName = if ($policy.displayName) { $policy.displayName } else { $policy.name }; PolicyId = $policy.id; ConflictType = "Currently included; removal would expose exclusion" }) } } } } # --- Endpoint Security: Firewall --- $currentCategory++ Write-Host "[$currentCategory/$totalCategories] Fetching Firewall Policies..." -ForegroundColor Yellow $simProcessedFirewallIds = [System.Collections.Generic.HashSet[string]]::new() $simConfigPoliciesForFirewall = Get-IntuneEntities -EntityType "configurationPolicies" $simMatchingFirewall = $simConfigPoliciesForFirewall | Where-Object { $_.templateReference -and $_.templateReference.templateFamily -eq 'endpointSecurityFirewall' } if ($simMatchingFirewall) { foreach ($policy in $simMatchingFirewall) { if ($simProcessedFirewallIds.Add($policy.id)) { $assignments = Get-IntuneAssignments -EntityType "configurationPolicies" -EntityId $policy.id $delta = Resolve-SimulatedAssignmentDelta -Assignments $assignments -CurrentGroupIds $simCurrentGroupIds -SimulatedGroupIds $simSimulatedGroupIds -TargetGroupIds $simTargetAllGroupIds -IncludeReasons @("All Users") if ($delta.IsLostPolicy) { $policy | Add-Member -NotePropertyName 'AssignmentReason' -NotePropertyValue $delta.CurrentStatus -Force [void]$deltaPolicies.FirewallProfiles.Add($policy) } elseif ($delta.IsConflict) { [void]$conflictPolicies.Add([PSCustomObject]@{ Category = "Endpoint Security - Firewall"; PolicyName = if ($policy.displayName) { $policy.displayName } else { $policy.name }; PolicyId = $policy.id; ConflictType = "Currently included; removal would expose exclusion" }) } } } } $simAllIntentsForFirewall = Get-IntuneEntities -EntityType "deviceManagement/intents" Add-IntentTemplateFamilyInfo -IntentPolicies $simAllIntentsForFirewall $simMatchingIntentsFirewall = $simAllIntentsForFirewall | Where-Object { $_.templateReference -and $_.templateReference.templateFamily -eq 'endpointSecurityFirewall' } if ($simMatchingIntentsFirewall) { foreach ($policy in $simMatchingIntentsFirewall) { if ($simProcessedFirewallIds.Add($policy.id)) { $assignmentsResponse = Invoke-MgGraphRequest -Uri "$GraphEndpoint/beta/deviceManagement/intents/$($policy.id)/assignments" -Method Get $assignmentDetailsList = foreach ($assignment in $assignmentsResponse.value) { [PSCustomObject]@{ Reason = switch ($assignment.target.'@odata.type') { '#microsoft.graph.allLicensedUsersAssignmentTarget' { "All Users" } '#microsoft.graph.allDevicesAssignmentTarget' { "All Devices" } '#microsoft.graph.groupAssignmentTarget' { "Group Assignment" } '#microsoft.graph.exclusionGroupAssignmentTarget' { "Group Exclusion" } default { "Unknown" } } GroupId = if ($assignment.target.'@odata.type' -match "groupAssignmentTarget") { $assignment.target.groupId } else { $null } } } $delta = Resolve-SimulatedAssignmentDelta -Assignments $assignmentDetailsList -CurrentGroupIds $simCurrentGroupIds -SimulatedGroupIds $simSimulatedGroupIds -TargetGroupIds $simTargetAllGroupIds -IncludeReasons @("All Users") if ($delta.IsLostPolicy) { $policy | Add-Member -NotePropertyName 'AssignmentReason' -NotePropertyValue $delta.CurrentStatus -Force [void]$deltaPolicies.FirewallProfiles.Add($policy) } elseif ($delta.IsConflict) { [void]$conflictPolicies.Add([PSCustomObject]@{ Category = "Endpoint Security - Firewall"; PolicyName = if ($policy.displayName) { $policy.displayName } else { $policy.name }; PolicyId = $policy.id; ConflictType = "Currently included; removal would expose exclusion" }) } } } } # --- Endpoint Security: EDR --- $currentCategory++ Write-Host "[$currentCategory/$totalCategories] Fetching Endpoint Detection and Response Policies..." -ForegroundColor Yellow $simProcessedEDRIds = [System.Collections.Generic.HashSet[string]]::new() $simConfigPoliciesForEDR = Get-IntuneEntities -EntityType "configurationPolicies" $simMatchingEDR = $simConfigPoliciesForEDR | Where-Object { $_.templateReference -and $_.templateReference.templateFamily -eq 'endpointSecurityEndpointDetectionAndResponse' } if ($simMatchingEDR) { foreach ($policy in $simMatchingEDR) { if ($simProcessedEDRIds.Add($policy.id)) { $assignments = Get-IntuneAssignments -EntityType "configurationPolicies" -EntityId $policy.id $delta = Resolve-SimulatedAssignmentDelta -Assignments $assignments -CurrentGroupIds $simCurrentGroupIds -SimulatedGroupIds $simSimulatedGroupIds -TargetGroupIds $simTargetAllGroupIds -IncludeReasons @("All Users") if ($delta.IsLostPolicy) { $policy | Add-Member -NotePropertyName 'AssignmentReason' -NotePropertyValue $delta.CurrentStatus -Force [void]$deltaPolicies.EndpointDetectionProfiles.Add($policy) } elseif ($delta.IsConflict) { [void]$conflictPolicies.Add([PSCustomObject]@{ Category = "Endpoint Security - EDR"; PolicyName = if ($policy.displayName) { $policy.displayName } else { $policy.name }; PolicyId = $policy.id; ConflictType = "Currently included; removal would expose exclusion" }) } } } } $simAllIntentsForEDR = Get-IntuneEntities -EntityType "deviceManagement/intents" Add-IntentTemplateFamilyInfo -IntentPolicies $simAllIntentsForEDR $simMatchingIntentsEDR = $simAllIntentsForEDR | Where-Object { $_.templateReference -and $_.templateReference.templateFamily -eq 'endpointSecurityEndpointDetectionAndResponse' } if ($simMatchingIntentsEDR) { foreach ($policy in $simMatchingIntentsEDR) { if ($simProcessedEDRIds.Add($policy.id)) { $assignmentsResponse = Invoke-MgGraphRequest -Uri "$GraphEndpoint/beta/deviceManagement/intents/$($policy.id)/assignments" -Method Get $assignmentDetailsList = foreach ($assignment in $assignmentsResponse.value) { [PSCustomObject]@{ Reason = switch ($assignment.target.'@odata.type') { '#microsoft.graph.allLicensedUsersAssignmentTarget' { "All Users" } '#microsoft.graph.allDevicesAssignmentTarget' { "All Devices" } '#microsoft.graph.groupAssignmentTarget' { "Group Assignment" } '#microsoft.graph.exclusionGroupAssignmentTarget' { "Group Exclusion" } default { "Unknown" } } GroupId = if ($assignment.target.'@odata.type' -match "groupAssignmentTarget") { $assignment.target.groupId } else { $null } } } $delta = Resolve-SimulatedAssignmentDelta -Assignments $assignmentDetailsList -CurrentGroupIds $simCurrentGroupIds -SimulatedGroupIds $simSimulatedGroupIds -TargetGroupIds $simTargetAllGroupIds -IncludeReasons @("All Users") if ($delta.IsLostPolicy) { $policy | Add-Member -NotePropertyName 'AssignmentReason' -NotePropertyValue $delta.CurrentStatus -Force [void]$deltaPolicies.EndpointDetectionProfiles.Add($policy) } elseif ($delta.IsConflict) { [void]$conflictPolicies.Add([PSCustomObject]@{ Category = "Endpoint Security - EDR"; PolicyName = if ($policy.displayName) { $policy.displayName } else { $policy.name }; PolicyId = $policy.id; ConflictType = "Currently included; removal would expose exclusion" }) } } } } # --- Endpoint Security: Attack Surface Reduction --- $currentCategory++ Write-Host "[$currentCategory/$totalCategories] Fetching Attack Surface Reduction Policies..." -ForegroundColor Yellow $simProcessedASRIds = [System.Collections.Generic.HashSet[string]]::new() $simConfigPoliciesForASR = Get-IntuneEntities -EntityType "configurationPolicies" $simMatchingASR = $simConfigPoliciesForASR | Where-Object { $_.templateReference -and $_.templateReference.templateFamily -eq 'endpointSecurityAttackSurfaceReduction' } if ($simMatchingASR) { foreach ($policy in $simMatchingASR) { if ($simProcessedASRIds.Add($policy.id)) { $assignments = Get-IntuneAssignments -EntityType "configurationPolicies" -EntityId $policy.id $delta = Resolve-SimulatedAssignmentDelta -Assignments $assignments -CurrentGroupIds $simCurrentGroupIds -SimulatedGroupIds $simSimulatedGroupIds -TargetGroupIds $simTargetAllGroupIds -IncludeReasons @("All Users") if ($delta.IsLostPolicy) { $policy | Add-Member -NotePropertyName 'AssignmentReason' -NotePropertyValue $delta.CurrentStatus -Force [void]$deltaPolicies.AttackSurfaceProfiles.Add($policy) } elseif ($delta.IsConflict) { [void]$conflictPolicies.Add([PSCustomObject]@{ Category = "Endpoint Security - ASR"; PolicyName = if ($policy.displayName) { $policy.displayName } else { $policy.name }; PolicyId = $policy.id; ConflictType = "Currently included; removal would expose exclusion" }) } } } } $simAllIntentsForASR = Get-IntuneEntities -EntityType "deviceManagement/intents" Add-IntentTemplateFamilyInfo -IntentPolicies $simAllIntentsForASR $simMatchingIntentsASR = $simAllIntentsForASR | Where-Object { $_.templateReference -and $_.templateReference.templateFamily -eq 'endpointSecurityAttackSurfaceReduction' } if ($simMatchingIntentsASR) { foreach ($policy in $simMatchingIntentsASR) { if ($simProcessedASRIds.Add($policy.id)) { $assignmentsResponse = Invoke-MgGraphRequest -Uri "$GraphEndpoint/beta/deviceManagement/intents/$($policy.id)/assignments" -Method Get $assignmentDetailsList = foreach ($assignment in $assignmentsResponse.value) { [PSCustomObject]@{ Reason = switch ($assignment.target.'@odata.type') { '#microsoft.graph.allLicensedUsersAssignmentTarget' { "All Users" } '#microsoft.graph.allDevicesAssignmentTarget' { "All Devices" } '#microsoft.graph.groupAssignmentTarget' { "Group Assignment" } '#microsoft.graph.exclusionGroupAssignmentTarget' { "Group Exclusion" } default { "Unknown" } } GroupId = if ($assignment.target.'@odata.type' -match "groupAssignmentTarget") { $assignment.target.groupId } else { $null } } } $delta = Resolve-SimulatedAssignmentDelta -Assignments $assignmentDetailsList -CurrentGroupIds $simCurrentGroupIds -SimulatedGroupIds $simSimulatedGroupIds -TargetGroupIds $simTargetAllGroupIds -IncludeReasons @("All Users") if ($delta.IsLostPolicy) { $policy | Add-Member -NotePropertyName 'AssignmentReason' -NotePropertyValue $delta.CurrentStatus -Force [void]$deltaPolicies.AttackSurfaceProfiles.Add($policy) } elseif ($delta.IsConflict) { [void]$conflictPolicies.Add([PSCustomObject]@{ Category = "Endpoint Security - ASR"; PolicyName = if ($policy.displayName) { $policy.displayName } else { $policy.name }; PolicyId = $policy.id; ConflictType = "Currently included; removal would expose exclusion" }) } } } } # --- Endpoint Security: Account Protection --- $currentCategory++ Write-Host "[$currentCategory/$totalCategories] Fetching Account Protection Policies..." -ForegroundColor Yellow $simProcessedAcctProtIds = [System.Collections.Generic.HashSet[string]]::new() $simConfigPoliciesForAcctProt = Get-IntuneEntities -EntityType "configurationPolicies" $simMatchingAcctProt = $simConfigPoliciesForAcctProt | Where-Object { $_.templateReference -and $_.templateReference.templateFamily -eq 'endpointSecurityAccountProtection' } if ($simMatchingAcctProt) { foreach ($policy in $simMatchingAcctProt) { if ($simProcessedAcctProtIds.Add($policy.id)) { $assignments = Get-IntuneAssignments -EntityType "configurationPolicies" -EntityId $policy.id $delta = Resolve-SimulatedAssignmentDelta -Assignments $assignments -CurrentGroupIds $simCurrentGroupIds -SimulatedGroupIds $simSimulatedGroupIds -TargetGroupIds $simTargetAllGroupIds -IncludeReasons @("All Users") if ($delta.IsLostPolicy) { $policy | Add-Member -NotePropertyName 'AssignmentReason' -NotePropertyValue $delta.CurrentStatus -Force [void]$deltaPolicies.AccountProtectionProfiles.Add($policy) } elseif ($delta.IsConflict) { [void]$conflictPolicies.Add([PSCustomObject]@{ Category = "Endpoint Security - Account Protection"; PolicyName = if ($policy.displayName) { $policy.displayName } else { $policy.name }; PolicyId = $policy.id; ConflictType = "Currently included; removal would expose exclusion" }) } } } } $simAllIntentsForAcctProt = Get-IntuneEntities -EntityType "deviceManagement/intents" Add-IntentTemplateFamilyInfo -IntentPolicies $simAllIntentsForAcctProt $simMatchingIntentsAcctProt = $simAllIntentsForAcctProt | Where-Object { $_.templateReference -and $_.templateReference.templateFamily -eq 'endpointSecurityAccountProtection' } if ($simMatchingIntentsAcctProt) { foreach ($policy in $simMatchingIntentsAcctProt) { if ($simProcessedAcctProtIds.Add($policy.id)) { $assignmentsResponse = Invoke-MgGraphRequest -Uri "$GraphEndpoint/beta/deviceManagement/intents/$($policy.id)/assignments" -Method Get $assignmentDetailsList = foreach ($assignment in $assignmentsResponse.value) { [PSCustomObject]@{ Reason = switch ($assignment.target.'@odata.type') { '#microsoft.graph.allLicensedUsersAssignmentTarget' { "All Users" } '#microsoft.graph.allDevicesAssignmentTarget' { "All Devices" } '#microsoft.graph.groupAssignmentTarget' { "Group Assignment" } '#microsoft.graph.exclusionGroupAssignmentTarget' { "Group Exclusion" } default { "Unknown" } } GroupId = if ($assignment.target.'@odata.type' -match "groupAssignmentTarget") { $assignment.target.groupId } else { $null } } } $delta = Resolve-SimulatedAssignmentDelta -Assignments $assignmentDetailsList -CurrentGroupIds $simCurrentGroupIds -SimulatedGroupIds $simSimulatedGroupIds -TargetGroupIds $simTargetAllGroupIds -IncludeReasons @("All Users") if ($delta.IsLostPolicy) { $policy | Add-Member -NotePropertyName 'AssignmentReason' -NotePropertyValue $delta.CurrentStatus -Force [void]$deltaPolicies.AccountProtectionProfiles.Add($policy) } elseif ($delta.IsConflict) { [void]$conflictPolicies.Add([PSCustomObject]@{ Category = "Endpoint Security - Account Protection"; PolicyName = if ($policy.displayName) { $policy.displayName } else { $policy.name }; PolicyId = $policy.id; ConflictType = "Currently included; removal would expose exclusion" }) } } } } # --- Autopilot Deployment Profiles --- $currentCategory++ Write-Host "[$currentCategory/$totalCategories] Fetching Autopilot Deployment Profiles..." -ForegroundColor Yellow $simAutoProfiles = Get-IntuneEntities -EntityType "windowsAutopilotDeploymentProfiles" foreach ($profile in $simAutoProfiles) { $assignments = Get-IntuneAssignments -EntityType "windowsAutopilotDeploymentProfiles" -EntityId $profile.id $delta = Resolve-SimulatedAssignmentDelta -Assignments $assignments -CurrentGroupIds $simCurrentGroupIds -SimulatedGroupIds $simSimulatedGroupIds -TargetGroupIds $simTargetAllGroupIds -IncludeReasons @("All Users") if ($delta.IsLostPolicy) { $profile | Add-Member -NotePropertyName 'AssignmentReason' -NotePropertyValue $delta.CurrentStatus -Force [void]$deltaPolicies.DeploymentProfiles.Add($profile) } elseif ($delta.IsConflict) { [void]$conflictPolicies.Add([PSCustomObject]@{ Category = "Autopilot Deployment Profile"; PolicyName = if ($profile.displayName) { $profile.displayName } else { $profile.name }; PolicyId = $profile.id; ConflictType = "Currently included; removal would expose exclusion" }) } } # --- Enrollment Status Page Profiles --- $currentCategory++ Write-Host "[$currentCategory/$totalCategories] Fetching Enrollment Status Page Profiles..." -ForegroundColor Yellow $simEnrollmentConfigs = Get-IntuneEntities -EntityType "deviceEnrollmentConfigurations" $simEspProfiles = $simEnrollmentConfigs | Where-Object { $_.'@odata.type' -match 'EnrollmentCompletionPageConfiguration' } foreach ($esp in $simEspProfiles) { $assignments = Get-IntuneAssignments -EntityType "deviceEnrollmentConfigurations" -EntityId $esp.id $delta = Resolve-SimulatedAssignmentDelta -Assignments $assignments -CurrentGroupIds $simCurrentGroupIds -SimulatedGroupIds $simSimulatedGroupIds -TargetGroupIds $simTargetAllGroupIds -IncludeReasons @("All Users") if ($delta.IsLostPolicy) { $esp | Add-Member -NotePropertyName 'AssignmentReason' -NotePropertyValue $delta.CurrentStatus -Force [void]$deltaPolicies.ESPProfiles.Add($esp) } elseif ($delta.IsConflict) { [void]$conflictPolicies.Add([PSCustomObject]@{ Category = "Enrollment Status Page"; PolicyName = if ($esp.displayName) { $esp.displayName } else { $esp.name }; PolicyId = $esp.id; ConflictType = "Currently included; removal would expose exclusion" }) } } # --- Windows 365 Cloud PC Provisioning Policies --- $currentCategory++ Write-Host "[$currentCategory/$totalCategories] Fetching Windows 365 Cloud PC Provisioning Policies..." -ForegroundColor Yellow try { $simCloudPCProvisioning = Get-IntuneEntities -EntityType "virtualEndpoint/provisioningPolicies" foreach ($policy in $simCloudPCProvisioning) { $assignments = Get-IntuneAssignments -EntityType "virtualEndpoint/provisioningPolicies" -EntityId $policy.id $delta = Resolve-SimulatedAssignmentDelta -Assignments $assignments -CurrentGroupIds $simCurrentGroupIds -SimulatedGroupIds $simSimulatedGroupIds -TargetGroupIds $simTargetAllGroupIds -IncludeReasons @("All Users") if ($delta.IsLostPolicy) { $policy | Add-Member -NotePropertyName 'AssignmentReason' -NotePropertyValue $delta.CurrentStatus -Force [void]$deltaPolicies.CloudPCProvisioningPolicies.Add($policy) } elseif ($delta.IsConflict) { [void]$conflictPolicies.Add([PSCustomObject]@{ Category = "Cloud PC Provisioning"; PolicyName = if ($policy.displayName) { $policy.displayName } else { $policy.name }; PolicyId = $policy.id; ConflictType = "Currently included; removal would expose exclusion" }) } } } catch { Write-Verbose "Skipping - Windows 365 may not be licensed for this tenant" } # --- Windows 365 Cloud PC User Settings --- $currentCategory++ Write-Host "[$currentCategory/$totalCategories] Fetching Windows 365 Cloud PC User Settings..." -ForegroundColor Yellow try { $simCloudPCUserSettings = Get-IntuneEntities -EntityType "virtualEndpoint/userSettings" foreach ($setting in $simCloudPCUserSettings) { $assignments = Get-IntuneAssignments -EntityType "virtualEndpoint/userSettings" -EntityId $setting.id $delta = Resolve-SimulatedAssignmentDelta -Assignments $assignments -CurrentGroupIds $simCurrentGroupIds -SimulatedGroupIds $simSimulatedGroupIds -TargetGroupIds $simTargetAllGroupIds -IncludeReasons @("All Users") if ($delta.IsLostPolicy) { $setting | Add-Member -NotePropertyName 'AssignmentReason' -NotePropertyValue $delta.CurrentStatus -Force [void]$deltaPolicies.CloudPCUserSettings.Add($setting) } elseif ($delta.IsConflict) { [void]$conflictPolicies.Add([PSCustomObject]@{ Category = "Cloud PC User Setting"; PolicyName = if ($setting.displayName) { $setting.displayName } else { $setting.name }; PolicyId = $setting.id; ConflictType = "Currently included; removal would expose exclusion" }) } } } catch { Write-Verbose "Skipping - Windows 365 may not be licensed for this tenant" } # Apply scope tag filter if specified if ($ScopeTagFilter) { foreach ($key in @($deltaPolicies.Keys)) { $deltaPolicies[$key] = @(Filter-ByScopeTag -Items $deltaPolicies[$key] -FilterTag $ScopeTagFilter -ScopeTagLookup $script:ScopeTagLookup) } } # ===== DISPLAY RESULTS ===== Write-Host "" Write-Host (Get-Separator -Character "=") -ForegroundColor Yellow Write-Host " SIMULATION RESULTS - GROUP MEMBERSHIP REMOVAL IMPACT" -ForegroundColor Yellow Write-Host " (no changes were made)" -ForegroundColor DarkGray Write-Host (Get-Separator -Character "=") -ForegroundColor Yellow Write-Host " User: $simUpn" -ForegroundColor White Write-Host " Target Group: $simTargetGroupName (ID: $simTargetGroupId)" -ForegroundColor White Write-Host (Get-Separator -Character "=") -ForegroundColor Yellow # Category display mapping $categoryDisplay = [ordered]@{ DeviceConfigs = "Device Configurations" SettingsCatalog = "Settings Catalog Policies" CompliancePolicies = "Compliance Policies" AppProtectionPolicies = "App Protection Policies" AppConfigurationPolicies = "App Configuration Policies" AppsRequired = "Required Apps" AppsAvailable = "Available Apps" AppsUninstall = "Uninstall Apps" PlatformScripts = "Platform Scripts" HealthScripts = "Proactive Remediation Scripts" AntivirusProfiles = "Endpoint Security - Antivirus" DiskEncryptionProfiles = "Endpoint Security - Disk Encryption" FirewallProfiles = "Endpoint Security - Firewall" EndpointDetectionProfiles = "Endpoint Security - EDR" AttackSurfaceProfiles = "Endpoint Security - ASR" AccountProtectionProfiles = "Endpoint Security - Account Protection" DeploymentProfiles = "Autopilot Deployment Profiles" ESPProfiles = "Enrollment Status Page Profiles" CloudPCProvisioningPolicies = "Windows 365 Cloud PC Provisioning" CloudPCUserSettings = "Windows 365 Cloud PC User Settings" } $totalLostPolicies = 0 foreach ($catKey in $categoryDisplay.Keys) { $items = $deltaPolicies[$catKey] if ($items.Count -gt 0) { $catLabel = $categoryDisplay[$catKey] $totalLostPolicies += $items.Count Write-Host "`n------- LOST: $catLabel ($($items.Count)) -------" -ForegroundColor Red $headerFormat = "{0,-50} {1,-40} {2,-30}" -f "Policy Name", "Policy ID", "Assignment Reason" $separator = Get-Separator Write-Host $separator Write-Host $headerFormat -ForegroundColor Yellow Write-Host $separator foreach ($item in $items) { $itemName = if (-not [string]::IsNullOrWhiteSpace($item.displayName)) { $item.displayName } else { $item.name } if (-not $itemName) { $itemName = "Unnamed" } if ($itemName.Length -gt 47) { $itemName = $itemName.Substring(0, 44) + "..." } $itemId = if ($item.id) { $item.id } else { "Unknown" } if ($itemId.Length -gt 37) { $itemId = $itemId.Substring(0, 34) + "..." } $reason = if ($item.AssignmentReason) { $item.AssignmentReason } else { "Unknown" } if ($reason.Length -gt 27) { $reason = $reason.Substring(0, 24) + "..." } Write-Host ("{0,-50} {1,-40} {2,-30}" -f $itemName, $itemId, $reason) -ForegroundColor White } Write-Host $separator } } # Display conflicts if ($conflictPolicies.Count -gt 0) { Write-Host "`n------- CONFLICTS (Exclusion Overrides) -------" -ForegroundColor Red Write-Host "Note: In Intune, exclusions take priority over inclusions." -ForegroundColor Yellow $headerFormat = "{0,-50} {1,-35} {2,-35}" -f "Policy Name", "Category", "Conflict" $separator = Get-Separator Write-Host $separator Write-Host $headerFormat -ForegroundColor Yellow Write-Host $separator foreach ($conflict in $conflictPolicies) { $cName = $conflict.PolicyName if ($cName.Length -gt 47) { $cName = $cName.Substring(0, 44) + "..." } $cCat = $conflict.Category if ($cCat.Length -gt 32) { $cCat = $cCat.Substring(0, 29) + "..." } $cType = $conflict.ConflictType if ($cType.Length -gt 32) { $cType = $cType.Substring(0, 29) + "..." } Write-Host ("{0,-50} {1,-35} {2,-35}" -f $cName, $cCat, $cType) -ForegroundColor Red } Write-Host $separator } # Summary Write-Host "`n=== Impact Summary ===" -ForegroundColor Cyan Write-Host "Removing '$simUpn' from '$simTargetGroupName' would result in:" -ForegroundColor White $categoryCount = ($categoryDisplay.Keys | Where-Object { $deltaPolicies[$_].Count -gt 0 }).Count $conflictCount = $conflictPolicies.Count if ($totalLostPolicies -eq 0 -and $conflictCount -eq 0) { Write-Host " No lost policy assignments and no conflicts." -ForegroundColor Yellow } else { $parts = @() if ($totalLostPolicies -gt 0) { $parts += "$totalLostPolicies lost $(if ($totalLostPolicies -eq 1) { 'policy' } else { 'policies' }) across $categoryCount $(if ($categoryCount -eq 1) { 'category' } else { 'categories' })" } if ($conflictCount -gt 0) { $parts += "$conflictCount $(if ($conflictCount -eq 1) { 'conflict' } else { 'conflicts' })" } Write-Host " Impact: $($parts -join ', ')" -ForegroundColor $(if ($conflictCount -gt 0) { "Yellow" } else { "Red" }) } # Export $exportData = [System.Collections.ArrayList]::new() $null = $exportData.Add([PSCustomObject]@{ Category = "Simulation Info" Item = "User: $simUpn -> Remove from Group: $simTargetGroupName (ID: $simTargetGroupId)" ScopeTags = "" AssignmentReason = "Removal Impact Analysis" }) Add-ExportData -ExportData $exportData -Category "LOST: Device Configuration" -Items $deltaPolicies.DeviceConfigs -AssignmentReason { param($item) $item.AssignmentReason } Add-ExportData -ExportData $exportData -Category "LOST: Settings Catalog Policy" -Items $deltaPolicies.SettingsCatalog -AssignmentReason { param($item) $item.AssignmentReason } Add-ExportData -ExportData $exportData -Category "LOST: Compliance Policy" -Items $deltaPolicies.CompliancePolicies -AssignmentReason { param($item) $item.AssignmentReason } Add-ExportData -ExportData $exportData -Category "LOST: App Protection Policy" -Items $deltaPolicies.AppProtectionPolicies -AssignmentReason { param($item) $item.AssignmentReason } Add-ExportData -ExportData $exportData -Category "LOST: App Configuration Policy" -Items $deltaPolicies.AppConfigurationPolicies -AssignmentReason { param($item) $item.AssignmentReason } Add-ExportData -ExportData $exportData -Category "LOST: Required App" -Items $deltaPolicies.AppsRequired -AssignmentReason { param($item) $item.AssignmentReason } Add-ExportData -ExportData $exportData -Category "LOST: Available App" -Items $deltaPolicies.AppsAvailable -AssignmentReason { param($item) $item.AssignmentReason } Add-ExportData -ExportData $exportData -Category "LOST: Uninstall App" -Items $deltaPolicies.AppsUninstall -AssignmentReason { param($item) $item.AssignmentReason } Add-ExportData -ExportData $exportData -Category "LOST: Platform Script" -Items $deltaPolicies.PlatformScripts -AssignmentReason { param($item) $item.AssignmentReason } Add-ExportData -ExportData $exportData -Category "LOST: Proactive Remediation Script" -Items $deltaPolicies.HealthScripts -AssignmentReason { param($item) $item.AssignmentReason } Add-ExportData -ExportData $exportData -Category "LOST: Endpoint Security - Antivirus" -Items $deltaPolicies.AntivirusProfiles -AssignmentReason { param($item) $item.AssignmentReason } Add-ExportData -ExportData $exportData -Category "LOST: Endpoint Security - Disk Encryption" -Items $deltaPolicies.DiskEncryptionProfiles -AssignmentReason { param($item) $item.AssignmentReason } Add-ExportData -ExportData $exportData -Category "LOST: Endpoint Security - Firewall" -Items $deltaPolicies.FirewallProfiles -AssignmentReason { param($item) $item.AssignmentReason } Add-ExportData -ExportData $exportData -Category "LOST: Endpoint Security - EDR" -Items $deltaPolicies.EndpointDetectionProfiles -AssignmentReason { param($item) $item.AssignmentReason } Add-ExportData -ExportData $exportData -Category "LOST: Endpoint Security - ASR" -Items $deltaPolicies.AttackSurfaceProfiles -AssignmentReason { param($item) $item.AssignmentReason } Add-ExportData -ExportData $exportData -Category "LOST: Endpoint Security - Account Protection" -Items $deltaPolicies.AccountProtectionProfiles -AssignmentReason { param($item) $item.AssignmentReason } Add-ExportData -ExportData $exportData -Category "LOST: Autopilot Deployment Profile" -Items $deltaPolicies.DeploymentProfiles -AssignmentReason { param($item) $item.AssignmentReason } Add-ExportData -ExportData $exportData -Category "LOST: Enrollment Status Page Profile" -Items $deltaPolicies.ESPProfiles -AssignmentReason { param($item) $item.AssignmentReason } Add-ExportData -ExportData $exportData -Category "LOST: Cloud PC Provisioning Policy" -Items $deltaPolicies.CloudPCProvisioningPolicies -AssignmentReason { param($item) $item.AssignmentReason } Add-ExportData -ExportData $exportData -Category "LOST: Cloud PC User Setting" -Items $deltaPolicies.CloudPCUserSettings -AssignmentReason { param($item) $item.AssignmentReason } foreach ($conflict in $conflictPolicies) { $null = $exportData.Add([PSCustomObject]@{ Category = "CONFLICT: $($conflict.Category)" Item = "$($conflict.PolicyName) (ID: $($conflict.PolicyId))" ScopeTags = "" AssignmentReason = $conflict.ConflictType }) } Export-ResultsIfRequested -ExportData $exportData -DefaultFileName "IntuneGroupRemovalImpact.csv" -ForceExport:$ExportToCSV -CustomExportPath $ExportPath } |