Dynamic Win 11 Supported Group

Dynamic security groups in Azure AD are great, but wouldn’t it be great if a dynamic query existed to add to groups based on Windows 11 compatibility.

Until such a query exists, I have put together a script using the metrics from Endpoint Analytics Work from Anywhere report.

As usual, the script can be found on GitHub here

To make it as dynamic as possible, I would recommend using Azure Automation Runbook to run regularly (obviously with an app registration)

After connecting to Graph, it creates two lists of machines, compliant and non-compliant

First we need to handle pagination with this function

function getallpagination () {
    <#
.SYNOPSIS
This function is used to grab all items from Graph API that are paginated
.DESCRIPTION
The function connects to the Graph API Interface and gets all items from the API that are paginated
.EXAMPLE
getallpagination -url "https://graph.microsoft.com/v1.0/groups"
 Returns all items
.NOTES
 NAME: getallpagination
#>
[cmdletbinding()]
    
param
(
    $url
)
    $response = (Invoke-MgGraphRequest -uri $url -Method Get -OutputType PSObject)
    $alloutput = $response.value
    
    $alloutputNextLink = $response."@odata.nextLink"
    
    while ($null -ne $alloutputNextLink) {
        $alloutputResponse = (Invoke-MGGraphRequest -Uri $alloutputNextLink -Method Get -outputType PSObject)
        $alloutputNextLink = $alloutputResponse."@odata.nextLink"
        $alloutput += $alloutputResponse.value
    }
    
    return $alloutput
    }

Then grab the results


##Get Devices compliant/not compliant with windows 11
write-host "Inspecting devices for Windows 11 compliance"
$reporturi = "https://graph.microsoft.com/beta/deviceManagement/userExperienceAnalyticsWorkFromAnywhereMetrics('allDevices')/metricDevices?`$select=id,deviceName,upgradeEligibility,azureAdJoinType"

$reportdata = (getallpagination -url $reporturi)

$compliantdevices = @()
$noncompliantdevices = @()
write-host "Checking Machines for Compatibility"
$counter = 0

foreach ($machine in $reportdata) {
    $counter++
    $deviceid = $machine.id
    Write-Progress -Activity 'Processing Devices' -CurrentOperation $deviceid -PercentComplete (($counter / $reportdata.count) * 100)

    $w11compliance = $machine.upgradeEligibility
    if ($w11compliance -eq "Capable") {
        $compliantdevices += $machine.deviceName
    }
    else {
        $noncompliantdevices += $machine.deviceName
    }
}

Next, it checks if the groups exist already and if not creates the two groups.

After creating, it checks if the machine is in the group and if not, adds it in


write-host "Creating AAD Groups"
##Create AAD Groups
write-host "Creating Windows 11 Group"
$win11groupexist = (get-mggroup -filter "displayName eq '$w11groupname'").id
write-host "Creating Windows 10 Group"
$win10groupexist = (get-mggroup -filter "displayName eq '$w10groupname'").id

##Windows 11
##Check if group exists
write-host "Checking if Windows 11 Group Exists"
if ($null -ne $win11groupexist) {
    $allmembers = get-mggroupmember -All -GroupId $win11groupexist
##It exists, add members
write-host "Windows 11 Group Exists, adding members"
foreach ($compliantdevice in $compliantdevices) {
    $compliantdeviceid = ($alldevices | Where-Object displayName -eq $compliantdevice).id
    ##Check if already in the group
    write-host "Checking if $compliantdevice is already in the group"
    $groupmember = ($allmembers) | where-object ID -eq $compliantdeviceid
    if ($null -eq $groupmember) {
    write-host "Adding $compliantdevice to the group"
   new-mggroupmember -GroupId $win11groupexist -DirectoryObjectId  $compliantdeviceid
    }
}
}
else {
##Does not, create it first
write-host "Windows 11 Group does not exist, creating it"
$win11group = new-mggroup -DisplayName $w11groupname -Description "Devices Compliant with Windows 11" -SecurityEnabled -mailEnabled:$false -MailNickname $w11groupname
$win11groupid = $win11group.id
$allmembers = get-mggroupmember -All -GroupId $win11groupid
foreach ($compliantdevice in $compliantdevices) {
    $compliantdeviceid = ($alldevices | Where-Object displayName -eq $compliantdevice).id

    ##Check if already in the group
    write-host "Checking if $compliantdevice is already in the group"
    $groupmember = ($allmembers) | where-object ID -eq $compliantdeviceid
    if ($null -eq $groupmember) {
        write-host "Adding $compliantdevice to the group"
    new-mggroupmember -GroupId $win11groupid -DirectoryObjectId  $compliantdeviceid
    }
}
}


##Windows 10
if ($null -ne $win10groupexist) {
    $allmembers = get-mggroupmember -All -GroupId $win10groupexist
##It exists, add members
write-host "Windows 10 Group Exists, adding members"
foreach ($noncompliantdevice in $noncompliantdevices) {
    $noncompliantdeviceid = ($alldevices | Where-Object displayName -eq $noncompliantdevice).id
    ##Check if already in the group
    write-host "Checking if $noncompliantdevice is already in the group"
    $groupmember = ($allmembers) | where-object ID -eq $noncompliantdeviceid
    if ($null -eq $groupmember) {
    write-host "Adding $noncompliantdevice to the group"
   new-mggroupmember -GroupId $win10groupexist -DirectoryObjectId  $noncompliantdeviceid
    }
}
}
else {
##Does not, create it first
write-host "Windows 10 Group does not exist, creating it"
$win10group = new-mggroup -DisplayName $w10groupname -Description "Devices Not Compliant with Windows 10" -SecurityEnabled -MailEnabled:$false -MailNickname $w10groupname
$win10groupid = $win10group.id
$allmembers = get-mggroupmember -All -GroupId $win10groupid
foreach ($noncompliantdevice in $noncompliantdevices) {
    $noncompliantdeviceid = ($alldevices | Where-Object displayName -eq $noncompliantdevice).id

    ##Check if already in the group
    write-host "Checking if $noncompliantdevice is already in the group"
    $groupmember = ($allmembers) | where-object ID -eq $noncompliantdeviceid
    if ($null -eq $groupmember) {
        write-host "Adding $noncompliantdevice to the group"
    new-mggroupmember -GroupId $win10groupid -DirectoryObjectId  $noncompliantdeviceid
    }
}
}

I then use these groups to assign and exclude against Feature Update policies, but whatever works for you.

3 thoughts on “Dynamic Win 11 Supported Group”

Leave a Comment