Demo-AutopilotDevicePreparationPolicy.ps1
<#PSScriptInfo .VERSION 1.0.0.0 .GUID a9526506-99e7-4c01-98a7-f5fbcb240a70 .AUTHOR Frits van Drie .COMPANYNAME 3-Link Opleidingen (3-link.nl) .COPYRIGHT (c) 2023 3-Link bv (NL). Anyone is free to use and distribute this module freely without modification. If you like this or experience failures, please notify me .TAGS Demoscript .LICENSEURI .PROJECTURI .ICONURI .EXTERNALMODULEDEPENDENCIES PowerShellGet, Microsoft.Graph.apAuthentication .REQUIREDSCRIPTS .EXTERNALSCRIPTDEPENDENCIES .RELEASENOTES 1.0.0.0 (2024-09-30) Initial release .PRIVATEDATA #> <# .SYNOPSIS Full setup for demonstrating Autopilot 'Device Preparation Policies' .DESCRIPTION 'Device Preparation Policies' demonstration. This script will setup all needed components. .PARAMETER CsvPath The full path to the csv-file for importing Corporate Identifiers. To extract Corporate Identifiers (Manufacturer,Model,SerialNumber) from your Windows computer using PowerShell: Set-Content -Path $CsvPath -Encoding UTF8 -Value ("{0},{1},{2}" -f (Get-CimInstance -Class Win32_ComputerSystem).Manufacturer, (Get-CimInstance -Class Win32_ComputerSystem).Model, (Get-CimInstance -Class Win32_BIOS).SerialNumber ) .PARAMETER TenantDnsName The FQDN of the Entra tenant .PARAMETER CsvPath Full path to a Csv-file containing 'Corporate Identifier(s)' (optional) .LINK .NOTES Author : Frits van Drie (f.vandrie) Company : 3-Link Opleidingen (3-Link.nl) This script is developed for training and demonstration only. Do not run this script in a production environment. A perfect way to run this script is to open it in your favorite PowerShell editor and run each region separate in sequence. Prerequisites for this demo: . A valid subscription for 'EMS Enterprise E3 or E5' . A test computer/VM for registration with Autopilot in OOBE phase. Windows 11 23H2 or later, at least 4GB memory and 4 (v)CPU's . Access to internet for all computers . PowerShell 5.1, 7+ Requirements for the client computer to provision: . Windows 11, version 23H2 with KB5035942 or later – Windows installation media dated April 2024 or later has KB5035942 included. . Windows 11, version 22H2 with KB5035942 or later – Windows installation media dated April 2024 or later has KB5035942 included. This script will create or install: . Install some required PowerShell modules . Create a local Folder with scripts and csv-files . Create an Entra User account . Assign an EMSPremium license to the demo user . Create an Entra Dynamic Usergroup containing all users with 'EMSPremium' license . Create an Entra Devicegroup . Create an Entra Service Principal for 'Intune Provisioning Client' with User logon enabled. . Add 'Intune Provioning Client' as an owner of the devicegroup . Import some demo 'Corporate Identifiers' in Intune . Add 'Office 365' to Intune MAM if not already available . Upload some PowerShell scripts for demo . Create an Autopilot 'Device preparation policy' in Intune . If this script is run multiple times, most creations from previous runs will be removed and recreated. #> [CmdletBinding()] param ( [Parameter(Mandatory=$false)] $TenantDnsName = $TenantDnsName, [Parameter(Mandatory=$false)] [ValidateNotNullOrEmpty()] $CsvPath = $CsvPath ) cls #region: Requirements $invocationInfo = $myInvocation.InvocationName $currentUser = [System.Security.Principal.WindowsIdentity]::GetCurrent() $windowsPrincipal = New-Object System.Security.Principal.WindowsPrincipal($currentUser) Write-Host "Requirements" -f Cyan Write-Host "`tScript path : $invocationInfo" Write-Host "`tCurrent user: $($currentUser.Name)" # Device not in Autopilot # Device OS # MDM Auto enrollment # Personal device enrollment allowed #endregion #region: Variables Do { if ($TenantDnsName -notmatch '^([a-zA-Z0-9]{2,}\.){2,}[a-zA-Z0-9]{2,}$') { $validTenantName = $false } else { try { $null = Resolve-DnsName $TenantDnsName -ErrorAction Stop $validTenantName = $true } catch { $validTenantName = $false } } if (-not $validTenantName) { Write-Host "`tNot a valid Tenant DNS name: $TenantDnsName" -f Red $TenantDnsName = Read-Host "`tTenantname DNS Name" } } Until ($validTenantName) $demoFolderName = 'DemoIntuneDevicePreparation' $basePath = "$env:USERPROFILE\Documents" $demoFolderPath = "$basePath\$demoFolderName" $userGivenName = 'Ademo' $userSurName = 'Youser' $userDisplayName = "$userGivenName $userSurName" $userUpn = "$userGivenName@$tenantDnsName" $userPassPlain = 'DemoY0user' $dppName = 'Demo Device Prep Policy' $dppDescription = 'Autopilot Device preparation policy for demo' $userGroupName = 'Autopilot Device Prep Users' $deviceGroupName = 'Autopilot Device Prep Devices' $deviceGroupOwnerName = "Intune Provisioning Client" $deviceGroupOwnerAppId = 'f1346770-5b25-470b-88bd-d5744ab7952c' $intuneProductId = 'c1ec4a95-1f05-45b3-a911-aa3fa01094f5' $userGroupMembershipRule = "(user.assignedPlans -any (assignedPlan.servicePlanId -eq `"$intuneProductId`" -and assignedPlan.capabilityStatus -eq `"Enabled`"))" $filePath = "$demoFolderPath\CorpIdentifiers" $IdTypes = "Windows","Serial","IMEI" $corporateIdentifiersWindows = @" MICROSOFTCORPORATION,VIRTUALMACHINE,0667-1996-4296-7445-8157-7226-71 MICROSOFTCORPORATION,VIRTUALMACHINE,5554-8932-8110-6895-8157-8816-33 HP,Elitebook 640 G9,12234567890321 Lenovo,Thinkpad T14,02234567890123 Microsoft,Surface 5,56789012345678 "@ if ($CsvPath) { $corporateIdentifiersWindows += "`n$(Get-content -Path $CsvPath -ErrorAction Stop)" } $corporateIdentifiersIMEI = @" 123456789012345,iPad Linda 098765432109876,iPad Tom "@ $corporateIdentifiersSerial = @" RF81AB2RZP,Samsung A35 Betty F9FC34DEFHK9,iPhone 16 Barney RF67GK8DDA,Samsung Galaxy S24 Joe "@ $appName ='Microsoft 365 Apps for Windows 10 and later' $arrScripts = @( @{ 'FileName' = 'Set-LastExecute.ps1' 'Name' = 'User-Set-LastExecute' 'Description' = 'This script creates a folder (Intune) in the User Documents folder with a file containing the time of execution' 'Content' = @" New-Item -ItemType Directory -Path `"`$env:USERPROFILE\Documents`" -Name 'Intune' -Force (Get-Date -Format 'yyyy-MM-dd_HH:mm:ss') | Out-File -FilePath `"`$env:USERPROFILE\Documents\Intune\LastExecuted.txt`" -Append "@ 'Scope' = 'User' 'Assignments' = @("$deviceGroupName") }, @{ 'FileName' = 'Test-DppOSVersionRequirement.ps1' 'Name' = 'Test-DppOSVersionRequirement' 'Description' = 'This script will display a popup with OS version at user logon' 'Content' = @" `$osVersion = ([Environment]::OSVersion).version [version]`$reqOsVersion = '10.0.22631.0' `$wshell = New-Object -ComObject Wscript.Shell if (`$osVersion -lt `$reqOsVersion) { `$Output = `$wshell.Popup("This computer might not meet the OS requirements for Intune 'Device Preparation Policies'!`nRequired version: `$reqOsVersion`nCurrent version: `$osVersion",0,'Warning',48 + 4096) } else { `$Output = `$wshell.Popup("Current OS version: `$osVersion",0,'Warning',48 + 4096) } "@ 'Scope' = 'User' 'Assignments' = @("$deviceGroupName") } ) #endregion #region: Functions Write-Host 'Functions' -f Cyan Write-Host "`tConvertToBase64{}" Function ConvertToBase64 { [CmdletBinding()] param ( [parameter(Mandatory=$true)] $Path ) Write-Debug "Filepath: $Path" $content = Get-Content -Path $Path -Raw $byte_array = [System.Text.Encoding]::UTF8.GetBytes($content) $base64 = [System.Convert]::ToBase64String($byte_array) Write-Output $base64 } Write-Host "`tNewConfigurationPolicyAssignment{}" Function NewConfigurationPolicyAssignment { [CmdletBinding()] param ( [parameter(Mandatory=$true)] $configurationPolicyId, [parameter(Mandatory=$true)] $target ) $jsonTarget = $target | ConvertTo-Json $jsonBody = @" { "assignments": [ { "id": "", "source": "direct", "target": $jsonTarget } ] } "@ Write-Verbose "`t`tAssigning group" $uri = "https://graph.microsoft.com/beta/deviceManagement/configurationPolicies/$ConfigurationPolicyId/assign" try { $null = (Invoke-MgGraphRequest -Method POST -Uri $uri -Body $jsonBody -ErrorAction Stop).value Write-Verbose 'success' } catch { Write-Verbose 'failed' throw $_ } Write-Verbose "`tGet Current Assignments" $uri = "https://graph.microsoft.com/beta/deviceManagement/configurationPolicies/$ConfigurationPolicyId/assignments" try { $assignments = (Invoke-MgGraphRequest -Method GET -Uri $uri -ErrorAction Stop).value Write-Verbose 'success' } catch { Write-Verbose 'failed' throw $_ } foreach ($item in $assignments.target) { $odataType = $item.'@odata.type' if ($odataType -like '*exclusionGroupAssignmentTarget') { Write-Verbose "`t`tExcluded:" } else { Write-Verbose "`t`tIncluded:" } if ($item.groupId) { $uri = "https://graph.microsoft.com/beta/groups/$($item.groupId)" $grpDisplayName = (Invoke-MgGraphRequest -Method GET -Uri $uri -ErrorAction Stop).displayName Write-Verbose "`t`t$grpDisplayName [$($item.groupId)]" } else { Write-Verbose "`t`t$($item.'@odata.type')" } } } #endregion #region: Packages Write-Host "Setup: Packages" -f Cyan # Package provider $packageProviderName = 'NuGet' $ppMinimalVersion = '2.8.5.201' Write-Host "`tPackage provider" Write-Host "`t`tProvider Name : $packageProviderName" Write-Host "`t`tMinimal Version: $ppMinimalVersion " -NoNewline try { $packageProvider = Get-PackageProvider -Name $packageproviderName -ForceBootstrap -ErrorAction Stop | Where Version -ge $minimalVersion | Sort Version if ($packageProvider) { Write-Host 'present' -f Green Write-Host "`t`tCurrent version: $($packageProvider.Version)" } else { Write-Host "failed" -f Red } } catch { throw $_ } $repoName = 'PSGallery' try { Write-Host "`tGet Repository" Write-Host "`t`tName : $repoName " -NoNewline $repo = Get-PSRepository -Name $repoName -ErrorAction Stop Write-Host "present" -f Green if ($repo.InstallationPolicy -ne 'Trusted') { $color = 'Red' } else { $color = 'Green' } Write-Host "`t`tPolicy: " -NoNewline Write-Host "$($repo.InstallationPolicy)" -f $color } catch { Write-Host "failed" -f Red try { Write-Host "`tRegister Repository" Write-Host "`t`tName : $repoName " -NoNewline $repo = Register-PSRepository -Default -ErrorAction Stop Write-Host 'success' -f Green } catch { Write-Host 'failed' -f Red throw $_ } } if ($repo.InstallationPolicy -ne 'Trusted') { try { Write-Host "`tTrust Repository" Write-Host "`t`tName : $repoName" Set-PSRepository -Name $repoName -InstallationPolicy Trusted -ErrorAction Stop $repo = Get-PSRepository -Name $repoName -ErrorAction Stop Write-Host "`t`tPolicy: " -NoNewline Write-Host "$($repo.InstallationPolicy)" -f Green } catch { Write-Host 'failed' -f Red throw $_ } } #endregion #region: Modules Write-Host "Setup: Modules" -f Cyan $modules = @( 'PowerShellGet', 'Microsoft.Graph.Authentication' ) Write-Host "`tImport Module" $missingModule = $false foreach ($module in $modules) { try { Write-Host "`t`t$module " -NoNewline Import-Module -Name $module -ErrorAction Stop Write-Host "present" -f Green } catch { Write-Host "installing " -NoNewline -f yellow try { Install-Module $module -Repository PSGallery -Confirm:$false -Force -ErrorAction Stop Import-Module -Name $module -ErrorAction Stop Write-Host "success" -f Green } catch { Write-Host "failed" -f Red $missingModule = $true } } } if ($missingModule) { throw 'Missing one or more required modules' } #endregion #region: Connections Write-Host "Setup: Connections" -f Cyan Write-Host "`tMicrosoft Graph" $scopes = @( 'Application.ReadWrite.All', 'Device.ReadWrite.All', 'DeviceManagementApps.ReadWrite.All', 'DeviceManagementConfiguration.ReadWrite.All', 'DeviceManagementManagedDevices.ReadWrite.All', 'DeviceManagementServiceConfig.ReadWrite.All', 'Directory.Read.All', 'Group.ReadWrite.All', 'Organization.ReadWrite.All', 'Policy.ReadWrite.MobilityManagement', 'User.ReadWrite.All' ) try { Write-Host "`t`tscopes: $($scopes -join "`n`t ")" Write-Host "`t`tState : " -NoNewline Connect-MgGraph -Scopes $scopes -NoWelcome -ErrorAction Stop Write-Host "Connected" -f Green $tenantId = (Get-MgContext).tenantId } catch { Write-Host "failed" -f Red Write-Error $_ } #endregion #region: Overview Write-Host "Overview" -f Cyan Write-Host "`tScript : $PSCommandPath" #$($myInvocation.InvocationName)" Write-Host "`tTenant Name : $tenantDnsName" Write-Host "`tDemo User : $userUpn [Pass: $userPassPlain]" Write-Host "`tPolicy name : $dppName" Write-Host "`tUser group : $userGroupName" Write-Host "`tDevice group : $deviceGroupName" Write-Host "`tLocal Folder : $demoFolderPath" Write-Host "`tCsv specified : $(!!$csvPath)" Write-Host "`tMgGraph : $(if (Get-MgContext) {'Connected'} else {'Not connected'})" #endregion ################################################## #region: [Local ] Folders and Files Write-Host "Folders and Files" -f Cyan Write-Host "`tCreate '$demoFolderPath' " -NoNewline try { $folder = New-Item -Path $basePath -Name $demoFolderName -ItemType Directory -Force -ErrorAction Stop Write-Host 'created' -f Green } catch { Write-Host 'failed' -f Red throw $_ } Write-Host "`tCreate demo CSV-file:" foreach ($idType in $IdTypes) { $corpIdPath = "$filePath$idType.csv" Write-Host "`t`t$corpIdPath " -NoNewline try { Get-Variable "corporateIdentifiers$IdType" -ValueOnly| Set-Content -Path $corpIdPath -Encoding UTF8 Write-Host 'created' -f Green } catch { Write-Host 'failed' -f Red throw $_ } } Write-Host "`tCreate demo Script:" foreach ($item in $arrScripts) { $itemPath = "$demoFolderPath\$($item.fileName)" try { Write-Host "`t`t$itemPath " -NoNewline $item.content | Set-Content -Path $itemPath -ErrorAction Stop Write-Host 'created' -f Green } catch { Write-Host 'failed' -f Red throw $_ } } #endregion #region: [Entra ] User Write-Host "Entra User account" -f Cyan write-Host "`tGet User: $userDisplayName " -NoNewline try { $uri = "https://graph.microsoft.com/beta/users?`$filter=displayName eq '$userDisplayName'" if ($user = (Invoke-MgGraphRequest -Method GET -Uri $uri -ErrorAction Stop).value) { Write-Host "found" -f Green if ($user.accountEnabled -eq $false) { Write-Host "`tAccount is disabled" -f Red break } } else { Write-Host 'not found' -f Red } } catch { Write-Host "failed" -f Red throw $_ } if ( -not $user) { $jsonBody = @" { "accountEnabled" : true, "givenName" : "$userGivenName", "surname" : "$userSurName", "displayName" : "$userDisplayName", "userPrincipalName": "$userUpn", "mailNickname" : "$($userDisplayName.replace(' ',''))", "passwordProfile" : { "forceChangePasswordNextSignIn": false, "password" : "$userPassPlain" }, "ageGroup" : "Adult", "department" : "Learning", "usageLocation" : "NL" } "@ Write-Host "`tCreate user: $userDisplayName " -NoNewline try { $uri = 'https://graph.microsoft.com/beta/users' $user = Invoke-MgGraphRequest -Method POST -Uri $uri -Body $jsonBody -ErrorAction Stop write-Host "[$($user.id)]`tsuccess" -f Green } catch { Write-Host "failed" -f Red throw $_ } } #endregion #region: [Entra ] Licenses Write-Host "Licenses" -f Cyan $requiredSubscriptions = 'EMSPREMIUM' Write-Host "`tGet subscribed products " -NoNewline $uri = "https://graph.microsoft.com/beta/subscribedSkus" try { $subscribedSku = (Invoke-MgGraphRequest -Method GET -Uri $uri -ErrorAction Stop).value Write-Host "found $($subscribedSku.count)" -f Green } catch { Write-Host 'failed' -f Red throw $_ } Write-Host "`tGet user licenses" Write-Host "`t`tUser: $userDisplayName " -NoNewline $uri = "https://graph.microsoft.com/beta/users/$($user.id)/licenseDetails" try { $userLicenses = (Invoke-MgGraphRequest -Method GET -Uri $uri -ErrorAction Stop).value Write-Host "found $($userLicenses.count)" -f Green } catch { Write-Host 'failed' -f Red throw $_ } foreach ($product in $requiredSubscriptions) { Write-Host "`t`tSku : $product " -NoNewline if ($product -in $userLicenses.skuPartNumber) { Write-Host 'licensed' -f Green continue } Write-Host 'missing license' -f Red Write-Host "`t`tLicenses available: "-NoNewline $sku = $subscribedSku | Where SkuPartNumber -eq $product if ( $sku) { $unitsAvailable = ($sku.prepaidUnits.enabled) - ($sku.consumedUnits) Write-Host $unitsAvailable if ($unitsAvailable -eq 0) { throw "No license available for product: $product" } } else { Write-Host "`t`tProduct not found" -f Red throw "No subscription found for product: $product" } Write-Host "`tAssign license " -NoNewline $jsonBody = @" { "addLicenses": [ { "disabledPlans": [], "skuId" : "$($sku.skuId)" } ], "removeLicenses": [] } "@ try { $uri = "https://graph.microsoft.com/beta/users/$($user.id)/assignLicense" $userLicense = (Invoke-MgGraphRequest -Method POST -Uri $uri -Body $jsonBody -ContentType 'application/json' -ErrorAction Stop).value Write-Host "success" -f Green } catch { Write-Host "failed" -f Red throw $_ } } # foreach product #endregion #region: [Entra ] Service Principal Write-Host "Service Principal" -f Cyan write-Host "`tGet ServicePrincipal" Write-Host "`t`tName : $deviceGroupOwnerName" Write-Host "`t`tAppid : $deviceGroupOwnerAppId " -NoNewline try { Connect-MgGraph -Scopes 'Directory.Read.All' -NoWelcome $uri = "https://graph.microsoft.com/beta/servicePrincipals?`$filter=appId eq '$deviceGroupOwnerAppId'" $deviceGroupOwner = (Invoke-MgGraphRequest -Method GET -Uri $uri -ErrorAction Stop).value if ($deviceGroupOwner.count -gt 0) { Write-Host "found" -f Green Write-Host "`t`tEnabled: " -NoNewline if ($deviceGroupOwner.accountEnabled) { Write-Host "true" -f Green } else { Write-Host "false" -f Red } } else { Write-Host 'not found' -f Red } } catch { Write-Host "failed" -f Red throw $_ } if ($deviceGroupOwner.count -eq 0) { Write-Host "`tRegister required Service Principal" Write-Host "`t`tName : $deviceGroupOwnerName" Write-Host "`t`tAppId: $deviceGroupOwnerAppId" -NoNewline $jsonBody = @" { "appid": "$deviceGroupOwnerAppId", "accountEnabled": "true" } "@ try { $uri = "https://graph.microsoft.com/beta/servicePrincipals/" $null = (Invoke-MgGraphRequest -Method POST -Uri $uri -Body $jsonBody -ErrorAction Stop) Write-Host "success" -f Green } catch { Write-Host "failed" -f Red throw $_ } } elseIf (-not $deviceGroupOwner.accountEnabled) { Write-Host "`tEnable User logon for required Service Principal" Write-Host "`t`tName : $($deviceGroupOwner.displayName)" Write-Host "`t`tAppId: $($deviceGroupOwner.appId)" $jsonBody = @" { "appid": "$deviceGroupOwnerAppId", "accountEnabled": "true" } "@ try { $uri = "https://graph.microsoft.com/beta/servicePrincipals/$($deviceGroupOwner.Id)" $null = (Invoke-MgGraphRequest -Method PATCH -Uri $uri -Body $jsonBody -ErrorAction Stop) Write-Host "success" -f Green } catch { Write-Host "failed" -f Red throw $_ } } #endregion #region: [Entra ] Device Group Write-Host "Entra Device group" -f Cyan write-Host "`tGet group: $deviceGroupName " -NoNewline try { $uri = "https://graph.microsoft.com/beta/groups?`$filter=displayName eq '$deviceGroupName'" [array]$entraGroups = (Invoke-MgGraphRequest -Method GET -Uri $uri -ErrorAction Stop).value Write-Host "found $($entraGroups.count)" -f Green } catch { Write-Host "failed" -f Red throw $_ } foreach ($group in $entraGroups) { write-Host "`tRemove group: $($group.displayName) [$($group.id)] " -NoNewline try { $uri = "https://graph.microsoft.com/beta/groups/$($group.id)" $return = Invoke-MgGraphRequest -Method DELETE -Uri $uri -ErrorAction Stop Write-Host "removed" -f Green } catch { Write-Host "failed" -f Red throw $_ } } Write-Host "`tCreate group: $deviceGroupName " -NoNewline try { $jsonBody = @" { "DisplayName" : "$deviceGroupName", "MailEnabled" : false, "MailNickName" : "$($deviceGroupName.Replace(' ',''))", "SecurityEnabled": true } "@ #| ConvertFrom-Json $uri = 'https://graph.microsoft.com/beta/groups' $deviceGroup = Invoke-MgGraphRequest -Method POST -Uri $uri -Body $jsonBody -ErrorAction Stop write-Host "[$($deviceGroup.id)] " -NoNewline Write-Host "created" -f Green } catch { Write-Host "failed" -f Red throw $_ } # Add Owner $jsonBody = @" { "requests": [ { "id": "owner_$($deviceGroupOwner.id)", "method": "POST", "url": "/groups/$($devicegroup.Id)/owners/`$ref", "headers": { "Content-Type": "application/json" }, "body": { "@odata.id": "https://graph.microsoft.com/beta/directoryObjects/$($deviceGroupOwner.id)" } } ] } "@ write-Host "`tAdd Owner : $deviceGroupOwnerName [$($deviceGroupOwner.id)] " -NoNewline try { $uri = "https://graph.microsoft.com/beta/`$batch" $null = Invoke-MgGraphRequest -Method POST -Uri $uri -Body $jsonBody -ErrorAction Stop Write-Host "success" -f Green } catch { Write-Host "failed" -f Red throw $_ } #endregion #region: [Entra ] Users Group Write-Host "Entra Users group" -f Cyan write-Host "`tGet group: $userGroupName " -NoNewline try { $uri = "https://graph.microsoft.com/beta/groups?`$filter=displayName eq '$userGroupName'" [array]$entraGroups = (Invoke-MgGraphRequest -Method GET -Uri $uri -ErrorAction Stop).value Write-Host "found $($entraGroups.count)" -f Green } catch { Write-Host "failed" -f Red throw $_ } foreach ($group in $entraGroups) { write-Host "`tRemove group: $($group.displayName) [$($group.id)] " -NoNewline try { $uri = "https://graph.microsoft.com/beta/groups/$($group.id)" $return = Invoke-MgGraphRequest -Method DELETE -Uri $uri -ErrorAction Stop Write-Host "removed" -f Green } catch { Write-Host "failed" -f Red throw $_ } } Write-Host "`tCreate group: $userGroupName " -NoNewline try { $jsonBody = @" { "DisplayName" : "$userGroupName", "MailEnabled" : false, "MailNickName" : "$($userGroupName.Replace(' ',''))", "GroupTypes" : [ "DynamicMembership" ], "MembershipRule" : "$($userGroupMembershipRule.Replace('"','\"'))", "MembershipRuleProcessingState": "On", "SecurityEnabled": true } "@ #| ConvertFrom-Json $uri = 'https://graph.microsoft.com/beta/groups' $userGroup = Invoke-MgGraphRequest -Method POST -Uri $uri -Body $jsonBody -ErrorAction Stop write-Host "[$($userGroup.id)] " -NoNewline write-host "created" -f Green } catch { Write-Host "failed" -f Red throw $_ } #endregion #region: [Entra ] MDM auto enrollment Write-Host "Entra ID Automatic MDM enrollment" -f Cyan $addGroupName = $userGroupName write-Host "`tGroup: $addGroupName " -NoNewline try { $uri = "https://graph.microsoft.com/beta/groups?`$filter=displayName eq '$addGroupName'" [array]$arrGroups = (Invoke-MgGraphRequest -Method GET -Uri $uri -ErrorAction Stop).value if ($arrGroups.count -eq 0) { throw "Cannot find group: $addGroupName" } if ($arrGroups.count -gt 1) { throw "Multiple groups found with name: $addGroupName" } $objGroup = $arrGroups Write-Host "found" -f Green } catch { Write-Host "failed" -f Red throw $_ } # Policy.ReadWrite.MobilityManagement Write-Host "`tCurrent MDM policy`t" -NoNewline try { $uri = 'https://graph.microsoft.com/beta/policies/mobileDeviceManagementPolicies/0000000a-0000-0000-c000-000000000000?$expand=includedGroups' $policy = Invoke-MgGraphRequest -Method GET -Uri $uri -ErrorAction Stop } catch { Write-Host 'failed' -f Red throw $_ } $mdmAppliesTo = $policy.appliesTo Write-Host $mdmAppliesTo -f Green foreach ($group in $policy.includedGroups) { Write-Host "`t`tGroup: " -NoNewline if ($group.id -eq $objGroup.Id) { Write-Host "$($group.displayName) " -NoNewline Write-Host "[$($group.id)]" -f Green } else { Write-Host "[$($group.id)] $($group.displayName)" } } if ( ($mdmAppliesTo -ne 'all') -and ($objGroup.Id -notin $policy.includedGroups.id) ) { Write-Host "`tUpdate current MDM policy" Write-Host "`t`tScope: Selected" Write-Host "`t`tGroup: [$($objGroup.id)] $($objgroup.displayName) " -NoNewline $jsonBody = @" { "requests": [ { "id": "1", "method": "POST", "url": "/policies/mobileDeviceManagementPolicies/0000000a-0000-0000-c000-000000000000/includedGroups/`$ref", "body": { "@odata.id": "https://graph.microsoft.com/odata/groups('$($objGroup.id)')" }, "headers": { "x-ms-command-name": "MDMApplications - AddMdmGroup", "Content-Type": "application/json" } } ] } "@ $retry = 0 do { try { $uri = 'https://graph.microsoft.com/beta/policies/mobileDeviceManagementPolicies/0000000a-0000-0000-c000-000000000000/includedGroups/$ref' $uri = 'https://graph.microsoft.com/beta/$batch' $policy = Invoke-MgGraphRequest -Method POST -Uri $uri -Body $jsonBody -ErrorAction Stop if ($policy.responses.status -ne 400) { $retry++ if ($retry -gt 10) { throw "Group not found: $addGroupName" } Write-Host '.' -NoNewline sleep 5 } } catch { Write-Host 'failed' -f Red throw $_ } } Until ($policy.responses.status -eq 400) Write-Host 'added' -f Green } #endregion #region: [Intune] Applications # Get added Apps Write-Host "Applications" -f Cyan Write-Host "`tGet Intune Apps:" Write-Host "`t`t$appName " -NoNewline try { $uri = "https://graph.microsoft.com/beta/deviceAppManagement/mobileApps?`$filter=(microsoft.graph.managedApp/appAvailability eq null or microsoft.graph.managedApp/appAvailability eq 'lineOfBusiness' or isAssigned eq true)&`$orderby=displayName" $intuneApp = (Invoke-MgGraphRequest -Method GET -Uri $uri -ErrorAction Stop -OutputType PSObject).value | where displayName -eq $appName Write-Host "found $($intuneApp.count)" -f Green } catch { Write-Host 'failed' -f Red throw $_ } # Add App if ( $intuneApp.count -eq 0) { $jsonBody = @" { "@odata.type": "#microsoft.graph.officeSuiteApp", "description": "Microsoft 365 Apps for Windows 10 and later", "developer": "Microsoft", "displayName": "Microsoft 365 Apps for Windows 10 and later", "informationUrl": "https://products.office.com/explore-office-for-home", "isFeatured": true, "roleScopeTagIds": [], "publisher": "Microsoft", "largeIcon": { "type": "image/png", "value": "iVBORw0KGgoAAAANSUhEUgAAAF0AAAAeCAMAAAEOZNKlAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAJhUExURf////7z7/i9qfF1S/KCW/i+qv3q5P/9/PrQwfOMae1RG+s8AOxGDfBtQPWhhPvUx/759/zg1vWgg+9fLu5WIvKFX/rSxP728/nCr/FyR+tBBvOMaO1UH+1RHOs+AvSScP3u6f/+/v3s5vzg1+xFDO9kNPOOa/i7pvzj2/vWyes9Af76+Pzh2PrTxf/6+f7y7vOGYexHDv3t5+1SHfi8qPOIZPvb0O1NFuxDCe9hMPSVdPnFs/3q4/vaz/STcu5VIe5YJPWcfv718v/9/e1MFfF4T/F4TvF2TP3o4exECvF0SexIEPONavzn3/vZze1QGvF3Te5dK+5cKvrPwPrQwvKAWe1OGPexmexKEveulfezm/BxRfamiuxLE/apj/zf1e5YJfSXd/OHYv3r5feznPakiPze1P7x7f739f3w6+xJEfnEsvWdf/Wfge1LFPe1nu9iMvnDsfBqPOs/BPOIY/WZevJ/V/zl3fnIt/vTxuxHD+xEC+9mN+5ZJv749vBpO/KBWvBwRP/8+/SUc/etlPjArP/7+vOLZ/F7UvWae/708e1OF/aihvSWdvi8p+tABfSZefvVyPWihfSVde9lNvami+9jM/zi2fKEXvBuQvOKZvalifF5UPJ/WPSPbe9eLfrKuvvd0uxBB/7w7Pzj2vrRw/rOv+1PGfi/q/eymu5bKf3n4PnJuPBrPf3t6PWfgvWegOxCCO9nOO9oOfaskvSYePi5pPi2oPnGtO5eLPevlvKDXfrNvv739Pzd0/708O9gL+9lNfJ9VfrLu/OPbPnDsPBrPus+A/nArfarkQAAAGr5HKgAAADLdFJOU/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////8AvuakogAAAAlwSFlzAAAOwwAADsMBx2+oZAAAAz5JREFUOE+tVTtu4zAQHQjppmWzwIJbEVCzpTpjbxD3grQHSOXKRXgCAT6EC7UBVAmp3KwBnmvfzNCyZTmxgeTZJsXx43B+HBHRE34ZkXgkerXFTheeiCkRrbB4UXmp4wSWz5raaQEMTM5TZwuiXoaKgV+6FsmkZQcSy0kA71yMTMGHanX+AzMMGLAQCxU1F/ZwjULPugazl82GM0NEKm/U8EqFwEkO3/EAT4grgl0nucwlk9pcpTTJ4VPA4g/Rb3yIRhhp507e9nTQmZ1OS5RO4sS7nIRPEeHXCHdkw9ZEW2yVE5oIS7peD58Avs7CN+PVCmHh21oOqBdjDzIs+FldPJ74TFESUSJEfVzy9U/dhu+AuOT6eBp6gGKyXEx8euO450ZE4CMfstMFT44broWw/itkYErWXRx+fFArt9Ca9os78TFed0LVIUsmIHrwbwaw3BEOnOk94qVpQ6Ka2HjxewJnfyd6jUtGDQLdWlzmYNYLeKbbGOucJsNabCq1Yub0o92rtR+i30V2dapxYVEePXcOjeCKPnYyit7BtKeNlZqHbr+gt7i+AChWA9RsRs03pxTQc67ouWpxyESvjK5Vs3DVSy3IpkxPm5X+wZoBi+MFHWW69/w8FRhc7VBe6HAhMB2b8Q0XqDzTNZtXUMnKMjwKVaCrB/CSUL7WSx/HsdJC86lFGXwnioTeOMPjV+szlFvrZLA5VMVK4y+41l4e1xfx7Z88o4hkilRUH/qKqwNVlgDgpvYCpH3XwAy5eMCRnezIUxffVXoDql2rTHFDO+pjWnTWzAfrYXn6BFECblUpWGrvPZvBipETjS5ydM7tdXpH41ZCEbBNy/+wFZu71QO2t9pgT+iZEf657Q1vpN94PQNDxUHeKR103LV9nPVOtDikcNKO+2naCw7yKBhOe9Hm79pe8C4/CfC2wDjXnqC94kEeBU3WwN7dt/2UScXas7zDl5GpkY+M8WKv2J7fd4Ib2rGTk+jsC2cleEM7jI9veF7B0MBJrsZqfKd/81q9pR2NZfwJK2JzsmIT1Ns8jUH0UusQBpU8d2JzsHiXg1zXGLqxfitUNTDT/nUUeqDBp2HZVr+Ocqi/Ty3Rf4Jn82xxfSNtAAAAAElFTkSuQmCC" }, "notes": "", "owner": "Microsoft", "privacyInformationUrl": "https://privacy.microsoft.com/privacystatement", "autoAcceptEula": true, "excludedApps": { "access": true, "oneNote": true, "powerPoint": true, "publisher": true, "lync": true, "teams": true, "word": true, "infoPath": true, "sharePointDesigner": true, "groove": true }, "officePlatformArchitecture": "x64", "localesToInstall": [], "productIds": [ "o365ProPlusRetail" ], "shouldUninstallOlderVersionsOfOffice": true, "targetVersion": "", "updateChannel": "deferred", "updateVersion": "", "useSharedComputerActivation": false, "officeSuiteAppDefaultFileFormat": "OfficeOpenDocumentFormat" } "@ Write-Host "`tAdd app to Intune:" Write-Host "`t`t$appName " -NoNewline try { $uri = "https://graph.microsoft.com/beta/deviceAppManagement/mobileApps/" $intuneApp = Invoke-MgGraphRequest -Method POST -Uri $uri -Body $jsonBody -ErrorAction Stop Write-Host "success" -f Green } catch { Write-Host 'failed' -f Red throw $_ } } $appIdOffice = $intuneApp.id $assignGroupName = $deviceGroupName # Assignments Write-Host "`tAssign Group to App" Write-Host "`t`tApp : $appIdOffice" write-Host "`t`tGroup: $assignGroupName " -NoNewline try { $uri = "https://graph.microsoft.com/beta/groups?`$filter=displayName eq '$assignGroupName'" $entraGroup = (Invoke-MgGraphRequest -Method GET -Uri $uri -ErrorAction Stop).value if ($entraGroup.count -eq 0) { throw "Group not found: $assignGroupName" } Write-Host "found" -f Green $entraGroupId = $entraGroup.id } catch { Write-Host "failed" -f Red throw $_ } $jsonBody = @" { "mobileAppAssignments": [ { "@odata.type": "#microsoft.graph.mobileAppAssignment", "target": { "@odata.type": "#microsoft.graph.groupAssignmentTarget", "groupId": "$entraGroupId" }, "intent": "Required", "settings": null } ] } "@ Write-Host "`t`tAssigning group " -NoNewline try { $uri = "https://graph.microsoft.com/beta/deviceAppManagement/mobileApps/$appIdOffice/assign" $assignments = (Invoke-MgGraphRequest -Method POST -Uri $uri -Body $jsonBody -ErrorAction Stop).value Write-Host "success" -f Green } catch { Write-Host "failed" -f Red throw $_ } #endregion #region: [Intune] PowerShell scripts Write-Host "PowerShell scripts" -f Cyan foreach ($item in $arrScripts) { $scriptPath = "$demoFolderPath\$($item.fileName)" $scriptFileName = $item.FileName $scriptName = $item.Name $scriptDescr = $item.Description $scriptContentBase64 = ConvertToBase64 -Path $scriptPath -ErrorAction Stop $scriptRunAs = $item.Scope $jsonBody = @" { "displayName" : "$scriptName", "description" : "$scriptDescr", "scriptContent" : "$scriptContentBase64", "runAsAccount" : "$scriptRunAs", "fileName" : "$scriptFileName", "roleScopeTagIds" : [ "0" ], "enforceSignatureCheck": false, "runAs32Bit" : false } "@ Write-Host "`tGet uploaded script(s): $scriptName " -NoNewline try { $uri = "https://graph.microsoft.com/beta/deviceManagement/deviceManagementScripts?`$filter=displayName eq '$scriptName'" $response = Invoke-MgGraphRequest -Method Get -Uri $uri -ErrorAction Stop Write-Host "found $($response.value.Count)" -f Green } catch { Write-Host 'failed' -f Red throw $_ } foreach ($script in $response.value) { Write-Host "`tRemove: $($script.displayName) [$($script.id)] " -NoNewline try { $uriDelete = "https://graph.microsoft.com/beta/deviceManagement/deviceManagementScripts/$($script.id)" $response = Invoke-MgGraphRequest -Method DELETE -Uri $uriDelete -ErrorAction Stop Write-Host "removed" -f Green } catch { Write-Host 'failed' -f Red throw $_ } } Write-Host "`tUpload: $scriptName " -NoNewline try { $uriPost = "https://graph.microsoft.com/beta/deviceManagement/deviceManagementScripts" $script = Invoke-MgGraphRequest -Method POST -Uri $uriPost -Body $jsonBody -ErrorAction Stop Write-Host "[$($script.id)] " -NoNewline Write-Host "success" -f Green } catch { Write-Host 'failed' -f Red throw $_ } # Assign to User group write-Host "`tAssign to group" $jsonAssignments = "" foreach ($groupName in $item.assignments) { Write-Host "`t`tName : $groupName " -NoNewline try { $uri = "https://graph.microsoft.com/beta/groups?`$filter=displayName eq '$groupName'" [array]$group = (Invoke-MgGraphRequest -Method GET -Uri $uri -ErrorAction Stop).value if ($group.count -eq 0) { throw "Group not found: $groupName" } Write-Host "[$($group[0].id)]" -f Green $jsonAssignments += @" { "target": { "@odata.type": "#microsoft.graph.groupAssignmentTarget", "groupId": "$($group.id)" } }, "@ } catch { Write-Host "failed" -f Red throw $_ } } # foreach group $jsonAssignments = $jsonAssignments.TrimEnd(',') $jsonBody = @" { "deviceManagementScriptAssignments": [ $jsonAssignments ] } "@ Write-Host "`t`tAssigning " -NoNewline try { $uriPost = "https://graph.microsoft.com/beta/deviceManagement/deviceManagementScripts/$($script.id)/assign" $assignment = Invoke-MgGraphRequest -Method POST -Uri $uriPost -Body $jsonBody -ErrorAction Stop Write-Host "success" -f Green } catch { Write-Host 'failed' -f Red throw $_ } } # foreach script #endregion #region: [Intune] Device preparation policies Write-Host "Device preparation policies" -f Cyan Write-Host "`tGet policy: $dppName " -NoNewline try { $uriGet = "https://graph.microsoft.com/beta/deviceManagement/configurationPolicies?`$filter=Name eq '$dppName'" $response = Invoke-MgGraphRequest -Method GET -Uri $uriGet -ErrorAction Stop Write-Host "found $($response.value.count)" -f Green } catch { Write-Host 'failed' -f Red throw $_ } # Remove existing policies foreach ($dpp in $response.value) { $dppPolicy = $dpp $dppName = $dpp.name $dppId = $dpp.id Write-Host "`tRemove policy: $dppName [$dppId] " -NoNewline try { $uriDelete = "https://graph.microsoft.com/beta/deviceManagement/configurationPolicies/$dppId" $response = Invoke-MgGraphRequest -Method DELETE -Uri $uriDelete -ErrorAction Stop Write-Host 'removed' -f Green } catch { Write-Host 'failed' -f Red throw $_ } } # Create new policy $arrayApps = @() $arrayApps += @{id = "$appIdOffice" ; type = "#microsoft.graph.officeSuiteApp" } $dppDeploymentMode = 'enrollment_autopilot_dpp_deploymentmode_0' # Deployment mode: User-driven (0) $dppDeploymentType = 'enrollment_autopilot_dpp_deploymenttype_0' # Deployment type: Single user (0) $dppJoinType = 'enrollment_autopilot_dpp_jointype_0' # Join type: Entra joined (0) $dppAccountType = 'enrollment_autopilot_dpp_accountype_0' # User Account type: Administrator (0), User (1) $dppTimeout = 90 # Minutes allowed before showing installation error: Default (60) $dppErrorMessage = 'Contact your organization support person for help' # Custom error message $dppAllowSkipSetup = 'enrollment_autopilot_dpp_allowskip_1' # Allow users to skip setup after multiple attempts: No (0), Yes (1) $dppAllowDiagnostics = 'enrollment_autopilot_dpp_allowdiagnostics_1' # Show link to diagnostics: No (0), Yes (1) # Apps $dppAllowedAppIds = @" [ "@ foreach ( $app in $arrayApps) { $appId = $app.id $appType = $app.type $dppAllowedAppIds += @" { "@odata.type": "#microsoft.graph.deviceManagementConfigurationStringSettingValue", "value": "{\"id\":\"$appId\",\"type\":\"$appType\"}" }, "@ } # foreach $dppAllowedAppIds = $dppAllowedAppIds.TrimEnd(',') $dppAllowedAppIds += @" ] "@ # Scripts Write-Host "`tGet scripts:" $dppAllowedScriptIds = @" [ "@ foreach ($script in $arrScripts) { $scriptName = $script.Name Write-Host "`t`tName: $scriptName " -NoNewline try { $uri = "https://graph.microsoft.com/beta/deviceManagement/deviceManagementScripts?`$filter=displayName eq '$scriptName'" $response = (Invoke-MgGraphRequest -Method Get -Uri $uri -ErrorAction Stop).value if ($response.count -eq 0) { Write-Host "not found" -f Red Continue } Write-Host "[$($response.id)]" -f Green $dppAllowedScriptIds += @" { "@odata.type": "#microsoft.graph.deviceManagementConfigurationStringSettingValue", "value": "$($response.id)" }, "@ } catch { Write-Host 'failed' -f Red throw $_ } } # foreach script $dppAllowedScriptIds = $dppAllowedScriptIds.TrimEnd(',') $dppAllowedScriptIds += @" ] "@ Write-Host "`tCreate policy: $dppName " -NoNewline $jsonBody = @" { "name": "$dppName", "description": "$dppDescription", "settings": [ { "@odata.type": "#microsoft.graph.deviceManagementConfigurationSetting", "settingInstance": { "@odata.type": "#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance", "choiceSettingValue": { "@odata.type": "#microsoft.graph.deviceManagementConfigurationChoiceSettingValue", "children": [], "settingValueTemplateReference": { "settingValueTemplateId": "5874c2f6-bcf1-463b-a9eb-bee64e2f2d82" }, "value": "$dppDeploymentMode" }, "settingDefinitionId": "enrollment_autopilot_dpp_deploymentmode", "settingInstanceTemplateReference": { "settingInstanceTemplateId": "5180aeab-886e-4589-97d4-40855c646315" } } }, { "@odata.type": "#microsoft.graph.deviceManagementConfigurationSetting", "settingInstance": { "@odata.type": "#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance", "choiceSettingValue": { "@odata.type": "#microsoft.graph.deviceManagementConfigurationChoiceSettingValue", "children": [], "settingValueTemplateReference": { "settingValueTemplateId": "e0af022f-37f3-4a40-916d-1ab7281c88d9" }, "value": "$dppDeploymentType" }, "settingDefinitionId": "enrollment_autopilot_dpp_deploymenttype", "settingInstanceTemplateReference": { "settingInstanceTemplateId": "f4184296-fa9f-4b67-8b12-1723b3f8456b" } } }, { "@odata.type": "#microsoft.graph.deviceManagementConfigurationSetting", "settingInstance": { "@odata.type": "#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance", "choiceSettingValue": { "@odata.type": "#microsoft.graph.deviceManagementConfigurationChoiceSettingValue", "children": [], "settingValueTemplateReference": { "settingValueTemplateId": "1fa84eb3-fcfa-4ed6-9687-0f3d486402c4" }, "value": "$dppJoinType" }, "settingDefinitionId": "enrollment_autopilot_dpp_jointype", "settingInstanceTemplateReference": { "settingInstanceTemplateId": "6310e95d-6cfa-4d2f-aae0-1e7af12e2182" } } }, { "@odata.type": "#microsoft.graph.deviceManagementConfigurationSetting", "settingInstance": { "@odata.type": "#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance", "choiceSettingValue": { "@odata.type": "#microsoft.graph.deviceManagementConfigurationChoiceSettingValue", "children": [], "settingValueTemplateReference": { "settingValueTemplateId": "bf13bb47-69ef-4e06-97c1-50c2859a49c2" }, "value": "$dppAccountType" }, "settingDefinitionId": "enrollment_autopilot_dpp_accountype", "settingInstanceTemplateReference": { "settingInstanceTemplateId": "d4f2a840-86d5-4162-9a08-fa8cc608b94e" } } }, { "@odata.type": "#microsoft.graph.deviceManagementConfigurationSetting", "settingInstance": { "@odata.type": "#microsoft.graph.deviceManagementConfigurationSimpleSettingInstance", "settingDefinitionId": "enrollment_autopilot_dpp_timeout", "settingInstanceTemplateReference": { "settingInstanceTemplateId": "6dec0657-dfb8-4906-a7ee-3ac6ee1edecb" }, "simpleSettingValue": { "@odata.type": "#microsoft.graph.deviceManagementConfigurationIntegerSettingValue", "settingValueTemplateReference": { "settingValueTemplateId": "0bbcce5b-a55a-4e05-821a-94bf576d6cc8" }, "value": $dppTimeout } } }, { "@odata.type": "#microsoft.graph.deviceManagementConfigurationSetting", "settingInstance": { "@odata.type": "#microsoft.graph.deviceManagementConfigurationSimpleSettingInstance", "settingDefinitionId": "enrollment_autopilot_dpp_customerrormessage", "settingInstanceTemplateReference": { "settingInstanceTemplateId": "2ddf0619-2b7a-46de-b29b-c6191e9dda6e" }, "simpleSettingValue": { "@odata.type": "#microsoft.graph.deviceManagementConfigurationStringSettingValue", "settingValueTemplateReference": { "settingValueTemplateId": "fe5002d5-fbe9-4920-9e2d-26bfc4b4cc97" }, "value": "$dppErrorMessage" } } }, { "@odata.type": "#microsoft.graph.deviceManagementConfigurationSetting", "settingInstance": { "@odata.type": "#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance", "choiceSettingValue": { "@odata.type": "#microsoft.graph.deviceManagementConfigurationChoiceSettingValue", "children": [], "settingValueTemplateReference": { "settingValueTemplateId": "a2323e5e-ac56-4517-8847-b0a6fdb467e7" }, "value": "$dppAllowSkipSetup" }, "settingDefinitionId": "enrollment_autopilot_dpp_allowskip", "settingInstanceTemplateReference": { "settingInstanceTemplateId": "2a71dc89-0f17-4ba9-bb27-af2521d34710" } } }, { "@odata.type": "#microsoft.graph.deviceManagementConfigurationSetting", "settingInstance": { "@odata.type": "#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance", "choiceSettingValue": { "@odata.type": "#microsoft.graph.deviceManagementConfigurationChoiceSettingValue", "children": [], "settingValueTemplateReference": { "settingValueTemplateId": "c59d26fd-3460-4b26-b47a-f7e202e7d5a3" }, "value": "$dppAllowDiagnostics" }, "settingDefinitionId": "enrollment_autopilot_dpp_allowdiagnostics", "settingInstanceTemplateReference": { "settingInstanceTemplateId": "e2b7a81b-f243-4abd-bce3-c1856345f405" } } }, { "@odata.type": "#microsoft.graph.deviceManagementConfigurationSetting", "settingInstance": { "@odata.type": "#microsoft.graph.deviceManagementConfigurationSimpleSettingCollectionInstance", "settingDefinitionId": "enrollment_autopilot_dpp_allowedappids", "settingInstanceTemplateReference": { "settingInstanceTemplateId": "70d22a8a-a03c-4f62-b8df-dded3e327639" }, "simpleSettingCollectionValue": $dppAllowedAppIds } }, { "@odata.type": "#microsoft.graph.deviceManagementConfigurationSetting", "settingInstance": { "@odata.type": "#microsoft.graph.deviceManagementConfigurationSimpleSettingCollectionInstance", "settingDefinitionId": "enrollment_autopilot_dpp_allowedscriptids", "settingInstanceTemplateReference": { "settingInstanceTemplateId": "1bc67702-800c-4271-8fd9-609351cc19cf" }, "simpleSettingCollectionValue": $dppAllowedScriptIds } } ], "roleScopeTagIds": [ "0" ], "platforms": "windows10", "technologies": "enrollment", "templateReference": { "templateId": "80d33118-b7b4-40d8-b15f-81be745e053f_1" } } "@ try { $uri = "https://graph.microsoft.com/beta/deviceManagement/configurationPolicies" $dpp = Invoke-MgGraphRequest -Method POST -Uri $uri -Body $jsonBody -ErrorAction Stop Write-Host "created" -f Green } catch { Write-Host 'failed' -f Red throw $_ } #endregion #region: [Intune] Add Devicegroup to Policy Write-Host "`tAdd Devicegroup to policy:" Write-Host "`t`tGroup : $deviceGroupName " -NoNewline $uri = "https://graph.microsoft.com/beta/groups?`$filter=displayName eq '$deviceGroupName'" try { $objGroup = (Invoke-MgGraphRequest -Method GET -Uri $uri -ErrorAction Stop).value if ($objGroup.count -eq 0) { throw "Group not found: $deviceGroupName" } Write-Host "[$($objGroup.id)]" -f Green $deviceGroupId = $objGroup.Id } catch { Write-Host 'failed' -f Red throw $_ } $jsonBody = @" { "enrollmentTimeDeviceMembershipTargets": [ { "targetType": "staticSecurityGroup", "targetId": "$deviceGroupId" } ] } "@ $uri = "https://graph.microsoft.com/beta/deviceManagement/configurationPolicies('$($dpp.id)')/setEnrollmentTimeDeviceMembershipTarget" $retry = 0 Write-Host "`t`tUpdate policy " -NoNewline Do { try { $response = (Invoke-MgGraphRequest -Method POST -Uri $uri -Body $jsonBody -ErrorAction Stop) if ($response.validationSucceeded -eq $false) { throw "Group not found: $deviceGroupName" } Write-Host "success" -f Green } catch { $retry++ if ($retry -le 5) { write-host '.' -NoNewline sleep 3 } else { Write-Host 'failed' -f Red throw $_ } } } Until ($response.validationSucceeded) #endregion #region: [Intune] Assign Usergroup to Policy Write-Host "`tAssign Usergroup to policy:" Write-Host "`t`tPolicy: $dppName [$($dpp.id)]" Write-Host "`t`tGroup : $userGroupName " -NoNewline $uri = "https://graph.microsoft.com/beta/groups?`$filter=displayName eq '$userGroupName'" try { $objGroup = (Invoke-MgGraphRequest -Method GET -Uri $uri -ErrorAction Stop).value if ($objGroup.count -eq 0) { throw "Group not found: $userGroupName" } Write-Host "[$($objGroup.id)]" -f Green $userGroupId = $objGroup.Id } catch { Write-Host 'failed' -f Red throw $_ } $target = @{ '@odata.type' ='#microsoft.graph.groupAssignmentTarget' "deviceAndAppManagementAssignmentFilterType" = "none" "groupId" = $userGroupId } Write-Host "`t`tAssigning " -NoNewline try { NewConfigurationPolicyAssignment -configurationPolicyId $dpp.id -target $target -ErrorAction Stop Write-Host "success" -f Green } catch { Write-Host 'failed' -f Red throw $_ } #endregion #region: [Intune] Import Corporate Identifiers Write-Host "Corporate Identifiers" -f Cyan foreach ($idType in $IdTypes) { $corpIdPath = "$filePath$idType.csv" Write-Host "`tImport file: $corpIdPath" try { $corporateIdentifiers = Get-Content $corpIdPath -ErrorAction Stop $importedDeviceIdentities = "" foreach ($identity in $corporateIdentifiers) { Write-Host "`t`t$identity " -NoNewline $arrId = $identity.split(',') Switch ($idType) { 'Windows' { Write-Host "valid" -f Green $importedDeviceIdentities += @" { "importedDeviceIdentityType": "manufacturerModelSerial", "importedDeviceIdentifier" : "$identity" }, "@ } 'Serial' { Write-Host "valid" -f Green $importedDeviceIdentities += @" { "importedDeviceIdentityType": "serialNumber", "importedDeviceIdentifier" : "$($arrId[0])", "description" : "$($arrId[1])" }, "@ } 'IMEI' { Write-Host "valid" -f Green $importedDeviceIdentities += @" { "importedDeviceIdentityType": "imei", "importedDeviceIdentifier" : "$($arrId[0])", "description" : "$($arrId[1])" }, "@ } default { # Unknown Write-Host "unknown type" -f Red } } # switch } # foreach $importedDeviceIdentities = $importedDeviceIdentities.TrimEnd(',') } catch { Write-Host 'failed' -f Red throw $_ } Write-Host "`t`tRegister device(s) " -NoNewline $jsonBody = @" { "overwriteImportedDeviceIdentities": false, "importedDeviceIdentities": [ $importedDeviceIdentities ] } "@ try { $uri = "https://graph.microsoft.com/beta/deviceManagement/importedDeviceIdentities/importDeviceIdentityList" $importedDevice = Invoke-MgGraphRequest -Method POST -Uri $uri -Body $jsonBody -ErrorAction Stop Write-Host "success" -f Green } catch { Write-Host "failed" -f Red throw $_ } } #endregion #region: Write-Host "Final processing" -f Cyan Write-Host "`tDynamic group: $($userGroupName)" Write-Host "`tProcessing membershiprule for: $userUpn " -NoNewline try { do { Write-Host '.' -NoNewline sleep 5 $uri = "https://graph.microsoft.com/beta/groups/$($userGroup.id)/members" [array]$arrayGroupMembers = (Invoke-MgGraphRequest -Method GET -Uri $uri -ErrorAction Stop).value } until ($userUpn -in $arrayGroupMembers.UserPrincipalName) Write-Host " success" -f Green } catch { Write-Host 'failed' -f Red throw $_ } #endregion Write-Host Write-Host ('='*25) " Script ready " ('='*25) if (-not $csvPath) { Write-Host "You can run this script with the CsvPath parameter to import your own Corporate Identifiers (optional)" Write-Host "To extract Corporate Identifiers (Manufacturer,Model,SerialNumber) from your Windows device using PowerShell:" Write-Host "`tSet-Content -Path CorpId.csv -Encoding UTF8 -Value (`"{0},{1},{2}`" -f" -f Yellow Write-Host "`t`t(Get-CimInstance -Class Win32_ComputerSystem).Manufacturer," -f Yellow Write-Host "`t`t(Get-CimInstance -Class Win32_ComputerSystem).Model," -f Yellow Write-Host "`t`t(Get-CimInstance -Class Win32_BIOS).SerialNumber" -f Yellow Write-Host "`t)" -f Yellow Write-Host "`tGet-CimInstance -Class Win32_BIOS | FT SerialNumber" -f Yellow } Write-Host "Make sure your device is running Windows 11 version 22H2/22H3 or later with KB5035942" Write-Host "Use these credentials for provisioning:" Write-Host "`tUsername: $userUpn" -f Cyan Write-Host "`tPassword: $userPassPlain" -f Cyan Write-Host |