By: Gowdhaman K – Product Manager 2 | Microsoft Intune
Assignment filters in Intune allow you to narrow the assignment scope of policies. For example, you can create an assignment filter that includes only devices that are enrolled in Intune, run Windows 10, and have a specific hardware model. You can then assign a configuration profile or an app to All devices with this filter in include mode, and only the devices that match the criteria will receive the assignment. This way, you can ensure that your assignments are relevant and appropriate for your devices and users. Further, you can use the Associated Assignments tab in each assignment filter to review the associated assignments.
Each tenant can create and use up to 200 assignment filters; for some organizations, this limit might be quickly reached. To help IT admins manage them efficiently on a periodic basis, you can leverage PowerShell and Microsoft Graph API to create a report that will generate all assignment filters along with the rule and associated assignments.
Important: From a support perspective, Microsoft fully supports Intune and its ability to deploy shell scripts to macOS. However, Microsoft does not support the scripts themselves, even if they are on our GitHub repository. They are provided for example only. You are responsible for anything that they may do within your environment. Always test!
The sample script, provided below, exports the data in HTML format for review and corresponding CSVs to manipulate. The script has $ReportFolder parameter (with default value of “C:\Windows\temp”) where you will find three files on every execution.
A screen capture of the three files generated, a CSV for Associated assignments, a CSV for the Summary, and an HTML view of the generated report.
The report will have a summary table of all assignment filters in the tenant with filter type, platform, rule, and associated assignments count along with a few other common fields. A second table will list all associated assignments details for each filter with payload id, payload name, payload type and intent.
A screen capture of the generated assignment filters summary report.
Note: In this sample script, we use delegated permissions. If you want to run the script unattended in an automation tool, modify the script to leverage a client app registration along with a client secret – see Authentication module cmdlets in Microsoft Graph PowerShell for details on how to do this.
The script requires Microsoft Graph PowerShell modules. You can install these using the commands below:
Install-Module Microsoft.Graph
Install-Module Microsoft.Graph.Beta
Refer to Install the Microsoft Graph PowerShell SDK documentation for more info.
Sample script
Param (
$ReportFolder = “C:\Windows\Temp”
)
$Head = "<style>"
$Head +="BODY{background-color:#CCCCCC;font-family:Calibri,sans-serif; font-size: small;}"
$Head +="TABLE{border-width: 1px;border-style: solid;border-color: black;border-collapse: collapse; width: 98%;}"
$Head +="TH{border-width: 1px;padding: 0px;border-style: solid;border-color: black;background-color:#293956;color:white;padding: 5px; font-weight: bold;text-align:left;}"
$Head +="TD{border-width: 1px;padding: 0px;border-style: solid;border-color: black;background-color:#F0F0F0; padding: 2px;}"
$Head +="</style>"
$Now = Get-Date -Format "dd-MM-yyyy-HH-mm-ss"
$Stopwatch = [System.Diagnostics.Stopwatch]::StartNew()
#Connect to Microsoft Graph using delegated permissions
Write-Output "Connecting Microsoft Graph..."
Connect-MgGraph -scopes Group.Read.All, DeviceManagementManagedDevices.Read.All, DeviceManagementServiceConfig.Read.All, DeviceManagementApps.Read.All, DeviceManagementApps.Read.All, DeviceManagementConfiguration.Read.All, DeviceManagementConfiguration.Read.All, DeviceManagementApps.Read.All
#Get all Assigment Filters
$AssignmentFilters = Get-MgBetaDeviceManagementAssignmentFilter -All
#Get all Intune Payloads in the tenant
$AllPayloads = @()
$Workloads = `
"https://graph.microsoft.com/beta/deviceManagement/deviceCompliancePolicies",
"https://graph.microsoft.com/beta/deviceManagement/configurationPolicies",
"https://graph.microsoft.com/beta/deviceAppManagement/mobileApps",
"https://graph.microsoft.com/beta/deviceAppManagement/targetedManagedAppConfigurations",
"https://graph.microsoft.com/beta/deviceManagement/deviceManagementScripts",
"https://graph.microsoft.com/beta/deviceManagement/windowsAutopilotDeploymentProfiles",
"https://graph.microsoft.com/beta/deviceManagement/deviceHealthScripts",
"https://graph.microsoft.com/beta/deviceManagement/deviceConfigurations",
"https://graph.microsoft.com/beta/deviceManagement/groupPolicyConfigurations",
"https://graph.microsoft.com/beta/deviceAppManagement/mobileAppConfigurations",
"https://graph.microsoft.com/beta/deviceAppManagement/iosManagedAppProtections",
"https://graph.microsoft.com/beta/deviceAppManagement/androidManagedAppProtections",
"https://graph.microsoft.com/beta/deviceAppManagement/windowsManagedAppProtections",
"https://graph.microsoft.com/beta/deviceAppManagement/mdmWindowsInformationProtectionPolicies"
$c = 1
foreach ($Workload in $Workloads){
Write-Progress -Activity "Getting all configurations in the tenant.." -Status "Processing $Workload" -PercentComplete $($c*100/$($Workloads.count))
$uri = $Workload
$AllPayloads += (Invoke-MgGraphRequest -Method GET -Uri $uri).Value
$c++
}
#Initialize few variables
$AFResults = @()
$PSObject = @()
$Set = 1
#Loop all Assignment Filters to get payload information. Currently JSON batching supports only 20 requests at a time. So breaking down the total Assignment Filters by set of 20 each and getting the Payload Information and storing the output in $AFResults array.
Write-Output "Getting Payload Information of all Assignment Filters..."
For ($n = 1; $n -le $AssignmentFilters.count; $n++){
Write-Progress -Activity "Getting Payload Information of all Assignment Filters..." -Status "Processing $n out of $AssignmentFilters.count" -PercentComplete $($n*100/$AssignmentFilters.count)
$id = $n - 1
$AssignmentFilterId = $AssignmentFilters[$id].id
$PSObject += [PSCustomObject]@{
id = "$id"
method = "GET"
url = "deviceManagement/assignmentFilters/$($AssignmentFilterId)/payloads"
}
if (($n -eq $($Set*20)) -or ($n -eq $AssignmentFilters.count)){
$BatchRequestBody = [PSCustomObject]@{requests = $PSObject }
$JSONRequests = $BatchRequestBody | ConvertTo-Json -Depth 4
$AFResults += Invoke-MgGraphRequest -Method POST -Uri 'https://graph.microsoft.com/beta/$batch' -Body $JSONRequests -ContentType 'application/json' -ErrorAction Stop
$PSObject = @()
$Set ++
}
}
#Create Assignment Filter Summary Report
Write-Output "Creating Assignment Filter Summary Report..."
$Filters = $AssociatedAssignments = @()
For ($n = 1; $n -le $AssignmentFilters.count; $n++){
Write-Progress -Activity "Creating Assignment Filters Summary Report..." -Status "Processing $n out of $AssignmentFilters.count" -PercentComplete $($n*100/$AssignmentFilters.count)
$id = $n - 1
$Assignments = ($AFResults.responses | where {$_.id -eq $id}).body.value
$AssignmentsCount = $Assignments.count
$Filters += [PSCustomObject]@{
Id = $AssignmentFilters[$id].id
ManagementType = $AssignmentFilters[$id].AssignmentFilterManagementType
DisplayName = $AssignmentFilters[$id].DisplayName
Description = $AssignmentFilters[$id].Description
CreatedDateTime = $AssignmentFilters[$id].CreatedDateTime
LastModifiedDateTime = $AssignmentFilters[$id].LastModifiedDateTime
Platform = $AssignmentFilters[$id].Platform
RoleScopeTags = [string]$AssignmentFilters[$id].RoleScopeTags -replace " ",","
Rule = $AssignmentFilters[$id].Rule
AssociatedAssignmentsCount = $AssignmentsCount
}
If ($AssignmentsCount -gt 0) {
Foreach ($Assignment in $Assignments){
$PayloadName = (($AllPayloads | where {$_.id -eq $($Assignment.payloadId)})|select -Unique displayname).displayname
If (!($PayloadName)){
$PayloadName = (($AllPayloads | where {$_.id -eq $($Assignment.payloadId)})|select -Unique name).name
}
$AssociatedAssignments += [PSCustomObject]@{
Id = $AssignmentFilters[$id].id
ManagementType = $AssignmentFilters[$id].AssignmentFilterManagementType
DisplayName = $AssignmentFilters[$id].DisplayName
GroupId = $Assignment.groupId
PayloadId = $Assignment.payloadId
PayloadName = $PayloadName
PayloadType = $Assignment.payloadType
IntentType = $Assignment.assignmentFilterType
}
}
}
}
$ReportOutput += "<h2>Assignment Filters Summary</h2>"
$ReportOutput += $Filters | ConvertTo-Html -Fragment
$Filters | ConvertTo-Csv -NoTypeInformation > $ReportFolder\AssignmentFilters_Summary_$($Now).csv
$ReportOutput += "<h2>Assignment Filters Associated Assignments Summary</h2>"
$ReportOutput += $AssociatedAssignments | ConvertTo-Html -Fragment
$AssociatedAssignments | ConvertTo-Csv -NoTypeInformation > $ReportFolder\AssignmentFilters_AssociatedAssignments_$($Now).csv
ConvertTo-HTML -head $Head -body "$ReportOutput" | Out-File $ReportFolder\AssignmentFilters_Summary_Report_$($Now).htm
Invoke-Item $ReportFolder\AssignmentFilters_Summary_Report_$($Now).htm
$Stopwatch.Stop()
Write-Output "Time Taken for the script execution with batching:`n"
$Stopwatch.Elapsed
If you have any questions leave a comment below or reach out to us on X @IntuneSuppTeam! For more sample scripts, check out the Microsoft Intune GitHub repository.
Updated Feb 29, 2024
Version 2.0Intune_Support_Team
Microsoft
Joined October 11, 2018
Intune Customer Success
Follow this blog board to get notified when there's new activity