Support tip: Leveraging PowerShell to view and manage Microsoft Intune Assignment filters
Published Feb 29 2024 12:00 PM 4,990 Views

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.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.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.

Version history
Last update:
‎Feb 29 2024 12:14 PM
Updated by: