Recently I needed to delete a desktop machine from the Windows Autopilot service in order to use the machine in another tenant. But the problem was that the Intune and Azure AD device objects were already deleted. All attempts taken within the Microsoft 365 Device Management and Intune Portal were unsuccessful.
Issue # Usually the autopilot device shows the associated Azure AD and Intune objects but here they were shown as N/A (not available) because they were already deleted.
Every attempt to delete the device produced the following error:
Device 8CC9082ZVE deletion failed. Please delete the associated Intune device before deleting this Autopilot device record.
Solution # A quick visit to the Microsoft Store for Business resolved things because there I could delete the device without any issue. Direct URL to the Microsoft Store for Business. After a sync in the Intune Autopilot Devices pane the device had also gone from the Intune portal.
Final words # This was a rather short post but I hope it prevents headache if you want to delete an Autopilot device with stale Azure AD / Intune records.
Nowadays where cloud services are available from all over the world we cannot (only) rely on trusted networks and on identities protected by usernames and passwords. Conditional access allows you to define granular controls whether an identity can access cloud applications. Based on the positive feedback for my “5 Ways to Screw up your Intune Tenant” post I felt empowered to get conditional access covered as well.
Chose your platform wisely # If you intend to use the device platform filter make sure that you cover all platforms including unknown platforms. Otherwise your might have a lack in your battleship. Also note that platform detection is based on best effort and can be exploited.
Long live legacy # Mind the client apps configuration to ensure that your conditional access policies also apply to non-modern authentication clients. If you have created your conditional access policies in the early days of the product you didn’t have this option available.
Something that has created some confusion is that conditional access policies don’t include legacy authentication clients by default, this means that if you have a conditional access policy enforcing MFA for all users and all cloud apps, it doesn’t block legacy authentication clients (or “Other clients”, as the CA UI refers to them) - Sue Bohn, Microsoft
I’m happy to share some field notes and experiences with the Windows Autopilot White Glove feature which is available with the Windows 10 1903 release. I’ve done a lot of testing and engineering for a recent project which also included this brand new feature.
First things first (requirements) # This is probably the most important information of this post. Really make sure to verify the following prerequisites for Autopilot White Glove. Because there are additional requirements compared to Autopilot enrollments.
Basic Autopilot # Make sure that a “classical” Autopilot Deployment is working properly without any issues.
Hardware and OS # Hardware with support for device Attestation (“Physical devices that support TPM 2.0 and device attestation; virtual machines are not supported.”) Physical devices with Ethernet connectivity (WiFi connectivity is not supported!) Windows 10, version 1903 with KB4505903 injected (equals OS Build 18362.267) Starting the white glove adventure # Preparing Windows 10 1903 # As mentioned by Michael Niehaus Windows multiple Autopilot issues were fixed by KB4505903. So we need to inject this cumulative update to the downloaded source. This was already the first hurdle to overcome because I’ve missed the fact that the Windows Setup (install.wim) actually contained multiple image indexes (yeah it’s kinda embarrassing). We achieve this by using dism offline servicing with PowerShell cmdlets.
While testing Autopilot White glove for a customer project my test machines always got stuck within the “Registering your device for mobile management” step and timed out after 12 minutes and returned the error “0x81036501” just before showing the White Glove Failed screen. I was doing my tests with Windows 10 1903 DE (German) with the most recent cumulative update installed, meaning OS build: 18362.267.
The Issue # As normal Autopilot enrollments were working like a charm this one had to be related to the White Glove scenario. Here’s a screen capture showing the actual behavior (unfortunately with German display language):
By pressing [shift] + [F10] i opened a command prompt and launched the event viewer (eventvwr.msc). In the “Microsoft-Windows-ModernDeployment-Diagnostics-Provider/Autopilot” event log I found the following error popping up multiple times, including a retry attempt and limit:
Autopilot discovery failed to find a valid MDM. Confirm that the AAD tenant is properly provisioned and licensed for exactly one MDM. HRESULT = 0x81036501
AutopilotManager failed during device enrollment phase DeviceDiscovery. HRESULT = 0x81036501
On the enrollment status page the error “0x81036501” got displayed for like one second before showing the red generic Autopilot White glove error screen.
The Intune Win32 app requirements feature is quite underrated and often overseen in my experience. The ability to specify a custom PowerShell scripts allow us to check for specific hardware or device properties in order to determine if an app or firmware update should be installed or not. So there’s no need to build multiple and complex dynamic Azure AD groups for the assignment of your apps.
Use cases from the field # From recent projects I’ve discovered the following use cases to deploy Win32 apps only to specific hardware types:
Install specific device drivers or hardware vendor’s software which is not available within the Windows update catalog (e.g. hotkey features, firmware updates) Install a VPN client only on notebooks and tablets (e.g. Palo Alto GlobalProtect Client) Win32 app requirements # Intune Win32 app requirements are evaluated by the Intune Management Extension to check if a device fulfills defined requirements for an application installation. Requirements support both built-in and custom rules.
Built-in rules # Wit the built-in capabilities we can check for:
Here are 5 common recommendations based on misconfigurations I’ve came across in the field which will give your Intune tenant and devices a hard time to work smoothly. So better read this post that you not screw up your Intune tenant and maybe take advantage of the experiences others already gained.
Housekeeping # It’s important to know which devices are actually being used and usually a nice addition to understand compliance data. Stale device entries in may give you a wrong impression of your Intune tenant and it’s health. So enable the automatic device cleanup rule to remove the enrolled device from Intune. Additionally you may also remove the device entries stored in Azure Active Directory (I created a little on-demand script for this which can also run in azure automation).
Same applies to registered Autopilot devices. E.g. if you allow your employees to buy their old devices from the company if they get a new one make sure to remove the device from the Autopilot service. Otherwise you’ll see it again popping up in your tenant very soon. Thus it also prevents the device from being registered in another tenant as autopilot device.
I’m thrilled to introduce the intune-drive-mapping-generator which creates PowerShell scripts to map network drives with Intune. The tool is open source and built on ASP.NET Core MVC.
The intune-drive-mapping-generator is your tool of choice to:
Generate an Intune PowerShell script to map network drives on Azure AD joined devices Seamlessly migrate existing network drive mapping group policies Generate a network drive mapping configuration from scratch Use an existing Active Directory group as a filter to deploy all your drive mapping configurations within one script This all happens without scripting effort. You receive a fully functional PowerShell script for the deployment with Intune.
Architecture # This tool is designed to work best with the following components although it can be useful for other purposes(?) :
Azure AD Joined and Intune enrolled Windows 10 devices Synced user account from Active Directory to Azure Active Directory (Azure AD Connect) On-premises file servers Howto # Export existing group policy # To convert your existing drive mapping group policy configuration, save the GPO as XML report with the group policy management console.
Why want you to create desktop shortcuts with Intune? Business specific apps may require special shortcuts in order to launch the application with the right parameters. Or you need to create a shortcut for an application which is stored on your on premises fileserver. For this purpose I created a little solution which closes the gap between the modern cloud and on premises world. In comparison with other solutions this one works if you have redirected the users desktop with OneDrive Known Folder Move and automatically remediates missing shortcuts if they got deleted.
Direct link to the GitHub repository.
Browser links: Instead of placing shortcuts to websites on the desktop I would recommend you to use managed bookmarks which can be directly provisioned within the web browser. I documented this for the new Microsoft Edge based on chromium here. {: .notice}
Features # This solution works when the desktop is redirected with OneDrive Known Folder Move Everything is user based (local userprofile) If the shortcut is missing or deleted it gets automatically (re)created Possibility to remove shortcut via Intune Win32 app uninstall Shortcut can point to: URL, File (UNC) or Folder (UNC) Ability to pass shortcut arguments Ability to specify shortcut icon (UNC/URL) Ability to deploy shortcut together with an app using Intune Win32 app dependencies Architecture # A simple PowerShell script which does all the shortcut stuff is wrapped as Intune Win32 App. This adds possibility to detect the presence of the shortcut and if required to uninstall it with Intune. In order to work with the redirected desktop to OneDrive with Known Folder Move we can take advantage of the [Environment]::GetFolderPath("Desktop") method to resolve the desktop location. Based on the Win32 app configuration the shortut get’s either created on the users personal desktop or on the allusers desktop.
Recently I read a great article from the Microsoft IAM Director Sue Bohn concerning a Conditional Access Q&A. One question was about the device platform feature - which let’s you apply a policy only to a specific device platform like iOS, Android or Windows 10.
The detection of the device platform relies on the user agent string sent by the application or web browser. Because this one can be spoofed easily better configure your Conditional Access policies wisely.
The problem # As soon as you enable the device platform selection there’s the chance that a user doesn’t catch any Conditional Access policy.
As a result, you should not rely on the User Agent String to be present or to be accurate. Most browsers have a function to set an arbitrary User Agent String for testing purposes. (Microsoft)
Bypass example # To give you an example, here’s a little walk-through:
Conditional Access Policy configured for all cloud apps Windows 10 selected as device platform Access control: Block If we now try to access the azure portal with a Windows 10 app or browser we get the following result:
A colleague recently asked me how to access the Microsoft Graph API using PowerShell without specifying his user account or credentials. So here’s a little post about the required configuration to authenticate against the OAuth 2.0 endpoint of Azure AD with an app registration. This is especially useful for automation services like Azure automation.
At the end of this post you’ll find a PowerShell template.
Gather application information # Create a new client secret for your app and note down the following values:
Client Secret Application ID (client ID) Directory ID (tenant ID) Azure AD App registration ## PowerShell code Request authentication token # In order to use the Graph API we need an authentication token. The information we gathered before is now sent to the Azure AD OAuth 2.0 endpoint.
https://login.microsoftonline.com/{TenantID}/oauth2/v2.0/token In the request supply a body with the following content:
$body=@{ client_id="8f9f420d-606c-4e13-889e-837072dbfb42" client_secret="BlaBlaExampleSecret" #Generated secret scope="https://graph.microsoft.com/.default" grant_type="client_credentials" } The scope and grant_type are required attributes. A full example looks like:
$body=@{ client_id="8f9f420d-606c-4e13-889e-837072dbfb42" client_secret="BlaBlaExampleSecret" scope="https://graph.microsoft.com/.default" grant_type="client_credentials" } $tenantId="7955e1b3-cbad-49eb-9a84-e14aed7f3400" Invoke-WebRequest -Uri "https://login.microsoftonline.com/$tenantId/oauth2/v2.0/token" -ContentType "application/x-www-form-urlencoded" -Body $body -Method Post If everything works we receive an access token object as HTML 200/ok response: