🚀 Executive Summary
TL;DR: Automating Intune enrollment for AVD multi-session hosts via Terraform often fails due to identity model conflicts, as multi-session hosts lack a single primary user to trigger MDM enrollment. Solutions range from a quick custom script extension to a robust golden image strategy, with a declarative Intune policy fix being the recommended ‘right way’ for most production environments.
🎯 Key Takeaways
- AVD multi-session hosts present a unique challenge for Intune enrollment because their shared resource nature conflicts with Azure AD’s standard user-triggered MDM enrollment process.
- The ‘Right Way’ to achieve automatic Intune enrollment involves configuring a dynamic Azure AD group to target AVD hosts and assigning a Windows automatic enrollment profile in Intune to this group.
- For large-scale or enterprise environments, a ‘Golden Image’ approach using Packer to pre-configure and capture AVD hosts, then deploying from an Azure Compute Gallery, offers the most reliable and fastest deployment with baked-in Intune configuration.
Struggling to automate AVD multi-session Intune enrollment with Terraform? This guide breaks down the root cause and provides three battle-tested solutions, from a quick script fix to a robust golden image strategy.
The Multi-Session Headache: My Guide to AVD, Terraform, and Intune Enrollment
I remember it vividly. It was 10 PM on a Thursday, the go-live for the new finance department’s remote access platform was the next morning, and my Terraform plan had run perfectly. Green checkmarks everywhere. But the AVD session hosts, all shiny and new, were sitting in Azure, stubbornly refusing to enroll in Intune. The monitoring dashboard was a sea of red, and the security team’s policy required Intune management on every single endpoint. No exceptions. That’s when the panic starts to set in—the feeling that you’ve followed the manual perfectly, but the cloud has other, more frustrating plans. This AVD multi-session enrollment problem is a classic “last mile” issue that has tripped up more engineers than I can count.
So, Why Does This Keep Breaking?
Before we dive into the fixes, you need to understand the “why.” This isn’t just a simple bug; it’s a conflict of identity models. When you provision a standard Windows 10/11 VM and Azure AD Join it, the process is straightforward—it assumes a single primary user. But an AVD multi-session host is a different beast entirely. It doesn’t have a single “owner.” It’s a shared resource.
The core of the problem is that the standard Terraform provisioning process for an `azurerm_windows_virtual_machine` might successfully Azure AD Join the machine, but it often fails to trigger the crucial subsequent step: the Mobile Device Management (MDM) enrollment into Intune. The automatic enrollment policy in Azure AD is looking for a user to sign in to trigger the process, but the system identity created by Terraform during the build doesn’t satisfy this requirement for a multi-session host. It’s a classic chicken-and-egg problem, and your Terraform code is stuck in the middle.
The Fixes: From Duct Tape to a New Engine
I’ve seen teams wrestle with this for weeks. The good news is, you don’t have to. Here are three ways to solve this, ranging from the quick-and-dirty to the architecturally sound.
Solution 1: The Quick Fix (The ‘Get-It-Done’ Script)
Let’s be honest, sometimes you just need to get the lights on. This approach uses a custom script extension in Terraform to force the Intune enrollment after the VM is built and joined to Azure AD. It’s reactive and a bit “hacky,” but it works when you’re in a jam.
You add a `azurerm_virtual_machine_extension` resource to your Terraform code that runs a simple PowerShell command to kick the enrollment process into gear.
resource "azurerm_virtual_machine_extension" "intune_enrollment_fix" {
name = "IntuneEnrollmentFix"
virtual_machine_id = azurerm_windows_virtual_machine.avd_host.id
publisher = "Microsoft.Compute"
type = "CustomScriptExtension"
type_handler_version = "1.10"
settings = <<SETTINGS
{
"commandToExecute": "powershell.exe -ExecutionPolicy Unrestricted -Command \"& { C:/Windows/System32/deviceenroller.exe /c /AutoEnrollMDM }\""
}
SETTINGS
}
Why it works: This directly invokes the enrollment client on the VM, bypassing the need for a user-triggered event. It’s a sledgehammer, but an effective one.
Warning: This is technical debt. It fixes the symptom, not the cause. If the underlying timing or permissions change in Azure, this script could start failing silently. Use it to get out of a fire, but plan to implement a proper fix later.
Solution 2: The ‘Right Way’ (The Intune Policy Fix)
The more permanent, declarative solution involves letting the tools do their job correctly. This approach focuses on ensuring your Intune and Azure AD policies are set up to automatically grab the AVD hosts as soon as they appear.
The magic isn’t in Terraform; it’s in a well-configured Intune Enrollment Profile and a dynamic Azure AD group. Terraform’s only job is to build the VM with the right properties (like a consistent naming convention or specific tags).
- Create a Dynamic AAD Group: In Azure AD, create a dynamic group that targets your AVD hosts. A common rule is to key off the VM name. For example, if all your hosts are named `avd-prod-finance-vm-##`, you can use a rule like
(device.displayName -startsWith "avd-prod-finance"). - Target an Enrollment Profile: In the Microsoft Intune admin center, go to Devices > Enrollment > Windows automatic enrollment. Make sure MDM enrollment is enabled. Then, create a Device Configuration Profile specifically for your AVD settings and assign it to the dynamic AAD group you just created.
- Terraform’s Role: Your Terraform code now just needs to create the VM. Once the VM joins Azure AD and its name matches the dynamic group rule, it will automatically be added to the group, receive the policy, and enroll itself in Intune. No custom scripts needed.
This is the proper “Infrastructure as Code” way. The state of your AVD fleet is managed by policy, not by imperative scripts running on each box.
Solution 3: The ‘Nuclear’ Option (The Golden Image Approach)
For large-scale, enterprise environments where consistency and deployment speed are paramount, you stop building these complex VMs from scratch with Terraform every time. Instead, you create a perfect “golden image” and deploy from that.
The Workflow:
- Build with Packer: Use a tool like HashiCorp Packer to create a VM, install all the AVD agents, run Windows Update, install necessary applications, configure settings, and then sysprep and capture it as a generalized image. The Intune enrollment configuration can be baked right into this image.
- Store in Azure Compute Gallery: Your Packer pipeline publishes this versioned image to an Azure Compute Gallery (formerly Shared Image Gallery).
- Deploy with Terraform: Your Terraform code becomes incredibly simple. Instead of dealing with extensions and configurations, it just deploys a new `azurerm_windows_virtual_machine` using your golden image from the gallery as its source.
# Terraform just points to the pre-built, configured image
source_image_id = "/subscriptions/your-sub-id/resourceGroups/rg-images/providers/Microsoft.Compute/galleries/MyComputeGallery/images/avd-win11-multisession-22h2/versions/1.0.2"
The Upside: This is the most reliable and fastest method for deployment at scale. It decouples application/OS configuration from infrastructure provisioning. Your deployments are predictable because you’re just stamping out copies of a known-good state.
Which Path Should You Choose?
To make it simple, here’s how I see it:
| Solution | Best For | Pros | Cons |
| 1. The Quick Fix | Emergency fixes; small or temporary environments. | Fast to implement; contained within Terraform. | Brittle; creates technical debt; not idempotent. |
| 2. The ‘Right Way’ | Most standard production environments. | Declarative; reliable; uses platform features correctly. | Requires configuring Azure AD/Intune outside of your TF code. |
| 3. The Golden Image | Large-scale, enterprise-grade, or regulated environments. | Fastest deployments; highly consistent and reliable. | Higher upfront investment in building the image pipeline. |
There’s no one “perfect” answer, only the best answer for your situation. My advice? Get yourself out of trouble with Solution 1 if you must, but immediately start planning your move to Solution 2. And if your AVD fleet is going to be a core part of your infrastructure, investing in a golden image pipeline (Solution 3) will pay for itself a dozen times over. Good luck out there.
🤖 Frequently Asked Questions
❓ Why do AVD multi-session hosts fail to enroll in Intune automatically with Terraform?
Standard Terraform provisioning for `azurerm_windows_virtual_machine` often fails to trigger MDM enrollment for multi-session hosts because the system identity created during the build does not satisfy the user-triggered requirement for automatic enrollment policies in Azure AD.
❓ How do the different Intune enrollment solutions for AVD multi-session hosts compare?
The ‘Quick Fix’ (Custom Script Extension) is fast but brittle and creates technical debt. The ‘Right Way’ (Dynamic AAD Group + Intune Policy) is declarative, reliable, and uses platform features correctly for most production. The ‘Golden Image’ approach (Packer + Azure Compute Gallery) offers the highest consistency and speed for enterprise scale but requires more upfront investment in pipeline setup.
❓ What is a common implementation pitfall when using the quick fix for AVD Intune enrollment?
The ‘Quick Fix’ using a `CustomScriptExtension` to invoke `deviceenroller.exe` is reactive and can become brittle. It fixes the symptom, not the cause, and may fail silently if underlying Azure timing or permissions change, leading to unmanaged endpoints. It should be used as a temporary measure while planning a more robust policy-driven solution.
Leave a Reply