Public/Get-IntunePolicyConflict.ps1
|
function Get-IntunePolicyConflict { <# .SYNOPSIS Finds overlapping Intune policy settings and potential conflicts. .DESCRIPTION Compares observed setting values across supported Settings Catalog, endpoint security intent and legacy device configuration profiles. A potential conflict is reported only when values differ and exact target evidence confirms overlap. The command does not claim the final setting enforced on a device. .PARAMETER Workload Optional workload objects from Get-IntuneAssignmentImpact. .PARAMETER Assignment Optional workload assignments from Get-IntuneAssignmentImpact. .EXAMPLE Get-IntunePolicyConflict .EXAMPLE $impact = Get-IntuneAssignmentImpact Get-IntunePolicyConflict -Workload $impact.Workloads -Assignment $impact.Assignments #> [CmdletBinding()] param( [AllowEmptyCollection()] [object[]] $Workload, [AllowEmptyCollection()] [object[]] $Assignment ) if (-not $PSBoundParameters.ContainsKey('Workload')) { $inventory = Get-IntuneAccessWorkloadAssignments $Workload = @($inventory.Workloads) $Assignment = @($inventory.Assignments) } elseif (-not $PSBoundParameters.ContainsKey('Assignment')) { $Assignment = @($Workload | ForEach-Object { Get-IntuneAccessProperty $_ 'Assignments' @() }) } $settingInventory = Get-IntuneAccessPolicySettings -Workload @($Workload) $findings = [Collections.Generic.List[object]]::new() foreach ($definitionGroup in @($settingInventory.Settings | Group-Object SettingDefinitionId)) { $policySettings = @($definitionGroup.Group | Sort-Object WorkloadId -Unique) for ($firstIndex = 0; $firstIndex -lt $policySettings.Count; $firstIndex++) { for ($secondIndex = $firstIndex + 1; $secondIndex -lt $policySettings.Count; $secondIndex++) { $first = $policySettings[$firstIndex] $second = $policySettings[$secondIndex] if ($first.WorkloadId -eq $second.WorkloadId) { continue } $overlap = Get-IntuneAccessPolicyTargetOverlap ` -FirstAssignment @($Assignment | Where-Object WorkloadId -EQ $first.WorkloadId) ` -SecondAssignment @($Assignment | Where-Object WorkloadId -EQ $second.WorkloadId) $valuesDiffer = [string] $first.ValueJson -cne [string] $second.ValueJson $findingState = if (-not $valuesDiffer) { 'SameValue' } elseif ($overlap.State -eq 'ConfirmedOverlap') { 'PotentialConflict' } else { 'NotEvaluated' } $findings.Add([PSCustomObject] @{ PSTypeName = 'IntuneAccess.PolicyConflictFinding' Id = "$($definitionGroup.Name)::$($first.WorkloadId)::$($second.WorkloadId)" SettingDefinitionId = [string] $definitionGroup.Name FirstPolicyId = [string] $first.WorkloadId FirstPolicyName = [string] $first.WorkloadName FirstValueJson = [string] $first.ValueJson SecondPolicyId = [string] $second.WorkloadId SecondPolicyName = [string] $second.WorkloadName SecondValueJson = [string] $second.ValueJson ValuesDiffer = $valuesDiffer TargetOverlapState = [string] $overlap.State TargetEvidence = @($overlap.Evidence) FindingState = $findingState Reason = [string] $overlap.Reason EvidenceState = 'CalculatedFromObservedSettingsAndAssignments' }) } } } $result = [PSCustomObject] @{ PSTypeName = 'IntuneAccess.PolicyConflictAnalysis' PolicySettings = @($settingInventory.Settings) Findings = $findings.ToArray() PotentialConflicts = @($findings | Where-Object FindingState -EQ 'PotentialConflict') PotentialConflictCount = @($findings | Where-Object FindingState -EQ 'PotentialConflict').Count UnevaluatedCount = @($findings | Where-Object FindingState -EQ 'NotEvaluated').Count CollectionStatus = @($settingInventory.CollectionStatus) Warnings = @($settingInventory.Warnings) ReadOnly = $true GeneratedAt = [DateTimeOffset]::Now ToolVersion = $script:IntuneAccessVersion } $result.PSObject.TypeNames.Insert(0, 'IntuneAccess.PolicyConflictAnalysis') $result } |