When VDI and ConfigMgr Co-Management Collide

Before we begin, here are some notes about persistent and non-persistent VDI that will likely give you nightmares:

Failed Azure AD Join
Failed Azure AD Join

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
+----------------------------------------------------------------------+
| Diagnostic Data                                                      |
+----------------------------------------------------------------------+

     Diagnostics Reference : www.microsoft.com/aadjerrors
              User Context : UN-ELEVATED User
               Client Time : 2021-11-13 07:34:49.000 UTC
      AD Connectivity Test : PASS
     AD Configuration Test : PASS
        DRS Discovery Test : PASS
     DRS Connectivity Test : PASS
    Token acquisition Test : SKIPPED
     Fallback to Sync-Join : ENABLED

     Previous Registration : 2021-11-13 07:14:20.000 UTC
         Registration Type : sync
               Error Phase : join
          Client ErrorCode : 0x801c03f3
          Server ErrorCode : invalid_request
       Server ErrorSubCode : error_missing_device
          Server Operation : DeviceRenew
            Server Message : The device object by the given id (f3751f0c-ed18-4205-8079-645ae0c9efaf) is not found.
              Https Status : 400
                Request Id : 82955534-26d6-4c06-8929-1c62096d7a36
    Executing Account Name : ASD\Adam

What have we done??

Today’s problem was discovered when our VDI master images were built and updated using ConfigMgr in an environment where Hybrid Azure AD Join and Co-Management is enabled for all devices (which automatically Intune Enrolls devices). When the master image is cloned to create new worker VMs (persistent or non-persistent), the new VMs all share the same Azure AD and Intune device IDs. Within Azure and Intune, if you search for a specific Device by ID a single device record is returned which changes randomly depending on which device checked in last.

We now run the script linked below along with BISF scripts and many other custom steps to clean up the master image and we disable the ConfigMgr client so that it doesn’t launch on the non-persistent devices, which prevents Co-Management from kicking in and re-enrolling into Intune. For persistent VDI cloned from master images, we re-enable ConfigMgr and manage the devices as regular worksations.

Take the Good with the Bad

If you have ever used a device which has not been Hybrid Azure AD joined to access any Microsoft cloud resources, you’ve likely been prompted numerous times to enter your Azure AD credentials. This can be overcome by hybrid joining your device to Azure AD. This has a huge user experience benefit but when used on cloned devices can really cause some issues. If you want the device to be Hybrid Azure AD Joined, then you will need to prepare your master image properly before cloning.

Take your Pick

The best part about this issue when using ConfigMgr is that it’s super easy to find devices with duplicate Azure AD Device IDs. The quickest way is to add the Azure Active Directory Device ID column to the ConfigMgr console. You can even group by the column to make is easier to find devices sharing the same ID.

Right Click and Select Azure Active Directory Device ID
Right Click and Select Azure Active Directory Device ID

Sort to find the same ID
Sort to find the same ID

Scroll to the bottom of the list to select Group By
Scroll to the bottom of the list to select Group By

Grouped by Azure Active Directory Device ID
Grouped by Azure Active Directory Device ID

Another alternative is to create a collection to help quickly determine how many devices are using duplicate IDs. I’ve uploaded a MOF file to my repo that you can import to create a new collection. Duplicate Azure AD Device ID.MOF

Duplicate Azure AD Device ID Collection
Duplicate Azure AD Device ID Collection

Grouped by Azure Active Directory Device ID
Grouped by Azure Active Directory Device ID

Too Much of a Good Thing

While searching for a solution to this problem, I frequently ran across solutions for handling Azure AD and ConfigMgr but nothing much related to Intune and Co-Management. When Co-Management is enabled, the Enablement tab has an option for Automatic enrollment in Intune which can target a pilot collection or all devices.

Co-Management Options
Co-Management Options

Unfortunately, All means just that. The moment a device is (Hybrid) Azure AD Joined it will trigger the Co-Management handler service which immediately triggers the Intune enrollment process for the device. You can watch CoManagementHandler.log on a client to see this in action.

Co-Management isn’t great on a master image.

If We Could Turn Back Time

Once a master image has been enrolled in Intune, you can’t just use DSREGCMD /LEAVE in the cleanup script before re-sealing it - each clone will still think that it is Intune enrolled and it will continue to re-register in Azure AD with the same device ID as the master.

Hybrid Azure AD Joined and Intune Enrolled
Hybrid Azure AD Joined and Intune Enrolled

The first step here is going to be un-enrolling the device from Intune. Unfortunately, that’s not really a feature that exists natively so we have to cleanup the client so that it no longer thinks that it’s enrolled in Intune so that we can disjoin and rejoin Azure AD.

Un-Enrolling - Just like Enrolling, only Backwards

To reverse the process, we need to delete everything listed below.

Scheduled Tasks

  • Task Scheduler Library > Microsoft > Windows > EnterpriseMgmt
  • New GUID folder created. This is the key to the rest of the puzzle.

Scheduled Task GUID is Key
Scheduled Task GUID is Key

Registry Keys

  • Several keys get created, but only these need to be deleted
  • HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Enrollments<ScheduledTaskGUID>
  • HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Enrollments\Status<ScheduledTaskGUID>
  • HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\EnterpriseResourceManager\Tracked<ScheduledTaskGUID>
  • HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\PolicyManager\AdmxInstalled<ScheduledTaskGUID>
  • HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\PolicyManager\Providers<ScheduledTaskGUID>
  • HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Provisioning\OMADM\Accounts<ScheduledTaskGUID>
  • HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Provisioning\OMADM\Logger<ScheduledTaskGUID>
  • HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Provisioning\OMADM\Sessions<ScheduledTaskGUID>

Enrollment Registry Entries
Enrollment Registry Entries

Intune Device ID
Intune Device ID

Certificates

  • 2 certificates will be created. One for Azure and one for MDM. Delete both.
  • Note that the GUID in Issued To for the certs will match the Intune and Azure AD Device IDs
  • Issued By Microsoft Intune MDM Device CA
  • Issued By MS-Organization-Access
  • Issued By MS-Organization-P2P-Access

They are Connected!
They are Connected!

Once you delete all of the items listed above, you can safely disjoin from Azure AD using DSREGCMD /LEAVE. But wait, there’s an easier way!

One Script to UnEnroll them All

Ok so I took you through all of the manual goodness because, just like GI JOE always says “Knowing is half the battle!”. The other half is hoping you don’t run out of broken VMs to test the script on before you get it working!

Knowing Is Half the Battle

The script is written to be run in ConfigMgr. Instead of posting the script content here, I’m just going to link my repo so that any changes are updated there. Check out the comments in the code for more details and for updates.

If you continue to have issues with re-joining, you may need to delete the AAD, Intune and Autopilot device objects from your tentant then wait for Azure AD Connect to re-sync.

Note - This has only been tested for Hybrid Azure AD Joined Devices. https://github.com/AdamGrossTX/Toolbox/blob/master/Intune/Intune-UnHybridJoin.ps1

Parting Thoughts

One question comment I’m sure I’ll get is around Co-Management and using pilot collections instead of deploying to all devices. One major reason not to leave Co-Management in pilot mode is because it targets a collection. That collection will need to be populated and updated when a new device is built and that takes time. Targeting all devices allows a device to immediately become Co-Managed as soon as the client pulls down policies. That seems like a better experience than using pilot to work around this.