Search icon
Arrow left icon
All Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Newsletters
Free Learning
Arrow right icon
Microsoft Intune Cookbook
Microsoft Intune Cookbook

Microsoft Intune Cookbook: Over 75 recipes for configuring, managing, and automating your identities, apps, and endpoint devices

By Andrew Taylor
€26.99 €17.99
Book Jan 2024 574 pages 1st Edition
eBook
€26.99 €17.99
Print
€33.99
Subscription
€14.99 Monthly
eBook
€26.99 €17.99
Print
€33.99
Subscription
€14.99 Monthly

What do you get with eBook?

Product feature icon Instant access to your Digital eBook purchase
Product feature icon Download this book in EPUB and PDF formats
Product feature icon Access this title in our online reader with advanced features
Product feature icon DRM FREE - Read whenever, wherever and however you want
Buy Now

Product Details


Publication date : Jan 19, 2024
Length 574 pages
Edition : 1st Edition
Language : English
ISBN-13 : 9781805126546
Vendor :
Microsoft
Category :
Concepts :
Table of content icon View table of contents Preview book icon Preview Book

Microsoft Intune Cookbook

Getting Started with Microsoft Intune

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:

  • Creating a tenant
  • Creating a user
  • Assigning Entra ID roles
  • Configuring Entra ID Device settings
  • Configuring Entra ID ESR
  • Creating Entra ID static groups
  • Creating Entra ID dynamic groups
  • Configuring Entra ID MDM/MAM scopes

Technical requirements

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.

Chapter materials

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:

  • Intune Plan 1: This includes your standard Intune functionality, including reporting and Endpoint analytics.
  • Intune Plan 2: This adds Microsoft Tunnel for iOS and Android application-level VPNs and support for specialty devices (such as VR headsets and large conference screens).
  • Intune Suite: This includes everything in Plans 1 and 2 plus Remote Help, Endpoint Privilege Management, and Advanced Endpoint Analytics (all of which will be covered in greater depth in Chapter 14). These can all be purchased individually on Plan 1, but it can work out to be more cost-effective to purchase the suite.

You can purchase your Intune licensing on a standalone plan or as part of the following Microsoft SKUs:

  • Microsoft 365 E3
  • Microsoft 365 E5
  • Microsoft 365 F1
  • Microsoft 365 F3
  • Microsoft 365 A3 (Education Only)
  • Microsoft 365 A5 (Education Only)
  • Microsoft Business Premium
  • Enterprise Mobility + Security E3
  • Enterprise Mobility + Security E5

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:

  • Defender for Endpoint Plan 2
  • AppLocker
  • Credential Guard
  • Windows Autopatch
  • Windows Virtualization Rights
  • Remediations

A very useful site for referencing licensing SKUs and what each contains is https://m365maps.com/.

Creating a tenant

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.

Getting ready

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.

How to do it…

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:

  1. For this book, we are going to grab a Microsoft 365 Business Premium trial license (Microsoft 365 E3 and E5 require an annual purchase); the screen will look as follows:
Figure 1.1 – Microsoft licensing page

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.

  1. Once completed, you will be taken to the Microsoft 365 admin center, where you can double-check your licenses in the Licenses menu under Billing.

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:

  1. First, load up the PowerShell console and install, then import, the module:
    Install-Module -Name Microsoft.Graph.Authentication -Scope CurrentUser -Repository PSGallery -Force
  2. Now, import the newly installed module:
    import-module microsoft.graph.authentication
  3. Finally, we need to connect:
    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.

Creating a user

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.

Getting ready

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.

How to do it…

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:

  1. Click on + New user and then Create new user.
  2. Fill in the basic details. You will be prompted to change your password on your first login, but if you are auto-generating, click the eye icon to show the password so that you can use it to log in later:
Figure 1.2 – Entra user details

Figure 1.2 – Entra user details

  1. Leave Groups and Roles empty for now; we will run through those in the Creating Entra ID groups recipe.
  2. Add a Usage location value on this screen; it will not let you assign a license without one set:
Figure 1.3 – Entra user license details

Figure 1.3 – Entra user license details

  1. Optionally, you can fill in Job Info, but this is not a requirement at this stage.
  2. Finally, click Create.

With that, you have created your first account in your new tenant.

Automating it

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:

  1. First, create the variables to populate – in this case, this is everything we set in the GUI. Setting these as variables instead of hardcoding them within the JSON gives us the option to run within a loop and change the variables each time in the future:
    $displayname = "User One"
    $givenname = "User"
    $surname = "One"
    $usageLocation = "GB"
    $mailNickname = "user1"
    $password = "PASSWORD HERE"
    $domainname = "DOMAIN HERE"
  2. Now, populate the JSON with these variables:
    $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.

  3. Next, tell it where to send the request. There are two versions of the Graph API – V1.0 and Beta. The Beta API receives the latest features ahead of the general release. In this case, either will work, but when creating groups, some aspects, such as being able to assign roles to them, require the beta version.
  4. Next, we must point to the Users section of the Graph API:
    $uri = "https://graph.microsoft.com/beta/users"
  5. Finally, send the request to Microsoft Graph. There are different types of requests you can use; we will run through them quickly so that you understand the difference:
    • GET: This simply retrieves values from Graph to manipulate, export, and more
    • POST: This sends new values to Graph that do not currently exist (a new user, new policy, and so on)
    • PATCH: This updates an existing record
    • PUT: This is similar to PATCH but needs a full URL, including the ID being created
    • DELETE: This deletes whatever you are pointing it at

    This 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.

Assigning Entra ID roles

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.

How to do it…

Follow these steps to assign a built-in role to your newly created user:

  1. Navigate to Entra admin center within your new tenant by going to https://entra.microsoft.com.
  2. Within Entra, click on Show more, then expand the Roles & admins dropdown and click on Roles & admins.
  3. You will be presented with this menu:
Figure 1.4 – Entra ID – Roles and administrators

Figure 1.4 – Entra ID – Roles and administrators

  1. You will now see this screen:
Figure 1.5 – Entra ID – Roles and administrators | All roles

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.

  1. Select Intune Administrator.
  2. On the screen that appears, click + Add Assignments and find your new user:
Figure 1.6 – Assigned Intune Administrator role

Figure 1.6 – Assigned Intune Administrator role

  1. The other way we can do this is within the Users blade; navigate back to Entra ID and click on Users, then the user you created.
  2. Within the user details, click on Assigned roles.
  3. Then, click + Add assignments.
  4. This time, select Microsoft Entra Joined Device Local Administrator and click Add.

Following these steps has granted your user administrative rights on your cloud-joined devices.

Automating it

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:

  1. For this, we will need to install and import an additional module:
    Install-Module Microsoft.Graph.DeviceManagement.Enrolment -Scope CurrentUser -Repository PSGallery -Force
    Import-Module Microsoft.Graph.DeviceManagement.Enrolment
  2. Set the variables, the role name, and the user we are assigning it to (at the time of writing, the role is still called Azure AD Joined Device Local Administrator, but it may change to Entra Joined Device Local Administrator in the future to match the UI):
    $rolename = "Azure AD Joined Device Local Administrator"
    $user = "test@test.onmicrosoft.com"
  3. We need to get the ID from the User Profile Name (UPN). We are querying the Users API to the user’s UPN, passing the output as 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.

  4. The next stage is to find the details for the role we are looking for. We can do this by grabbing all the roles and then using 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
  5. Now that we have the role ID and the user ID, we just need to put them together and assign the role. As we are using a PowerShell module instead of JSON, we must pass parameters instead of raw JSON. Here, we are setting 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.

Configuring Entra ID Device settings

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.

How to do 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:

  1. First, within Entra ID, expand Devices, click Overview, and then click Device Settings.
  2. We need to ensure Users may join devices to Microsoft Entra is set to either All or Selected as we need our machines to be Entra ID joined. We can restrict device types later within Intune, so it is best just to leave this one set to All.

    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.

  3. Once you have configured the settings, click Save.

This recipe has allowed our tenant to accept Intune device enrollment.

Automating it

Again, we can use PowerShell to automate this configuration to make it more easily repeatable:

  1. Set some variables and change them so that they match your environment:
    $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.

  2. These settings are all configured with defaults from the initial tenant configuration, so if you need to check the raw JSON values, run a GET request against this URL: https://graph.microsoft.com/beta/policies/authorizationPolicy/authorizationPolicy.
  3. We are simply manipulating the retrieved values to receive our new values. You can copy and paste this script block as we set our values in Step 1:
    $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
    }
    }
    "@
  4. Then, we manipulate the BitLocker settings:
    $jsonbitlocker = @"
    {"defaultUserRolePermissions":
    {"allowedToReadBitlockerKeysForOwnedDevice":$bitlocker}}
    "@
  5. Now, set the URLs for each setting we are changing:
    $registrationuri = "https://graph.microsoft.com/beta/policies/deviceRegistrationPolicy"
    $bitlockeruri = "https://graph.microsoft.com/beta/policies/authorizationPolicy/authorizationPolicy"
  6. For deviceRegistrationPolicy, we need to send a PUT request:
    Invoke-MgGraphRequest -Method PUT -Uri $registrationuri -Body $jsonsettings -ContentType "application/json"
  7. For the BitLocker policy, we must send a 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:

  1. For this, we need a different module:
    Install-Module -Name Microsoft.Graph.Identity.DirectoryManagement -Repository PSGallery -Force -Scope CurrentUser
    import-module Microsoft.Graph.Identity.DirectoryManagement
  2. Set the necessary variables:
    $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.

  3. After setting the date we are looking for, loop through the devices and find any that have not been seen in that time, then disable them.
  4. We are using the 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
    }
  5. Then, do the same retrieval, but look for anything older than our delete date, which is also disabled (this will stop us from deleting something we had to re-enable previously but still has not been seen for whatever reason). For these devices, remove them using 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.

Configuring Entra ID ESR

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.

How to do it…

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:

  • Keyboard: Turn on toggle keys (off by default)
  • Date, time, and region: Country/region
  • Date, time, and region: Region format (locale)
  • Language: Language profile
  • Keyboard: List of keyboards
  • Mouse: Primary mouse button
  • Passwords: Web credentials
  • Pen: Pen handedness
  • Touchpad: Scrolling direction
  • Wi-Fi: Wi-Fi profiles (only WPA)

The following settings are backed up on Edge:

  • Favorites
  • Passwords
  • Addresses and more (form-fill)
  • Collections
  • Settings
  • Extensions
  • Open tabs (available in Microsoft Edge version 88 or later)
  • History (available in Microsoft Edge version 88 or later)

To enable ESR, follow these steps:

  1. Navigate to Entra ID | Devices | Overview | Device settings and click on Enterprise State Roaming.
  2. Change the Users may sync settings and app data across devices setting to All or Selected. As there is no cost regarding this, it is recommended to set it to All.
  3. Then, click Save.

You have now enabled ESR across your tenant.

Automating it

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:

  1. Set the necessary variables:
    ##Set to 2 to disable or 0 to enable
    $esrstatus = 0
    $tenantid = "Your-Tenant-ID"
  2. Create the JSON. If we had set it to a select user group, it would be populated within the 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
    }
    "@
  3. Set the URL (note the non-Graph setup of it):
    $url = "https://main.iam.ad.ext.azure.com/api/RoamingSettings?ESRV2=true"
  4. Now, create the access token and headers.
  5. When you run this section, you will be presented with a hyperlink and some code that you must enter to authenticate. Click the link, enter the code, and then accept the numerous prompts.
  6. Here, we are using 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
  7. The previous command has given us our access token, which we can then add to the header to call our 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()
    }
  8. Finally, send the request to enable or disable ESR:
    Invoke-RestMethod -Uri $url -Headers $Headers -Method PUT -Body $json -ErrorAction Stop

This script has automated enabling ESR using the IAM API.

Creating Entra ID static groups

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.

Getting ready

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).

How to do it…

A static group is pretty straightforward to use – you manually add either users or devices to it:

  1. Click on New Group and enter the necessary details. Set Group type to Security and enter Group name and Group description values. If you want to be able to assign roles directly to the group instead of at the user level (for example, you want a group of Intune administrators), change the setting to Yes. Set Membership type to Assigned. Optionally, add any members and an owner to manage the group. Then, click Create.
  2. Once your group has been created, click on it to look at some of the other actions you can take against it. You can also get an overview of the group membership, as well as the group ID:
Figure 1.7– Entra ID group menu

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.

Automating it

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:

  1. As usual, we need to start with the variables:
    $groupname = "TestGroup123"
    $groupdescription = "TestGroupDescription"
  2. Convert the group name into lowercase and remove any special characters so that we can use it as the mail nickname:
    $groupnickname = ($groupname -replace '[^a-zA-Z0-9]', '').ToLower()
  3. Set the URL. Here, we are using the Groups subsection of Graph:
    $uri = "https://graph.microsoft.com/beta/groups/"
  4. Populate the JSON. We do not need mail for this group as it is for Entra ID and Intune membership only and it is a security group, so we need to pass this through:
    $json = @"
    {
        "description": "$groupdescription",
        "displayName": "$groupname",
        "mailEnabled": false,
        "mailNickname": "$groupnickname",
        "securityEnabled": true
    }
    "@
  5. Send the command to create the group:
    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.

Creating Entra ID dynamic groups

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.

Getting ready

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).

How to do it…

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.

Creating a dynamic Office user group

Follow these steps to create a dynamic group containing only licensed Office users:

  1. Starting with the user group, click New Group and enter the basic details:
    1. Group type: Security.
    2. Enter Group name and Group description details.
    3. Change the membership type to Dynamic User.
  2. You will notice that we have to create a dynamic query. So, click Add dynamic query. This will take you to the Configure Rules interface and is where you can view the properties available and set them accordingly. If you already know the query, you can add it directly into the Rule syntax window.

    To detect Office users, we are going to check the user assigned plans:

    1. For Property, select assignedPlans.
    2. Set Operator to Any.
    3. The Value needs to be(assignedPlan.servicePlanId -eq "43de0ff5-c92c-492b-9116-175376d08c38" -and assignedPlan.capabilityStatus -eq "Enabled")).
    4. It should look like this in the syntax (sometimes, you may need to edit it to add the final closing brackets):
Figure 1.8 –  Entra ID – new dynamic rule result

Figure 1.8 – Entra ID – new dynamic rule result

  1. Now, click the Validate Rules button.
  2. Add a user who has an Office license assigned and click Select.
  3. Then, click Validate. Here, you can see I have only assigned the license to one of my two users:
Figure 1.9 – User validation results

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.

Creating a dynamic Autopilot device group

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:.

  1. Create a New Group value in Entra ID, but this time, pick Dynamic Device as the membership type. Set Group type to Security. Then, add the Group name and Group description values. Finally, click Add dynamic query.
  2. This one is slightly more straightforward. Set Property to devicePhysicalIds, Operator to Any, and Value to (_ -startsWith "[ZTDid]:
Figure 1.10 – Dynamic rule creator

Figure 1.10 – Dynamic rule creator

  1. It should look like this (sometimes, you may need to edit it to add the final closing brackets). Click OK on this screen:
Figure 1.11– Dynamic device query

Figure 1.11– Dynamic device query

We do not need to validate this one as we do not have a device enrolled yet anyway.

  1. Now, click Save, then Create on the following screen.

With that, we have created our dynamic Autopilot devices group so that it is ready to enroll devices in Chapter 4.

Automating it

This script will demonstrate how we can use Graph and PowerShell to create both of our dynamic groups, demonstrating the different queries.

Dynamic Office user group

This is similar to a static group, except we must add an extra line for the dynamic rule:

  1. Set the necessary variables:
    $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.

  1. Now, give it a URL:
    $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.

Dynamic Autopilot device group

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:

  1. Set the necessary variables:
    $groupname = "TestGroup123"
    $groupdescription = "TestGroupDescription"
  2. Set the mail nickname:
    $groupnickname = ($groupname -replace '[^a-zA-Z0-9]', '').ToLower()
  3. Set the membership rule:
    $membershiprule = '(device.devicePhysicalIDs -any (_ -startsWith "[ZTDid]"))'
  4. Set the URL:
    $url = "https://graph.microsoft.com/beta/groups"
  5. Populate the JSON:
    $json = @"
    {
        "description": "$groupdescription",
        "displayName": "$groupname",
        "groupTypes": [
            "DynamicMembership"
        ],
        "mailEnabled": false,
        "mailNickname": "$groupnickname",
        "membershipRule": $membershiprule,
        "membershipRuleProcessingState": "On",
        "securityEnabled": true
    }
    "@
  6. Finally, submit our Graph request:
    Invoke-MgGraphRequest -Uri $url -Method Post -Body $json -ContentType "application/json"

We now have a script for creating our dynamic Autopilot group.

Configuring Entra ID MDM/MAM scopes

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.

How to do it…

Follow these steps to configure your Entra ID MDM and MAM scopes:

  1. Within Microsoft Entra ID, expand Settings and click on Mobility.
  2. Within the Mobility portal, click Microsoft Intune:
Figure 1.12 – The Mobility (MDM and MAM) screen

Figure 1.12 – The Mobility (MDM and MAM) screen

  1. For this environment, set them both to All. Note you can restrict by groups – for example, only allowing users with an Intune license based on a dynamic group, or block users from enrolling completely. Leave the default URLs as is and then click Save.

With that, we have configured our Microsoft Entra environment for device enrollment.

Automating it

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:

  1. First, in your browser window, look in the address bar and grab the ID:
Figure 1.13 – Address bar object ID

Figure 1.13 – Address bar object ID

  1. Set the necessary variables, including this ID. A setting of 2 means enabled for all, while 0 means disabled:
    $MDMstatus = 2
    $MAMstatus = 2
    $policyid = "Policy ID grabbed from browser"
  2. Populate the JSON. As with the Entra ID device settings, we are manipulating the default values so that we can retrieve the current JSON with a 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"
        }
    }
    "@
  3. Set the URL:
    $url = "https://main.iam.ad.ext.azure.com/api/MdmApplications
    /$policyid?mdmAppliesToChanged=true&mamAppliesToChanged=true"
  4. Authenticate against the IAM API:
    ##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
  5. Create the headers:
    $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()
    }
  6. Configure the policy:
    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.

Left arrow icon Right arrow icon
Download code icon Download Code

Key benefits

  • Create and configure your new mobile device management (MDM) environment
  • Become an Intune pro by mastering compliance policies, monitoring techniques, reporting practices, and application deployment procedures
  • Learn how to manage Windows, Android, iOS, and macOS devices using Intune
  • Purchase of the print or Kindle book includes a free PDF eBook

Description

Microsoft Intune is a cloud-managed mobile device management (MDM) tool that empowers you to manage your end-user device estate across various platforms. While it is an excellent platform, the initial setup and configuration can be a daunting process, and mistakes made early on can be more challenging to resolve later. This book addresses these issues by guiding you through the end-to-end configuration of an Intune environment, incorporating best practices and utilizing the latest functionalities. In addition to setting up your environment, you’ll delve into the Microsoft Graph platform to understand the underlying mechanisms behind the web GUI. This knowledge will enable you to automate a significant portion of your daily tasks using PowerShell. By the end of this book, you’ll have established an Intune environment that supports Windows, Apple iOS, Apple macOS, and Android devices. You’ll possess the expertise to add new configurations, policies, and applications, tailoring an environment to your specific requirements. Additionally, you’ll have the ability to troubleshoot any issues that may arise and package and deploy your company applications. Overall, this book is an excellent resource for anyone who wants to learn how to use Microsoft Intune to manage their organization's end-user devices.

What you will learn

Set up your Intune tenant and associated platform connections Create and deploy device policies to your organization's devices Find out how to package and deploy your applications Explore different ways to monitor and report on your environment Leverage PowerShell to automate your daily tasks Understand the underlying workings of the Microsoft Graph platform and how it interacts with Intune

What do you get with eBook?

Product feature icon Instant access to your Digital eBook purchase
Product feature icon Download this book in EPUB and PDF formats
Product feature icon Access this title in our online reader with advanced features
Product feature icon DRM FREE - Read whenever, wherever and however you want
Buy Now

Product Details


Publication date : Jan 19, 2024
Length 574 pages
Edition : 1st Edition
Language : English
ISBN-13 : 9781805126546
Vendor :
Microsoft
Category :
Concepts :

Table of Contents

17 Chapters
Preface Chevron down icon Chevron up icon
Chapter 1: Getting Started with Microsoft Intune Chevron down icon Chevron up icon
Chapter 2: Configuring Your New Tenant for Windows Devices Chevron down icon Chevron up icon
Chapter 3: Securing Your Windows Devices with Security Policies Chevron down icon Chevron up icon
Chapter 4: Setting Up Enrollment and Updates for Windows Chevron down icon Chevron up icon
Chapter 5: Android Device Management Chevron down icon Chevron up icon
Chapter 6: iOS Device Management Chevron down icon Chevron up icon
Chapter 7: macOS Device Management Chevron down icon Chevron up icon
Chapter 8: Setting Up Your Compliance Policies Chevron down icon Chevron up icon
Chapter 9: Monitoring Your New Environment Chevron down icon Chevron up icon
Chapter 10: Looking at Reporting Chevron down icon Chevron up icon
Chapter 11: Packaging Your Windows Applications Chevron down icon Chevron up icon
Chapter 12: PowerShell Scripting across Intune Chevron down icon Chevron up icon
Chapter 13: Tenant Administration Chevron down icon Chevron up icon
Chapter 14: Looking at Intune Suite Chevron down icon Chevron up icon
Index Chevron down icon Chevron up icon
Other Books You May Enjoy Chevron down icon Chevron up icon

Customer reviews

Filter icon Filter
Top Reviews
Rating distribution
Empty star icon Empty star icon Empty star icon Empty star icon Empty star icon 0
(0 Ratings)
5 star 0%
4 star 0%
3 star 0%
2 star 0%
1 star 0%

Filter reviews by


No reviews found
Get free access to Packt library with over 7500+ books and video courses for 7 days!
Start Free Trial

FAQs

How do I buy and download an eBook? Chevron down icon Chevron up icon

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:

  • You may make copies of your eBook for your own use onto any machine
  • You may not pass copies of the eBook on to anyone else
How can I make a purchase on your website? Chevron down icon Chevron up icon

If you want to purchase a video course, eBook or Bundle (Print+eBook) please follow below steps:

  1. Register on our website using your email address and the password.
  2. Search for the title by name or ISBN using the search option.
  3. Select the title you want to purchase.
  4. Choose the format you wish to purchase the title in; if you order the Print Book, you get a free eBook copy of the same title. 
  5. Proceed with the checkout process (payment to be made using Credit Card, Debit Cart, or PayPal)
Where can I access support around an eBook? Chevron down icon Chevron up icon
  • If you experience a problem with using or installing Adobe Reader, the contact Adobe directly.
  • To view the errata for the book, see www.packtpub.com/support and view the pages for the title you have.
  • To view your account details or to download a new copy of the book go to www.packtpub.com/account
  • To contact us directly if a problem is not resolved, use www.packtpub.com/contact-us
What eBook formats do Packt support? Chevron down icon Chevron up icon

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.

What are the benefits of eBooks? Chevron down icon Chevron up icon
  • You can get the information you need immediately
  • You can easily take them with you on a laptop
  • You can download them an unlimited number of times
  • You can print them out
  • They are copy-paste enabled
  • They are searchable
  • There is no password protection
  • They are lower price than print
  • They save resources and space
What is an eBook? Chevron down icon Chevron up icon

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.