Microsoft Intune is the leader in the Gartner Magic Quadrant for unified endpoint management (UEM) and is an excellent tool for managing your end user devices, especially in the modern hybrid workforce. This book is your comprehensive guide to getting you started with using and configuring Microsoft Intune with only a basic understanding of end user compute management and PowerShell (for automation and scripting).
Intune is a cloud management software service that can fully manage your entire end user computing estate wherever you are. This includes Windows, iOS, iPadOS, macOS, Android, and Linux for both corporate and personally owned devices, as well as cloud computing with Windows 365 and Azure Virtual Desktop.
You can secure corporate data on any device, and Intune follows the zero-trust security model. As well as compliance and policy management, Intune will also handle your application deployment across devices.
Before digging into the finer points of using the platform, first, we need to look at the prerequisites and have a general look at Entra ID (previously Azure AD; you may find references to both in documentation and blog posts). While Microsoft Intune is part of the Microsoft 365 suite, it relies on Entra ID for groups, users, conditional access policies, and more, so an understanding of how these work will make your life significantly easier. In this chapter, we will look at how we can leverage Microsoft Entra to set the foundations for a successful Intune deployment.
This chapter will include the following recipes:
For this chapter, you will need a modern web browser and a PowerShell code editor such as Visual Studio Code (VS Code) or the PowerShell ISE.
All of the scripts referenced in this chapter can be found here: https://github.com/PacktPublishing/Microsoft-Intune-Cookbook/tree/main/Chapter1.
Microsoft licensing can be tricky at the best of times, so we will start there.
To use Intune, you will need an Intune license, which comes in three flavors:
You can purchase your Intune licensing on a standalone plan or as part of the following Microsoft SKUs:
If you are purchasing Intune on a standalone plan, you will also need to purchase an Entra ID license as well as a Defender for Endpoint license (if required).
These licenses are all per-user; however, Intune device-based licensing is available for some niche use cases, such as multi-user kiosk machines or manufacturing facilities with non-user-assigned devices.
On top of the Intune licensing, there are some additional Windows-only features that require a Windows Enterprise license over the standard Professional one.
This license is included in the M365 E3/E5/F3/F5/A3/A5 SKUs or can be added as an additional license.
Adding Windows Enterprise adds the following features:
A very useful site for referencing licensing SKUs and what each contains is https://m365maps.com/.
Now that we have our licensing in place, we need to create a tenant. This recipe will run you through the steps to create your new Microsoft 365/Intune/Azure tenant.
A tenant can be used across the full Microsoft platform, so it will apply to Microsoft 365, Azure, and Intune. If you have Active Directory set up currently, you can synchronize your users/groups/devices into Entra ID to give your users a hybrid identity (you need to ensure they do not have a .local
suffix for this to succeed).
You can synchronize multiple Active Directory forests into a single Entra tenant, but you cannot synchronize one on-premises AD domain/forest into multiple Entra tenants.
A tenant can be configured with a custom domain name rather than the .onmicrosoft.com one, which is automatically configured when you create your new tenant. Within a tenant, you can have multiple Azure subscriptions but only one Intune configuration. There is also no built-in functionality to copy or migrate devices and settings between tenants using Intune.
If you would rather follow this book using a demo tenant, head over to the Microsoft 365 Developer Program, where you will be able to grab a free developer tenant with licenses to cover most aspects we will be covering here: https://developer.microsoft.com/en-us/microsoft-365/dev-program.
Important note
The licenses do not include Windows Enterprise, so you will not be able to test the chapters on Autopatch and Remediations.
To create your live tenant, first, you need to obtain your licenses. These can be purchased from any VAR or directly from Microsoft. If you are using a developer tenant, Steps 1 and 2 can be skipped:
Figure 1.1 – Microsoft licensing page
After clicking the Try free for 1 month button, enter an email address to use for the tenancy. If it does not exist, it will create it for you, so long as it is on a Microsoft domain (outlook.com, for example).
You will also be required to verify your identity, so make sure you enter a valid telephone number.
That is all we need to do within the Microsoft 365 admin center. Now, we must navigate to https://entra.microsoft.com and log in with the same account that was licensed when we set up the tenant.
Before moving on to the next recipe, from here on, we are going to include the PowerShell and JSON code (where possible) to complete the steps both in the GUI and from a command line.
Microsoft Graph is the technology that is used underneath most Microsoft products to handle all of the commands that are sent via the web interface. Fortunately, it includes a powerful API that we can use to automate these using PowerShell.
To use the command-line scripts, you will need to install the Microsoft Graph PowerShell module and connect to Graph (we are going to set up a connection with full access so that you can reuse the connection at all stages). For this, use your preferred code editor (VS Code is a good choice and is platform agnostic) or use the built-in PowerShell ISE on a Windows device:
Install-Module -Name Microsoft.Graph.Authentication -Scope CurrentUser -Repository PSGallery -Force
import-module microsoft.graph.authentication
Connect-MgGraph -Scopes RoleAssignmentSchedule.ReadWrite.Directory, Domain.Read.All, Domain.ReadWrite.All, Directory.Read.All, Policy.ReadWrite.ConditionalAccess, DeviceManagementApps.ReadWrite.All, DeviceManagementConfiguration.ReadWrite.All, DeviceManagementManagedDevices.ReadWrite.All, openid, profile, email, offline_access, Policy.ReadWrite.PermissionGrant,RoleManagement.ReadWrite.Directory, Policy.ReadWrite.DeviceConfiguration, DeviceLocalCredential.Read.All, DeviceManagementManagedDevices.PrivilegedOperations.All, DeviceManagementServiceConfig.ReadWrite.All, Policy.Read.All, DeviceManagementRBAC.ReadWrite.All
After pressing Enter, you will be prompted to log in with your new credentials and then approve the permissions for your tenant by checking the Consent on behalf of your organization box and then clicking Accept.
We now have a working tenant and a Microsoft Graph connection that we can use in the following recipes and chapters.
Now that our tenant has been set up, we can create our first user. This recipe will run through how to create your first user and then look at what is happening in the Graph API underneath.
Navigate to the Microsoft Entra portal at https://entra.microsoft.com/#home.
Here, you will find an overview of your tenant, including your tenant ID, which you will find yourself needing when setting up policies such as OneDrive within Intune. You cannot display it within Intune directly, so you will have to navigate back to Entra ID to find it.
Within Entra ID, click on Users, then All users; you will see the user you set up when enrolling the tenant. This user will have Global Administrator access across the whole tenant, so we will create a new user to test role assignment, license assignment, and group membership.
Follow these steps to create an additional non-admin user in your tenant. The new user screen runs across a few pages, so we will concentrate on cropped screenshots of the appropriate areas:
Figure 1.2 – Entra user details
Figure 1.3 – Entra user license details
With that, you have created your first account in your new tenant.
Now, we can learn how to automate user creation.
You will need the PowerShell ISE or VS Code running for this, as we will be setting variables to send to Microsoft Graph.
Follow these steps in a new PowerShell script to create your user with Microsoft Graph:
$displayname = "User One" $givenname = "User" $surname = "One" $usageLocation = "GB" $mailNickname = "user1" $password = "PASSWORD HERE" $domainname = "DOMAIN HERE"
$json = @" { "accountEnabled": true, "displayName": "$displayname", "givenName": "$givenname", "mailNickname": "$mailNickname", "passwordProfile": { "forceChangePasswordNextSignIn": true, "password": "$password" }, "surname": "$surname", "usageLocation": "$usageLocation", "userPrincipalName": "$mailnickname@$domainname" } "@
As you can see, the JSON is a fairly straightforward array. Watch the names of the items as they are case sensitive; as an example, accountEnabled
will fail if it is listed as AccountEnabled
or accountenabled
. The error will be a standard malformed request, so it is always a good idea to start here with any troubleshooting.
You can also see that passwordProfile
is a nested array as it has further child items.
$uri = "https://graph.microsoft.com/beta/users"
GET
: This simply retrieves values from Graph to manipulate, export, and morePOST
: This sends new values to Graph that do not currently exist (a new user, new policy, and so on)PATCH
: This updates an existing recordPUT
: This is similar to PATCH
but needs a full URL, including the ID being createdDELETE
: This deletes whatever you are pointing it atThis is a new account we are creating, and a PUT
request is more complex than a POST
request, so we will stick with POST
:
Invoke-MgGraphRequest -Method POST -Uri $uri -Body $json -ContentType "application/json"
This command sends a POST
request to the URL we specified earlier (in this case, users
) to pass the JSON we wrote. The content type tells it to look for JSON.
Now that we have our user, we can assign a role to it.
Before we proceed further, we need to understand what roles are within Entra ID. A role gives a user specific permissions to items within Entra ID/Microsoft 365/Intune. There are numerous built-in roles, and you can also create a custom role with specific permissions applied.
It is always worth working from the principle of the least required permissions. It is better to give an admin multiple roles with strict permissions rather than going for a global administrator with keys to the kingdom.
A list of the built-in roles can be found here: https://learn.microsoft.com/en-us/azure/active-directory/roles/permissions-reference.
As this is an Intune book, the two main roles we are interested in initially are Intune Administrator and Entra Joined Device Local Administrator. As its name suggests, Intune Administrator gives full access to everything within Intune.
Entra Joined Device Local Administrator gives users full administrative access over all Entra joined devices. While this is useful for support teams, if licensed, it is worth considering using privileged identity management (PIM), which you can use for role access for a limited amount of time with full reporting.
You can find out more about PIM here: https://learn.microsoft.com/en-us/azure/active-directory/privileged-identity-management/pim-configure
Intune also has specific role-based access control (RBAC) to restrict access within the Intune portal itself. We will cover this further in Chapter 13.
There are two ways to assign roles, so we will use one for each.
Follow these steps to assign a built-in role to your newly created user:
Figure 1.4 – Entra ID – Roles and administrators
Figure 1.5 – Entra ID – Roles and administrators | All roles
For this, we will use the in-built roles, but if you need something more granular, you can create a custom role based on the exact permissions you require.
Figure 1.6 – Assigned Intune Administrator role
Following these steps has granted your user administrative rights on your cloud-joined devices.
By automating the assignment of roles, we can add to our previous user creation to create an automated onboarding function for user management across job roles.
Adding roles via PowerShell is slightly more complex as we need to find the role ID to be able to assign it.
Create a new PowerShell script and follow these steps:
Install-Module Microsoft.Graph.DeviceManagement.Enrolment -Scope CurrentUser -Repository PSGallery -Force Import-Module Microsoft.Graph.DeviceManagement.Enrolment
$rolename = "Azure AD Joined Device Local Administrator" $user = "test@test.onmicrosoft.com"
PSObject
, and then retrieving the ID from it. This can be done with two commands, one for grabbing the user details and the second for grabbing the ID from the first variable, but wrapping the query in brackets does the same job and runs quicker:$userid = (Invoke-MgGraphRequest -Uri "https://graph.microsoft.com/beta/users/$user" -Method Get -OutputType PSObject).id
Note that we are passing OutputType
and using a GET
request with this first command. Setting OutputType
allows us to use the output within PowerShell.
where-object
to grab the role we are looking for, after which we can pass the output to a PowerShell object. We grab the roles from roleDefinitions
within the whole directory in Graph, in the roleManagement
subsection of the API:$uri = "https://graph.microsoft.com/beta/roleManagement/directory/roleDefinitions" $roletoassign = (((Invoke-MgGraphRequest -Uri $uri -Method Get -OutputType PSObject).value) | where-object DisplayName -eq $rolename).id
ScopeID
to "/"
to cover the entire directory:$params = @{ "@odata.type" = "#microsoft.graph.unifiedRoleAssignment" RoleDefinitionId = "$roletoassign" PrincipalId = "$userid" DirectoryScopeId = "/" } New-MgRoleManagementDirectoryRoleAssignment -BodyParameter $params
By completing these steps, we have created our script to automate role assignment in Microsoft Entra using the Graph API.
The first settings we need to look at are the Device settings. This is where we can configure what users can and cannot do with their devices. This includes setting who can enroll devices into Intune and Entra ID, as well as the security around it.
While the vast majority of our device settings will be configured within Intune, there are a few within Entra ID that are worth setting up before we move into the Intune configuration.
Following these steps will configure your Entra environment for device enrollment:
Regarding Multi-factor authentication, leave this set to No and use Conditional Access as recommended. This will give you much more granular control and reporting.
The maximum number of devices is something to note here. It is also a setting within Intune, so there are two places where you can check if users have issues enrolling devices. The Entra ID setting here is for all registered devices, so it will include any personally enrolled devices that are not Intune joined. It is also worth noting that this will include any previous devices as Entra ID does not automatically clean stale devices (although this can be scripted; see the following Automating it section).
Unless you have a large number of devices per user, leave this set to 50
devices per user.
You can ignore the blue text link, as we configured that with the Entra ID roles earlier.
The final setting here (Restrict non-admin users from recovering the BitLocker key(s) for their owned devices (preview)) lets your end users retrieve their own BitLocker keys (after authenticating). This is a personal preference; changing it to Yes would result in additional support calls in the event of a power cut or other events that could trigger BitLocker. For this example, we are leaving it set to No.
This recipe has allowed our tenant to accept Intune device enrollment.
Again, we can use PowerShell to automate this configuration to make it more easily repeatable:
$devicequota = 50 ##Set to 0 to block Entra ID Registration $azureadregister = 1 ##Set to 0 to block Entra ID Join $azureadjoin = 1 ##Set to 1 to require MFA $mfa = 0 ##Set to False to block BitLocker $bitlocker = "true"
While this is displaced on one screen in the GUI, these are two separate policies, so we need to create the JSON for the non-BitLocker settings. This JSON will include some nested arrays, as each section of the page is an array in itself.
GET
request against this URL: https://graph.microsoft.com/beta/policies/authorizationPolicy/authorizationPolicy
.$jsonsettings = @" { "@odata.context":"https://graph.microsoft.com/beta/$metadata#policies/deviceRegistrationPolicy/$entity", "multiFactorAuthConfiguration":"$mfa", "id":"deviceRegistrationPolicy", "displayName":"Device Registration Policy", "description":"Tenant-wide policy that manages intial provisioning controls using quota restrictions, additional authentication and authorization checks", "userDeviceQuota":$devicequota, "azureADRegistration":{ "appliesTo":"$azureadregister","allowedUsers":null, "allowedGroups":null,"isAdminConfigurable":false }, "azureADJoin":{ "appliesTo":"$azureadjoin","allowedUsers":[],"allowedGroups":[], "isAdminConfigurable":true } } "@
$jsonbitlocker = @" {"defaultUserRolePermissions": {"allowedToReadBitlockerKeysForOwnedDevice":$bitlocker}} "@
$registrationuri = "https://graph.microsoft.com/beta/policies/deviceRegistrationPolicy" $bitlockeruri = "https://graph.microsoft.com/beta/policies/authorizationPolicy/authorizationPolicy"
deviceRegistrationPolicy
, we need to send a PUT
request:Invoke-MgGraphRequest -Method PUT -Uri $registrationuri -Body $jsonsettings -ContentType "application/json"
PATCH
request as we are amending existing settings:Invoke-MgGraphRequest -Method PATCH -Uri $bitlockeruri -Body $jsonbitlocker -ContentType "application/json"
These steps have configured our tenant to allow enrollment and let users view their BitLocker keys.
As we mentioned earlier, clearing out stale devices requires a script, so we will run through that quickly as well:
Install-Module -Name Microsoft.Graph.Identity.DirectoryManagement -Repository PSGallery -Force -Scope CurrentUser import-module Microsoft.Graph.Identity.DirectoryManagement
$daystodisable = 90 $daystoremove = 120
Now, we will disable anything over 90 days (or whatever the variable is set to). It is always best to do something slightly less drastic initially.
Get-MgDevice
module here to retrieve all devices from Entra ID. This is the same as running a GET
request against this URL: https://graph.microsoft.com/beta/devices
.We are adding -All
to get everything and not restrict with pagination and then filtering on devices that have not logged on in the last 90 days.
For each of the devices we find, we are calling the Update-MgDevice
command, which is the same as running a POST
/PATCH
request against the same URL. However, rather than having to retrieve, manipulate, and then upload the JSON, this module takes inline parameters to do the hard work for us:
$dt = (Get-Date).AddDays(-$daystodisable) $Devices = Get-MgDevice -All | Where-Object {$_.ApproximateLastLogonTimeStamp -le $dt} foreach ($Device in $Devices) { $deviceid = $Device.Id Update-MgDevice -DeviceId $deviceid -AccountEnabled $false }
Remove-MgDevice
. This is the same as running a DELETE
command against the Devices
/DeviceID
section of Graph:$dt = (Get-Date).AddDays(-$daystoremove) $Devices = Get-MgDevice -All | Where-Object {($_.ApproximateLastLogonTimeStamp -le $dt) -and ($_.AccountEnabled -eq $false)} foreach ($Device in $Devices) { $deviceid = $Device.Id Remove-MgDevice -DeviceId $deviceid }
This script has configured your tenant to allow enrollment and configured key device settings.
Now, we will look at Enterprise State Roaming (ESR), which automatically backs up some device user preferences into Azure for a more seamless experience when moving between Windows devices.
The other device setting within Entra ID is ESR. This is similar to the older User Experience Virtualization (UE-V), which can be found in the Microsoft Desktop Optimization Pack (MDOP).
It backs up certain user settings within Intune and Edge and backs them up to Azure Storage (outside the subscription and without cost).
The following Windows settings are currently backed up:
The following settings are backed up on Edge:
To enable ESR, follow these steps:
You have now enabled ESR across your tenant.
This one is slightly more complicated as it does not work with the Graph API; instead, you have to access the more hidden Azure Identity and Access Management (IAM) API:
##Set to 2 to disable or 0 to enable $esrstatus = 0 $tenantid = "Your-Tenant-ID"
syncSelectedUsers
array. As we are doing an all-or-nothing, we will simply leave the array blank:$json = @" { "isAdminConfigurable": true, "isRoamingSettingChanged": true, "syncSelectedUsers": [], "syncSetting": $esrstatus } "@
$url = "https://main.iam.ad.ext.azure.com/api/RoamingSettings?ESRV2=true"
Invoke-Restmethod
to send a POST
request to the oauth2
Microsoft login URL for the tenant and requesting a token for the Entra ID IAM client ID.As this one requires user interaction, we will add a while
loop to wait until the request has been requested and approved within the web browser. If no activity is detected, the script will stop with an error code:
##Create Access Token $clientid = "1950a258-227b-4e31-a9cf-717495945fc2" $response = Invoke-RestMethod -Method POST -UseBasicParsing -Uri "https://login.microsoftonline.com/$tenantId/oauth2/devicecode" -ContentType "application/x-www-form-urlencoded" -Body "resource=https%3A%2F%2Fmain.iam.ad.ext.azure.com&client_id=$clientId" Write-Output $response.message $waited = 0 while($true){ try{ $authResponse = Invoke-RestMethod -uri "https://login.microsoftonline.com/$tenantId/oauth2/token" -ContentType "application/x-www-form-urlencoded" -Method POST -Body "grant_type=device_code&resource=https%3A%2F%2Fmain.iam.ad.ext.azure.com&code=$($response.device_code)&client_id=$clientId" -ErrorAction Stop $refreshToken = $authResponse.refresh_token break }catch{ if($waited -gt 300){ Write-Verbose "No valid login detected within 5 minutes" Throw } #try again Start-Sleep -s 5 $waited += 5 } } $response = (Invoke-RestMethod "https://login.windows.net/$tenantId/oauth2/token" -Method POST -Body "resource=74658136-14ec-4630-ad9b-26e160ff0fc6&grant_type=refresh_token&refresh_token=$refreshToken&client_id=$clientId&scope=openid" -ErrorAction Stop) $resourceToken = $response.access_token
webrequest
. The authorization section always needs to start with "Bearer"
and then the access token (in this case, $resourceToken
):$Headers = @{ "Authorization" = "Bearer " + $resourceToken "Content-type" = "application/json" "X-Requested-With" = "XMLHttpRequest" "x-ms-client-request-id" = [guid]::NewGuid() "x-ms-correlation-id" = [guid]::NewGuid() }
Invoke-RestMethod -Uri $url -Headers $Headers -Method PUT -Body $json -ErrorAction Stop
This script has automated enabling ESR using the IAM API.
Now that our new user has been configured, we need a way to assign our policies to them and any machines they may use. For this, we need to configure Entra ID groups, which come in two flavors – static and dynamic.
If you are familiar with traditional Active Directory groups, these are very similar, except they include dynamic groups, where a group is populated automatically based on a particular query or filter that has been configured.
First, load the Entra portal, expand Groups, and click on All Groups (you can also access groups within the Intune portal, which loads the same window).
A static group is pretty straightforward to use – you manually add either users or devices to it:
Figure 1.7– Entra ID group menu
Members and Owners are pretty self-explanatory. Administrative units is a useful feature if you want to delegate within your environment. Say, for example, you want your service desk to be able to perform tasks on a particular group of users – you can create an administrative unit and assign users and groups to it. You can then configure a custom Azure role with specific access only to that administrative unit. Group memberships is for nested groups. Clicking the Licenses option allows you to assign a license at a group level rather than directly to the users. If you selected Yes earlier, you can also assign Azure roles to the group in the Azure role assignments menu.
With that, you have created a static Microsoft Entra group.
Creating this PowerShell script will automate your Entra group creation process, which will be useful when you need to bulk-create groups during your tenant management.
This is a fairly easy one to automate:
$groupname = "TestGroup123" $groupdescription = "TestGroupDescription"
$groupnickname = ($groupname -replace '[^a-zA-Z0-9]', '').ToLower()
$uri = "https://graph.microsoft.com/beta/groups/"
$json = @" { "description": "$groupdescription", "displayName": "$groupname", "mailEnabled": false, "mailNickname": "$groupnickname", "securityEnabled": true } "@
Invoke-MgGraphRequest -Uri $uri -Method Post -Body $json -ContentType "application/json"
This can also be completed by using the New-mgGroup
module and passing variables through if required.
You now have a script to create your static Entra groups automatically.
In this recipe, we will configure Entra ID dynamic groups, where we can configure a group to automatically populate based on specified criteria. This example will cover both user and device-based queries.
First, load the Entra portal, expand Groups, and click on All groups (you can also access groups within the Intune portal, which loads the same window).
Dynamic groups are automated; you set a membership rule (the user is a member of a particular location, device prefix, and so on), and then Entra ID reviews the rules on a schedule and adds/removes members accordingly. It is worth noting that there can be a delay while Entra queries the membership rules to populate the group membership.
For this example, we will create one Office user group and one Autopilot device dynamic group that we can use later on.
The user group will collect any users with an Office Business license (not the Enterprise ones), while the device group will collect all of your Autopilot devices; we will cover this in more detail in Chapter 4.
Follow these steps to create a dynamic group containing only licensed Office users:
To detect Office users, we are going to check the user assigned plans:
(assignedPlan.servicePlanId -eq "43de0ff5-c92c-492b-9116-175376d08c38" -and assignedPlan.capabilityStatus -
eq "Enabled"))
.Figure 1.8 – Entra ID – new dynamic rule result
Figure 1.9 – User validation results
With that, we have created a dynamic user group for users with an Office license.
To find the servicePlanId
value for individual products, you can use a downloadable CSV from the Microsoft site. You can use this to create any other dynamic groups: https://learn.microsoft.com/en-us/azure/active-directory/enterprise-users/licensing-service-plan-reference.
When we create our Autopilot profile later, in Chapter 4, we will configure it to automatically pick up all users/devices. However, in a pilot or Proof of Concept (PoC), we may only want to target those devices enrolled in Autopilot. For this, we can query the device’s ZTID, which is added when we import it (covered in Chapter 4).
Follow this process to create our dynamic grou:.
(_ -
startsWith "[ZTDid]
:Figure 1.10 – Dynamic rule creator
Figure 1.11– Dynamic device query
We do not need to validate this one as we do not have a device enrolled yet anyway.
With that, we have created our dynamic Autopilot devices group so that it is ready to enroll devices in Chapter 4.
This script will demonstrate how we can use Graph and PowerShell to create both of our dynamic groups, demonstrating the different queries.
This is similar to a static group, except we must add an extra line for the dynamic rule:
$groupname = "TestGroup123" $groupdescription = "TestGroupDescription" $membershiprule = '(user.assignedPlans -any (assignedPlan.servicePlanId -eq \"43de0ff5-c92c-492b-9116-175376d08c38\" -and assignedPlan.capabilityStatus -eq \"Enabled\"))' $groupnickname = ($groupname -replace '[^a-zA-Z0-9]', '').ToLower()
Important note
We have single quotes around the rule because we are using double quotes in the rule and also escaping the double quotes.
$url = "https://graph.microsoft.com/beta/groups" Populate the JSON $json = @" { "description": "$groupdescription", "displayName": "$groupname", "groupTypes": [ "DynamicMembership" ], "mailEnabled": false, "mailNickname": "$groupnickname", "membershipRule": "$membershiprule", "membershipRuleProcessingState": "On", "securityEnabled": true } "@
Finally, submit our Graph request:
Invoke-MgGraphRequest -Uri $url -Method Post -Body $json -ContentType "application/json"
This script will create a dynamic group for users who have an active Office license based on the SKU and license properties.
This is the same as the user group but with a different rule. The Graph backend does not differentiate between user and device groups.
We can now create a PowerShell script to create a dynamic group:
$groupname = "TestGroup123" $groupdescription = "TestGroupDescription"
$groupnickname = ($groupname -replace '[^a-zA-Z0-9]', '').ToLower()
$membershiprule = '(device.devicePhysicalIDs -any (_ -startsWith "[ZTDid]"))'
$url = "https://graph.microsoft.com/beta/groups"
$json = @" { "description": "$groupdescription", "displayName": "$groupname", "groupTypes": [ "DynamicMembership" ], "mailEnabled": false, "mailNickname": "$groupnickname", "membershipRule": $membershiprule, "membershipRuleProcessingState": "On", "securityEnabled": true } "@
Invoke-MgGraphRequest -Uri $url -Method Post -Body $json -ContentType "application/json"
We now have a script for creating our dynamic Autopilot group.
The last thing we must do before we move on to Intune is allow our users to enroll devices into Mobile Device Management (MDM) and, if required, Mobile Application Management (MAM).
MDM is for enrolling your corporate-owned devices into Intune, while MAM is for your bring-your-own devices (BYODs). MAM uses Windows Information Protection (WIP), which is only supported on Android and iOS, but we can block personal Windows devices within Intune so that we can still set this to everyone and let Intune handle the rest.
Follow these steps to configure your Entra ID MDM and MAM scopes:
Figure 1.12 – The Mobility (MDM and MAM) screen
With that, we have configured our Microsoft Entra environment for device enrollment.
This is a tricky one to automate. Not only does it use the IAM API that we used for ESR, but the MDM application ID is also tenant-specific.
Let us build a PowerShell script to automate these settings:
Figure 1.13 – Address bar object ID
2
means enabled for all, while 0
means disabled:$MDMstatus = 2 $MAMstatus = 2 $policyid = "Policy ID grabbed from browser"
GET
request. In this case, we are only changing two settings; everything else remains the same:$json = @" { "appCategory": "Mdm", "appData": { "complianceUrl": "https://portal.manage.microsoft.com/?portalAction=Compliance", "enrollmentUrl": "https://enrollment.manage.microsoft.com/enrollmentserver/discovery.svc", "mamComplianceUrl": "", "mamEnrollmentUrl": "https://wip.mam.manage.microsoft.com/Enroll", "mamTermsOfUseUrl": "", "termsOfUseUrl": "https://portal.manage.microsoft.com/TermsofUse.aspx" }, "appDisplayName": "Microsoft Intune", "appId": "0000000a-0000-0000-c000-000000000000", "isOnPrem": false, "logoUrl": null, "mamAppliesTo": $MAMstatus, "mamAppliesToGroups": [], "mdmAppliesTo": $MDMstatus, "mdmAppliesToGroups": [], "objectId": "$policyid", "originalAppData": { "complianceUrl": "https://portal.manage.microsoft.com/?portalAction=Compliance", "enrollmentUrl": "https://enrollment.manage.microsoft.com/enrollmentserver/discovery.svc", "mamComplianceUrl": "", "mamEnrollmentUrl": "https://wip.mam.manage.microsoft.com/Enroll", "mamTermsOfUseUrl": "", "termsOfUseUrl": "https://portal.manage.microsoft.com/TermsofUse.aspx" } } "@
$url = "https://main.iam.ad.ext.azure.com/api/MdmApplications /$policyid?mdmAppliesToChanged=true&mamAppliesToChanged=true"
##Create Access Token $clientid = "1950a258-227b-4e31-a9cf-717495945fc2" $response = Invoke-RestMethod -Method POST -UseBasicParsing -Uri "https://login.microsoftonline.com/$tenantId/oauth2/devicecode" -ContentType "application/x-www-form-urlencoded" -Body "resource=https%3A%2F%2Fmain.iam.ad.ext.azure.com&client_id=$clientId" Write-Output $response.message $waited = 0 while($true){ try{ $authResponse = Invoke-RestMethod -uri "https://login.microsoftonline.com/$tenantId/oauth2/token" -ContentType "application/x-www-form-urlencoded" -Method POST -Body "grant_type=device_code&resource=https%3A%2F%2Fmain.iam.ad.ext.azure.com&code=$($response.device_code)&client_id=$clientId" -ErrorAction Stop $refreshToken = $authResponse.refresh_token break }catch{ if($waited -gt 300){ Write-Verbose "No valid login detected within 5 minutes" Throw } #try again Start-Sleep -s 5 $waited += 5 } } $response = (Invoke-RestMethod "https://login.windows.net/$tenantId/oauth2/token" -Method POST -Body "resource=74658136-14ec-4630-ad9b-26e160ff0fc6&grant_type=refresh_token&refresh_token=$refreshToken&client_id=$clientId&scope=openid" -ErrorAction Stop) $resourceToken = $response.access_token
$Headers = @{ "Authorization" = "Bearer " + $resourceToken "Content-type" = "application/json" "X-Requested-With" = "XMLHttpRequest" "x-ms-client-request-id" = [guid]::NewGuid() "x-ms-correlation-id" = [guid]::NewGuid() }
Invoke-RestMethod -Uri $url -Headers $Headers -Method PUT -Body $json -ErrorAction Stop
We now have a script to amend the MDM and MAM enrollment scopes.
Where there is an eBook version of a title available, you can buy it from the book details for that title. Add either the standalone eBook or the eBook and print book bundle to your shopping cart. Your eBook will show in your cart as a product on its own. After completing checkout and payment in the normal way, you will receive your receipt on the screen containing a link to a personalised PDF download file. This link will remain active for 30 days. You can download backup copies of the file by logging in to your account at any time.
If you already have Adobe reader installed, then clicking on the link will download and open the PDF file directly. If you don't, then save the PDF file on your machine and download the Reader to view it.
Please Note: Packt eBooks are non-returnable and non-refundable.
Packt eBook and Licensing When you buy an eBook from Packt Publishing, completing your purchase means you accept the terms of our licence agreement. Please read the full text of the agreement. In it we have tried to balance the need for the ebook to be usable for you the reader with our needs to protect the rights of us as Publishers and of our authors. In summary, the agreement says:
If you want to purchase a video course, eBook or Bundle (Print+eBook) please follow below steps:
Our eBooks are currently available in a variety of formats such as PDF and ePubs. In the future, this may well change with trends and development in technology, but please note that our PDFs are not Adobe eBook Reader format, which has greater restrictions on security.
You will need to use Adobe Reader v9 or later in order to read Packt's PDF eBooks.
Packt eBooks are a complete electronic version of the print edition, available in PDF and ePub formats. Every piece of content down to the page numbering is the same. Because we save the costs of printing and shipping the book to you, we are able to offer eBooks at a lower cost than print editions.
When you have purchased an eBook, simply login to your account and click on the link in Your Download Area. We recommend you saving the file to your hard drive before opening it.
For optimal viewing of our eBooks, we recommend you download and install the free Adobe Reader version 9.