Src/Private/Get-AbrIntuneAppConfigPolicies.ps1
|
function Get-AbrIntuneAppConfigPolicies { <# .SYNOPSIS Documents Intune App Configuration Policies (managed device and managed app). .DESCRIPTION Collects and reports on: - Managed Device App Configuration policies (settings pushed to enrolled devices) - Managed App (MAM) App Configuration policies (settings pushed via App Protection) - Assignments with resolved group names and exclusion detection .NOTES Version: 0.1.0 Author: Pai Wei Sing #> [CmdletBinding()] param ( [Parameter(Position = 0, Mandatory)] [string]$TenantId ) begin { Write-PScriboMessage -Message "Collecting Intune App Configuration Policies for $TenantId." Show-AbrDebugExecutionTime -Start -TitleMessage 'App Config Policies' } process { Section -Style Heading2 'App Configuration Policies' { Paragraph "The following section documents App Configuration Policies configured in tenant $TenantId." BlankLine $TotalAppConfigPolicies = 0 $UnassignedAppConfigCount = 0 #region Managed Device App Config Policies try { Write-Host " - Retrieving App Configuration Policies (managed devices)..." $MdmConfigResp = Invoke-MgGraphRequest -Method GET ` -Uri "$($script:GraphEndpoint)/beta/deviceAppManagement/mobileAppConfigurations?`$expand=assignments" ` -ErrorAction SilentlyContinue $MdmConfigs = $MdmConfigResp.value if ($MdmConfigs -and @($MdmConfigs).Count -gt 0) { $null = ($TotalAppConfigPolicies += @($MdmConfigs).Count) Section -Style Heading3 'Managed Device App Configurations' { BlankLine $MdmObj = [System.Collections.ArrayList]::new() foreach ($Cfg in ($MdmConfigs | Sort-Object displayName)) { $assignResolved = Resolve-IntuneAssignments -Assignments $Cfg.assignments -CheckMemberCount:$script:CheckEmptyGroups if ($assignResolved.AssignmentSummary -eq 'Not assigned') { $null = ($UnassignedAppConfigCount++) } $scopeTagStr = if ($script:ResolveScopeTagNames -and $Cfg.roleScopeTagIds) { Get-IntuneScopeTagNames -ScopeTagIds $Cfg.roleScopeTagIds } else { 'Default' } $targetApps = if ($Cfg.targetedMobileApps -and @($Cfg.targetedMobileApps).Count -gt 0) { "$(@($Cfg.targetedMobileApps).Count) app(s)" } else { '--' } $cfgInObj = [ordered] @{ 'Policy Name' = $Cfg.displayName 'Platform' = if ($Cfg.targetedMobileApps) { 'MDM' } else { '--' } 'Targeted Apps' = $targetApps 'Included Groups' = $assignResolved.IncludedGroups 'Excluded Groups' = if ($script:ShowExcludedGroups) { $assignResolved.ExcludedGroups } else { $null } 'Scope Tags' = $scopeTagStr 'Last Modified' = if ($Cfg.lastModifiedDateTime) { ([datetime]$Cfg.lastModifiedDateTime).ToString('yyyy-MM-dd') } else { '--' } } $MdmObj.Add([pscustomobject]$cfgInObj) | Out-Null } $null = (& { if ($HealthCheck.Intune.AppManagement) { $null = ($MdmObj | Where-Object { $_.'Included Groups' -eq '--' } | Set-Style -Style Warning | Out-Null) } }) $MdmTableParams = @{ Name = "Managed Device App Configurations - $TenantId"; ColumnWidths = 18, 7, 10, 20, 18, 8, 19 } if ($Report.ShowTableCaptions) { $MdmTableParams['Caption'] = "- $($MdmTableParams.Name)" } $MdmObj | Table @MdmTableParams if (Get-IntuneExcelSheetEnabled -SheetKey 'AppConfigPolicies') { $script:ExcelSheets['App Config Policies (MDM)'] = $MdmObj } if (Get-IntuneBackupSectionEnabled -SectionKey 'AppConfigPolicies') { $script:BackupData['AppConfigPolicies'] = $MdmConfigs } #region InfoLevel 2 if ($InfoLevel.AppConfigPolicies -ge 2) { foreach ($Cfg in ($MdmConfigs | Sort-Object displayName)) { $assignResolved = Resolve-IntuneAssignments -Assignments $Cfg.assignments Section -Style Heading4 $Cfg.displayName { BlankLine $ovObj = [System.Collections.ArrayList]::new() $ovObj.Add([pscustomobject]@{ Setting = 'Policy Name'; Value = $Cfg.displayName }) | Out-Null $ovObj.Add([pscustomobject]@{ Setting = 'Description'; Value = if ($Cfg.description) { $Cfg.description } else { '--' } }) | Out-Null # Resolve targeted app names from the mobileApps endpoint if ($Cfg.targetedMobileApps -and @($Cfg.targetedMobileApps).Count -gt 0) { $appNameList = $Cfg.targetedMobileApps | ForEach-Object { $appId = if ($_ -is [string]) { $_ } else { $_.id } if ($appId) { try { $ar = Invoke-MgGraphRequest -Method GET ` -Uri "$($script:GraphEndpoint)/beta/deviceAppManagement/mobileApps/$appId`?`$select=displayName" ` -ErrorAction Stop if ($ar.displayName) { $ar.displayName } else { $appId } } catch { $appId } } } $ovObj.Add([pscustomobject]@{ Setting = 'Targeted Apps'; Value = ($appNameList -join '; ') }) | Out-Null } else { $ovObj.Add([pscustomobject]@{ Setting = 'Targeted Apps'; Value = '--' }) | Out-Null } $ovObj.Add([pscustomobject]@{ Setting = 'Included Groups'; Value = $assignResolved.IncludedGroups }) | Out-Null $ovObj.Add([pscustomobject]@{ Setting = 'Excluded Groups'; Value = $assignResolved.ExcludedGroups }) | Out-Null $ovObj.Add([pscustomobject]@{ Setting = 'Last Modified'; Value = if ($Cfg.lastModifiedDateTime) { ([datetime]$Cfg.lastModifiedDateTime).ToString('yyyy-MM-dd') } else { '--' } }) | Out-Null $OvParams = @{ Name = "App Config Detail - $($Cfg.displayName)"; ColumnWidths = 30, 70 } if ($Report.ShowTableCaptions) { $OvParams['Caption'] = "- $($OvParams.Name)" } $ovObj | Table @OvParams # Custom settings key-value pairs # settings[] items have a nested structure: { name/key, settingValue: { value/... } } # payloadJson is used for XML/JSON payloads (e.g. OEMConfig) if ($Cfg.settings -and @($Cfg.settings).Count -gt 0) { BlankLine Paragraph "Custom Settings ($(@($Cfg.settings).Count) setting(s)):" BlankLine $kvRows = $Cfg.settings | ForEach-Object { $settingKey = if ($_ -is [System.Collections.IDictionary]) { if ($_['name']) { $_['name'] } elseif ($_['key']) { $_['key'] } else { '--' } } else { if ($_.name) { $_.name } elseif ($_.key) { $_.key } else { '--' } } # settingValue is a nested object with a 'value' property $sv = if ($_ -is [System.Collections.IDictionary]) { $_['settingValue'] } else { $_.settingValue } $rawVal = if ($sv -is [System.Collections.IDictionary]) { $sv['value'] } elseif ($null -ne $sv) { $sv.value } else { # Fallback: direct value property if ($_ -is [System.Collections.IDictionary]) { $_['value'] } else { $_.value } } $displayVal = if ($null -ne $rawVal) { $s = "$rawVal" if ($s.Length -gt 100) { "$($s.Substring(0,100))..." } else { $s } } else { '--' } [pscustomobject]([ordered]@{ 'Key' = $settingKey; 'Value' = $displayVal }) } $KvParams = @{ Name = "Settings - $($Cfg.displayName)"; ColumnWidths = 40, 60 } if ($Report.ShowTableCaptions) { $KvParams['Caption'] = "- $($KvParams.Name)" } $kvRows | Table @KvParams } elseif ($Cfg.payloadJson) { BlankLine Paragraph "Configuration payload: JSON/XML payload configured (see backup export for full content)." } } } } #endregion } } } catch { if (Test-AbrGraphForbidden -ErrorRecord $_) { Write-AbrPermissionError -Section 'App Configuration Policies' -RequiredRole 'Intune Service Administrator or Global Administrator' } else { Write-AbrSectionError -Section 'App Configuration Policies' -Message "$($_.Exception.Message)" } } #endregion #region MAM App Config Policies try { Write-Host " - Retrieving App Configuration Policies (managed apps / MAM)..." $MamConfigResp = Invoke-MgGraphRequest -Method GET ` -Uri "$($script:GraphEndpoint)/beta/deviceAppManagement/targetedManagedAppConfigurations?`$expand=assignments" ` -ErrorAction SilentlyContinue $MamConfigs = $MamConfigResp.value if ($MamConfigs -and @($MamConfigs).Count -gt 0) { $null = ($TotalAppConfigPolicies += @($MamConfigs).Count) Section -Style Heading3 'Managed App (MAM) Configurations' { BlankLine $MamObj = [System.Collections.ArrayList]::new() foreach ($Cfg in ($MamConfigs | Sort-Object displayName)) { $assignResolved = Resolve-IntuneAssignments -Assignments $Cfg.assignments -CheckMemberCount:$script:CheckEmptyGroups if ($assignResolved.AssignmentSummary -eq 'Not assigned') { $null = ($UnassignedAppConfigCount++) } $cfgInObj = [ordered] @{ 'Policy Name' = $Cfg.displayName 'Deployed Apps' = if ($Cfg.apps) { @($Cfg.apps).Count } else { 0 } 'Settings Count' = if ($Cfg.customSettings) { @($Cfg.customSettings).Count } else { 0 } 'Included Groups' = $assignResolved.IncludedGroups 'Excluded Groups' = if ($script:ShowExcludedGroups) { $assignResolved.ExcludedGroups } else { $null } 'Last Modified' = if ($Cfg.lastModifiedDateTime) { ([datetime]$Cfg.lastModifiedDateTime).ToString('yyyy-MM-dd') } else { '--' } } $MamObj.Add([pscustomobject]$cfgInObj) | Out-Null } $null = (& { if ($HealthCheck.Intune.AppManagement) { $null = ($MamObj | Where-Object { $_.'Included Groups' -eq '--' } | Set-Style -Style Warning | Out-Null) } }) $MamTableParams = @{ Name = "Managed App Configurations (MAM) - $TenantId"; ColumnWidths = 22, 12, 11, 22, 18, 15 } if ($Report.ShowTableCaptions) { $MamTableParams['Caption'] = "- $($MamTableParams.Name)" } $MamObj | Table @MamTableParams if (Get-IntuneExcelSheetEnabled -SheetKey 'AppConfigPolicies') { if ($script:ExcelSheets['App Config Policies (MAM)']) { $script:ExcelSheets['App Config Policies (MAM)'] += $MamObj } else { $script:ExcelSheets['App Config Policies (MAM)'] = $MamObj } } } } } catch { if (Test-AbrGraphForbidden -ErrorRecord $_) { Write-AbrPermissionError -Section 'MAM App Configuration Policies' -RequiredRole 'Intune Service Administrator or Global Administrator' } else { Write-AbrSectionError -Section 'MAM App Configuration Policies' -Message "$($_.Exception.Message)" } } #endregion if ($TotalAppConfigPolicies -eq 0) { Paragraph "No App Configuration Policies found in tenant $TenantId." } } } end { Show-AbrDebugExecutionTime -End -TitleMessage 'App Config Policies' } } |