Entra ID: Optimizing Dynamic Group Membership Evaluation

Operators:

Recently, Entra ID team pulled off -contains operator from dynamic group creation UI but it still can be used in rule builder. While we wait for an official communication/documentation update by Entra ID team, I did some analysis with Graph queries on Entra ID device and user objects to find the supported operators and parameters. From the testing, it is evident that the contains function is not supported, while -startsWith function is supported through Graph.

As per above analysis, using the -contains function could prove costly as the data processing needs to be done outside of Graph.

Properties:

Also from the documentation on Advanced query parameters, there are non-indexed properties that are not available through Graph filters.

While, I couldn’t find a list of indexed vs non-indexed properties available publicly, I did more research and found that user resource type and device resource type documentation lists properties along with information whether $filter parameter is supported and if supported, also provides list of allowed operators.

Let’s experiment with 3 properties as below.

Property NameSupportability

deviceCategory

Documented and tested that it does not support $filter

enrollmentProfileName

No documentation on $filter support. But when tested with Graph queries, it supports $filter with advanced query parameters: -Countvariable and -ConsistencyLevel

extensionAttributes

Documented and tested that it supports $filter with advanced query parameters: -Countvariable and -ConsistencyLevel

As per above analysis, If we use a property that is supported through $filter parameter along with a supported operator as per the documentation, the dynamic device evaluation is expected to be done within the Graph. Else like where-object clause in PS, the entire set of users/devices needs to be processed which will increase the membership evaluation time.

What next?

Here is a PS snippet to get a html report of all dynamic groups along with membership rules. You can review the rules for any such properties (like deviceCategory) or operators (especially –contains, -match etc.,), test it through Graph API and modify accordingly to match your oraganizational requirements.

<#
DISCLAIMER STARTS 
THIS SAMPLE CODE IS PROVIDED FOR THE PURPOSE OF ILLUSTRATION ONLY AND IS NOT INTENDED TO BE USED IN A PRODUCTION ENVIRONMENT. THIS SAMPLE CODE AND ANY RELATED INFORMATION ARE PROVIDED IS "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE."
DISCLAIMER ENDS
#>

#Set Report Location Variables
$ReportLocation = "C:\Windows\Temp"
$ReportName = "Entra-DynamicGroups-Report-$(get-date -format "yyyy-M-dd").html"
$ReportPath = "$ReportLocation\$ReportName"

#Connect with MS Graph
Connect-MgGraph -Scopes GroupMember.Read.All

#Get list of all Dynamic Groups
$DynamicGroups = Get-MgGroup -Filter "groupTypes/any(s:s eq 'DynamicMembership')" -All | Select Id,DisplayName,Description,CreatedDateTime,MembershipRule
$userDynamicGroups = $DynamicGroups | where {$_.MembershipRule -match "user\."}
$deviceDynamicGroups = $DynamicGroups | where {$_.MembershipRule -match "device\."}

#Create header for HTML Report
$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>"

#Create Report contents
$ReportOutput = "<h1>Dynamic Groups</h1>"
$ReportOutput += "<p>Total Dynamic Groups      :  $($DynamicGroups.Count)</p>"
$ReportOutput += "<h2>Dynamic User Groups</h2>"
$ReportOutput += "<p>Total Dynamic User Groups      :  $($userDynamicGroups.Count)</p>"
$ReportOutput += $userDynamicGroups | ConvertTo-Html -Fragment 
$ReportOutput += "<h2>Dynamic Device Groups</h2>"
$ReportOutput += "<p>Total Dynamic Device Groups      :  $($deviceDynamicGroups.Count)</p>"
$ReportOutput += $deviceDynamicGroups | ConvertTo-Html -Fragment 

#Generate Report
ConvertTo-HTML -head $Head -body "$ReportOutput" | Out-File $ReportPath

#Open Report
Invoke-Item $ReportPath

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.