create-w365-groups.ps1
<#PSScriptInfo
.VERSION 1.00 .GUID 90ccb2c9-a75c-4d6b-a92a-a12866166b84 .AUTHOR AndrewTaylor .DESCRIPTION Creates Windows 365 for all purchased SKUs and then nests them within master groups .COMPANYNAME .COPYRIGHT GPL .TAGS intune endpoint MEM environment .LICENSEURI https://github.com/andrew-s-taylor/public/blob/main/LICENSE .PROJECTURI https://github.com/andrew-s-taylor/public .ICONURI .EXTERNALMODULEDEPENDENCIES .REQUIREDSCRIPTS .EXTERNALSCRIPTDEPENDENCIES .RELEASENOTES #> <# .SYNOPSIS Creates Windows 365 groups for each SKU .DESCRIPTION Creates Windows 365 for all purchased SKUs and then nests them within master groups .INPUTS None .OUTPUTS Creates a log file in %Temp% .NOTES Version: 1.00 Author: Andrew Taylor WWW: andrewstaylor.com Creation Date: 25/07/2022 Purpose/Change: Initial script development .EXAMPLE N/A #> ################################################################################################################################## ################# INITIALIZATION ################# ################################################################################################################################## $ErrorActionPreference = "Continue" ##Start Logging to %TEMP%\intune.log $date = get-date -format yyyyMMddTHHmmssffff Start-Transcript -Path $env:TEMP\intune-$date.log #Install MS Graph if not available Write-Host "Installing Microsoft Graph modules if required (current user scope)" #Install MS Graph if not available #Install MS Graph if not available if (Get-Module -ListAvailable -Name Microsoft.Graph.Authentication) { Write-Host "Microsoft Graph Authentication Already Installed" } else { Install-Module -Name Microsoft.Graph.Authentication -Scope CurrentUser -Repository PSGallery -Force -RequiredVersion 1.19.0 Write-Host "Microsoft Graph Authentication Installed" } if (Get-Module -ListAvailable -Name Microsoft.Graph.Groups) { Write-Host "Microsoft Graph Groups Already Installed " } else { Install-Module -Name Microsoft.Graph.Groups -Scope CurrentUser -Repository PSGallery -Force -RequiredVersion 1.19.0 Write-Host "Microsoft Graph Groups Installed" } # Load the Graph module Import-Module microsoft.graph.authentication import-module microsoft.Graph.Groups ############################################################ ############################################################ ############# CHANGE THIS TO USE IN AUTOMATION ############# ############################################################ ############################################################ $automated = "no" ############################################################ ############################################################ ############# AUTOMATION NOTES ############# ############################################################ ## You need to add these modules to your Automation Account if using Azure Automation ## Don't use the V2 preview versions ## https://www.powershellgallery.com/packages/Microsoft.Graph.Authentication/1.19.0 ## https://www.powershellgallery.com/packages/Microsoft.Graph.Groups/1.19.0 if ($automated -eq "yes") { ################################################################################################################################## ################# VARIABLES ################# ################################################################################################################################## $clientid = "YOUR_AAD_REG_ID" $clientsecret = "YOUR_CLIENT_SECRET" $sourcetenant = "TENANT_ID" ################################################################################################################################## ################# END VARIABLES ################# ################################################################################################################################## } ############################################################################################################### ###### MS Graph Implementations ###### ############################################################################################################### if ($automated -eq "yes") { $body = @{ grant_type="client_credentials"; client_id=$clientId; client_secret=$clientSecret; scope="https://graph.microsoft.com/.default"; } $response = Invoke-RestMethod -Method Post -Uri https://login.microsoftonline.com/$sourcetenant/oauth2/v2.0/token -Body $body $accessToken = $response.access_token Select-MgProfile -Name Beta Connect-MgGraph -AccessToken $accessToken write-host "Graph Connection Established" } else { ##Connect to Graph Select-MgProfile -Name Beta Connect-MgGraph -Scopes Domain.Read.All, Domain.ReadWrite.All, Directory.Read.All openid, profile, email, offline_access, Group.ReadWrite.All } ############################################################################################################### ###### ENGAGE ###### ############################################################################################################### ##Create AAD Group write-host "Creating Azure AD Groups" ##Create W365 Groups for W365 users, manually assigned ##Check if group exists first $w365users = Get-MgGroup -Filter "DisplayName eq 'W365-Users'" if ($null -eq $w365users) { write-host "Creating W365 Users Group" $w365users = New-MGGroup -DisplayName "W365-Users" -Description "Windows 365 Users" -MailEnabled:$False -MailNickName "W365Users" -SecurityEnabled -IsAssignableToRole:$false write-host "W365 Users Group Created" } else { write-host "W365 Users Group Already Exists" } ##Check if device group exists $w365devices = Get-MgGroup -Filter "DisplayName eq 'W365 Devices'" if ($null -eq $w365devices) { ##Create Devices Group with dynamic membership based on Cloud PC model type write-host "Creating W365 Devices Group - Dynamically Assigned" $w365devices = New-MGGroup -DisplayName "W365 Devices" -Description "Dynamic group for all Windows 365 Single User devices" -MailEnabled:$False -MailNickName "w365devices" -SecurityEnabled -GroupTypes "DynamicMembership" -MembershipRule "(device.deviceModel -startsWith ""Cloud"")" -MembershipRuleProcessingState "On" -IsAssignableToRole:$false write-host "W365 Devices Group Created" } else { write-host "W365 Devices Group Already Exists" } ## Get the Group ID for our Win365 devices $groupid = $w365users.Id ##Grab all SKUs and create groups accordingly ##Assign Licenses to Group write-host "Creating groups and assigning licenses" ##Get Assigned SKUs ##Get All skus in the tenant write-host "Getting SKUs" $sku2 = ((Invoke-MgGraphRequest -uri "https://graph.microsoft.com/v1.0/subscribedSkus" -method get -OutputType PSObject).value) ##Loop through looking for W365 enterprise non-frontline SKUs (currently start with either CPC_E) $skuids = @() foreach ($sku in $sku2) { $part = $sku.skuPartNumber if ($part -like "*CPC_E*") { $skuidsobject = [pscustomobject]@{ sid = $sku.skuid part = $part } $skuids += $skuidsobject write-host "SKU Found - $part" } } $i = 1 foreach ($skuiditem in $skuids) { $skuid = $skuiditem.sid $skupart = $skuiditem.part ##Check if this group already exists $w365userssku = Get-MgGroup -Filter "DisplayName eq 'W365-Users-$skupart'" if ($null -eq $w365userssku) { ##Create W365 Groups for W365 users of each sku, manually assigned write-host "Creating W365 Users Group for SKU $skupart" $w365userssku = New-MGGroup -DisplayName "W365-Users-$skupart" -Description "Windows 365 Users $skupart" -MailEnabled:$False -MailNickName "W365Users_$i" -SecurityEnabled -IsAssignableToRole:$false write-host "W365 Users Group Created for SKU $skupart" $skugroupid = $w365userssku.Id ##Assign the license to the group write-host "Assigning License to Group - W365 Users $skupart" $uri = "https://graph.microsoft.com/v1.0/groups/$skugroupid/assignLicense" $body = @" { "addLicenses": [{ "disabledPlans": [], "skuId": "$skuid" }], "removeLicenses": [] } "@ Invoke-MgGraphRequest -Uri $uri -Method POST -Body $body -ContentType "application/json" write-host "License Assigned to Group W365 Users $skupart" ##Add to main group write-host "Nesting Group $skugroupid in $groupid" New-MgGroupMember -GroupId "$groupid" -DirectoryObjectId "$skugroupid" write-host "Group $skugroupid nested in $groupid" $i++ } else { write-host "Group W365-Users-$skupart already exists, skipping" } } ###############Front Line Users ##Create AAD Group ##Check if group exists first $w365frontlineusers = Get-MgGroup -Filter "DisplayName eq 'W365-Frontline-Users'" if ($null -eq $w365users) { ##Create W365 Groups for W365 Frontline users, manually assigned write-host "Creating W365 Frontline Users Group" $w365frontlineusers = New-MGGroup -DisplayName "W365-Frontline-Users" -Description "Windows 365 Frontline Users" -MailEnabled:$False -MailNickName "W365FrontlineUsers" -SecurityEnabled -IsAssignableToRole:$false write-host "W365 Frontline Users Group Created" } else { write-host "W365 Frontline Users Group already exists" } ##Assign Licenses to Group write-host "Assigning Licenses to Group" $frontlinegroupid = $w365frontlineusers.Id ##Get Assigned SKUs ##Get All skus in the tenant write-host "Getting SKUs" $skuf2 = ((Invoke-MgGraphRequest -uri "https://graph.microsoft.com/v1.0/subscribedSkus" -method get -OutputType PSObject).value) ##Loop through looking for W365 SKUs (currently start with Windows_365_S) $skuidfs = @() foreach ($skuf in $skuf2) { $partf = $skuf.skuPartNumber if (($partf -like "*Windows_365_S*")) { $skuidsobjectf = [pscustomobject]@{ sid = $skuf.skuid part = $partf } $skuidfs += $skuidsobjectf write-host "SKU Found - $partf" } } $i = 1 foreach ($skuidfitem in $skuidfs) { $skuidf = $skuidfitem.sid $skupartf = $skuidfitem.part ##Check if group exists $w365usersskuf = Get-MgGroup -Filter "DisplayName eq 'W365-Frontline-Users-$skupartf'" if ($null -eq $w365usersskuf) { ##Create W365 Groups for W365 users of each sku, manually assigned write-host "Creating W365 Users Group for SKU $skupartf" $w365usersskuf = New-MGGroup -DisplayName "W365-Frontline-Users-$skupartf" -Description "Windows 365 Frontline Users $skupartf" -MailEnabled:$False -MailNickName "W365Usersfront_$i" -SecurityEnabled -IsAssignableToRole:$false write-host "W365 Frontline Users Group Created for SKU $skuidf" $skugroupidf = $w365usersskuf.Id ##Assign the license to the group write-host "Assigning License to Group - W365 Users $skupartf" $uri = "https://graph.microsoft.com/v1.0/groups/$skugroupidf/assignLicense" $body = @" { "addLicenses": [{ "disabledPlans": [], "skuId": "$skuidf" }], "removeLicenses": [] } "@ Invoke-MgGraphRequest -Uri $uri -Method POST -Body $body -ContentType "application/json" write-host "License Assigned to Group W365 Users $skupartf" ##Add to main group write-host "Nesting Group $skugroupidf in $frontlinegroupid" New-MgGroupMember -GroupId "$frontlinegroupid" -DirectoryObjectId "$skugroupidf" write-host "Group $skugroupidf nested in $frontlinegroupid" $i++ } else { write-host "Group W365-Users-$skupartf already exists, skipping" } } |