private/core/Get-FilteredPoliciesBySetting.ps1
<# .SYNOPSIS Filters policies based on specific setting configurations and their expected values. .DESCRIPTION This function filters an array of policies by checking if they contain specific settings with expected values. Each setting can have its own path configuration for navigating the policy's JSON structure, making this function flexible enough to work with different policy types and structures. .PARAMETER Policies An array of policy objects to filter. Each policy should contain settings that can be navigated using the paths specified in RequiredSettings. .PARAMETER RequiredSettings A hashtable where each key is a setting definition ID and the value is a configuration object containing: - ExpectedValues: Array of values that the setting should have - ContainerPath: Dot-separated path to the container holding the settings (e.g., 'settings.settinginstance.groupSettingCollectionValue.children') - SettingIdPath: Property name or path to access the setting ID within each container item - ValuePath: Property name or path to access the setting value within the target setting - Description: (Optional) Human-readable description of what the setting controls .OUTPUTS System.Array Returns an array of policy objects that contain all of the required settings with matching values. .EXAMPLE $requiredSettings = @{ 'com.apple.extensiblesso_extensionidentifier' = @{ ExpectedValues = @('com.microsoft.CompanyPortalMac.ssoextension') ContainerPath = 'settings.settinginstance.groupSettingCollectionValue.children' SettingIdPath = 'settingDefinitionId' ValuePath = 'simplesettingvalue.value' Description = 'Microsoft SSO Extension Identifier' } } $filteredPolicies = Get-FilteredPoliciesBySetting -Policies $allPolicies -RequiredSettings $requiredSettings Filters policies to include only those that have the Microsoft SSO extension configured. .EXAMPLE $multipleSettings = @{ 'setting.id.one' = @{ ExpectedValues = @('value1', 'value2') ContainerPath = 'settings.configurations' SettingIdPath = 'id' ValuePath = 'value' } 'setting.id.two' = @{ ExpectedValues = @('requiredvalue') ContainerPath = 'customSettings.payloadContent' SettingIdPath = 'payloadType' ValuePath = 'payloadContent.value' } } $filteredPolicies = Get-FilteredPoliciesBySetting -Policies $policies -RequiredSettings $multipleSettings Filters policies that contain both required settings, each located in different JSON paths. .NOTES - The function uses a nested helper function Get-NestedProperty to safely navigate object properties - If any path evaluation fails, the function logs a verbose message and continues with the next setting - The function returns policies that match ALL of the required settings (AND logic) - Empty or null policy arrays are handled gracefully by returning an empty array #> function Get-FilteredPoliciesBySetting { [CmdletBinding()] param( [Parameter(Mandatory)] [array]$Policies, [Parameter(Mandatory)] [hashtable]$RequiredSettings ) <# .SYNOPSIS Retrieves a nested property value from an object using a dot-separated path. .DESCRIPTION Traverses an object's properties according to the provided dot-separated path and returns the value found at that path, or $null if any segment is missing. .PARAMETER InputObject The object from which to retrieve the nested property. .PARAMETER Path The dot-separated path string indicating the property to retrieve (e.g., 'settings.settinginstance.groupSettingCollectionValue'). .OUTPUTS Returns the value at the specified path, or $null if not found. #> function Get-NestedProperty { [CmdletBinding()] param( [Parameter(Mandatory)][object]$InputObject, [Parameter(Mandatory)][string]$Path ) $current = $InputObject foreach ($segment in $Path -split '\.') { if ($null -eq $current) { return $null } $current = $current."$segment" } return $current } $filteredPolicies = @() foreach ($policy in $Policies) { $matchedSettingsCount = 0 # Check each required setting configuration foreach ($settingId in $RequiredSettings.Keys) { $settingConfig = $RequiredSettings[$settingId] $expectedValues = $settingConfig.ExpectedValues $containerPath = $settingConfig.ContainerPath $settingIdPath = $settingConfig.SettingIdPath $valuePath = $settingConfig.ValuePath $settingMatched = $false try { # Get the settings container using the configured path $settingsContainer = Get-NestedProperty -InputObject $policy -Path $containerPath if ($settingsContainer) { # Find the specific setting by ID $targetSetting = $settingsContainer | Where-Object { (Get-NestedProperty -InputObject $_ -Path $settingIdPath) -eq $settingId } if ($targetSetting) { # Get actual values using the configured value path $actualValues = @(Get-NestedProperty -InputObject $targetSetting -Path $valuePath) # Check if any actual value matches any expected value foreach ($actualValue in $actualValues) { if ($expectedValues -contains $actualValue) { $settingMatched = $true break } } } } } catch { Write-Verbose "Failed to evaluate paths for setting $settingId : $_" continue } if ($settingMatched) { $matchedSettingsCount++ } } # Policy must match ALL required settings (AND logic) if ($matchedSettingsCount -eq $RequiredSettings.Keys.Count) { $filteredPolicies += $policy } } return $filteredPolicies } |