Assigning users or groups to Azure Virtual Desktop application groups should be simple. In Terraform, it's surprisingly tricky.
The Resource
resource "azurerm_virtual_desktop_application_group" "desktop" {
name = "ag-desktop"
location = azurerm_resource_group.this.location
resource_group_name = azurerm_resource_group.this.name
type = "Desktop"
host_pool_id = azurerm_virtual_desktop_host_pool.this.id
}
resource "azurerm_role_assignment" "avd_users" {
scope = azurerm_virtual_desktop_application_group.desktop.id
role_definition_name = "Desktop Virtualization User"
principal_id = data.azuread_group.avd_users.object_id
}
Wait - that's a role assignment, not an application group assignment. What?
The Confusion
Azure Virtual Desktop has two concepts:
- RBAC role assignments - Who can use the application group
- Application group assignments - (Legacy) Direct user/group assignments
The modern approach uses RBAC. The Desktop Virtualization User role grants access to use the application group.
Getting the Azure AD Group
data "azuread_group" "avd_users" {
display_name = "AVD-Users"
security_enabled = true
}
You need the azuread provider:
terraform {
required_providers {
azurerm = {
source = "hashicorp/azurerm"
version = "~> 3.80"
}
azuread = {
source = "hashicorp/azuread"
version = "~> 2.45"
}
}
}
provider "azuread" {
tenant_id = var.tenant_id
}
Multiple Groups
Assign multiple groups using for_each:
variable "avd_user_groups" {
type = list(string)
default = ["AVD-Users", "AVD-Admins", "Remote-Workers"]
}
data "azuread_group" "avd_groups" {
for_each = toset(var.avd_user_groups)
display_name = each.value
security_enabled = true
}
resource "azurerm_role_assignment" "avd_access" {
for_each = data.azuread_group.avd_groups
scope = azurerm_virtual_desktop_application_group.desktop.id
role_definition_name = "Desktop Virtualization User"
principal_id = each.value.object_id
}
RemoteApp Application Groups
For RemoteApp (published applications):
resource "azurerm_virtual_desktop_application_group" "remoteapp" {
name = "ag-apps"
location = azurerm_resource_group.this.location
resource_group_name = azurerm_resource_group.this.name
type = "RemoteApp"
host_pool_id = azurerm_virtual_desktop_host_pool.this.id
}
resource "azurerm_virtual_desktop_application" "word" {
name = "Word"
application_group_id = azurerm_virtual_desktop_application_group.remoteapp.id
friendly_name = "Microsoft Word"
path = "C:\\Program Files\\Microsoft Office\\root\\Office16\\WINWORD.EXE"
command_line_argument_policy = "DoNotAllow"
show_in_portal = true
}
Workspace Association
Don't forget to associate application groups with a workspace:
resource "azurerm_virtual_desktop_workspace" "this" {
name = "ws-avd"
location = azurerm_resource_group.this.location
resource_group_name = azurerm_resource_group.this.name
}
resource "azurerm_virtual_desktop_workspace_application_group_association" "desktop" {
workspace_id = azurerm_virtual_desktop_workspace.this.id
application_group_id = azurerm_virtual_desktop_application_group.desktop.id
}
Common Issues
"Principal does not exist" - The Azure AD group doesn't exist or you don't have permission to read it. Check azuread provider authentication.
"Role assignment already exists" - Use lifecycle { ignore_changes = [principal_id] } if managing assignments outside Terraform too.
Changes not taking effect - Users may need to sign out and back in. Check the Windows Remote Desktop client for updates.
Need help deploying Azure Virtual Desktop? Get in touch - we help organisations implement secure remote desktop solutions.