You are on page 1of 15
7128122, 908 PM Deploy Azure Vitual Desktop (AVD) Using Terraform and Azure Active Directory Domain Services (ADDS) > |Search... =B¢ Deploy Azure Virtual Desktop (AVD) Using Terraform and Azure Active Directory Domain Services (AADDS) 2022-02-27 taadds #avd f#azure #azure-active-directory-domain-services Hazure-virtual-desktop #iac #infrastructure-as-code #terraform With Azure Virtual Desktop (AVD) 7, you can deliver secure Windows 11 desktops and > When you participate in the comments, a cookie is used . ; Got it! to keep you logged in. hitpssschnerring neublogideploy-azure-vitual-dosktop-avd.tsng-te-raform-and-azure-active-direclory-domain-services-aadds! 46 712812, 908 PM Deploy Azure Vitus Desktop (AVD) Using Terraform and Azure Active Directory Domain Services (AADDS) Windows 11 multi-session licensing, This tutorial will guide you through setting up AVD with AADDS using Terraform. As always, all the code is available on my GitHub 7. Prerequisites Besides an active Azure subscription and Terraform 7 configured on your workstation, Azure Active Directory Domain Services (AADDS) 7 are required. Check out my previous post on setting up AADDS with Terraform if you haven't already! Some ‘Terraform resources in this guide, e.g,, the network peerings and AADDS domain-join (AADDS-join) VM extension, depend on the AADDS resources from that post. Do You Know What’s Exciting? It's possible to just Azure AD-join (AAD-join) AVD session hosts /, eliminating the requirement to use AADDS or on-premise AD DS and reduce the costs and complexity of AVD deployments even more. Unfortunately, it's not yet fully production-ready because FSLogix profile support for AAD-joined AVD VMs is only in public preview /. Currently, using AAD authentication with Azure Files still requires hybrid identities 7. But it's nice that AVD is one step closer to being a cloud-only solution. I can't wait to terraformify all of it! Stay tuned because I'll post about it as soon as things are generally available. Overview We'll deploy AADDS and AVD resources to separate virtual networks and resource groups. It is called a hub-spoke network topology 7, a typical approach to organize large-scale networks, The hub (aadds-vnet ), the central connectivity point, typically contains other services besides AADDS. Eg,,a VPN gateway 7 connecting your on- premises network to the Azure cloud. Azure Bastion 7 or Azure Firewall 7 are also services that might reside in the hub network. Spoke networks (avd-vnet ) contain > When you participate in the comments, a cookie is used . Got it! to keep you logged in. hitpssschnerring neublogideploy-azure-vitual-dosKtop-avd.tsng-te-raform-and-azure-active-direclory-domain-services-aadds! 216 7128122, 908 PM Deploy Azure Vitual Desktop (AVD) Using Terraform and Azure Retive Directory Domain Services (ADDS) Create the avd-rg resource group and add the avd-vnet spoke network to it. The network uses the AADDS domain controllers (DCs) as dns_servers resource “azurerm_resource_group" "avd" { name avd-rg” location ‘Switzerland North" } # Network Resources resource “azurerm_yvirtual_network" "avd" { name = “avd-vnet™ location azurerm_resource_group.avd. location resource_group_name = azurerm_resource_group.avd.name address_space = ["10.10.0.0/16"] dns_servers = azurerm_active_directory_domain_service.aadds.in } resource “azurerm_subnet" "avd" { “avd-snet” azurerm_resource_group.avd.name azurerm_virtual_network.avd.name ["10.10.0.0/24"] name resource_group_name virtual_network_name address_prefixes To give AVD VMs line of sight of AADDS, we need to add the following network peerings: resource “azurerm_virtual_network_peering" "aadds_to_avd" { name = "hub-to-avd-peer” azurerm_resource_group.aadds name resource_group_name virtual_network_name azurerm_virtual_network.aadds.name remote_virtual_network_id = azurerm_virtual_network.avd.id > When you participate in the comments, a cookie is used to keep you logged in. hitpssschnerring neublogideploy-azure-vitual-dosKtop-avd.tsng-te-raform-and-azure-active-direclory-domain-services-aadds! Got it! 36 7128722, 908 PM Deploy Azure Vitual Desktop (AVD) Using Terraform and Azure Retive Directory Domain Services (ADDS) virtual_network_name azurerm_virtual_network.avd.name remote_virtual_network_id azurerm_virtual_network.aadds.id Host Pool A host pool 7 is a collection of Azure virtual machines that register to Azure Virtual Desktop as session hosts when you run the Azure Virtual Desktop agent. All session host virtual machines in a host pool should be sourced from the same image for a consistent user experience We add the AVD host pool and the registration info. We'll later register the session hosts via VM extension to the host pool using the token from the registration info: locals { # Switzerland North is not supported avd_location = “West Europe" + resource “azurerm_virtual_desktop_host_pool” "avd" { name avd-vdpool" location local.avd_location resource_group_name = azurerm_resource_group.avd.name type = "Pooled" load_balancer_type = "BreadthFirst” friendly_name "AVD Host Pool using ADDS” } resource “time_rotating" “avd_registration_expiration" { # Must be between 1 hour and 3@ days rotation_days = 29 > When you participate in the comments, a cookie is used . Got it! to keep you logged in. hitpssschnerring neublogideploy-azure-vitual-dosKtop-avd.tsng-te-raform-and-azure-active-direclory-domain-services-aadds! ans. 7128722, 908 PM Deploy Azure Vitual Desktop (AVD) Using Terraform and Azure Retive Directory Domain Services (ADDS) expiration_date = time_rotating.avd_registration_expiration.rotation_r Ideploy my AADDS and AVD resources to the Switzerland North region, However, Ihave to deploy AVD service resources to West Europe because the AVD service isn't available in all regions 7 To get the latest supported regions, re-register the AVD resource provider 7: 1 Select your subscription under Subscriptions in the Azure Portal 2. Select the Resource Provider menu. 3. Re-register Microsoft .DesktopVirtualization. Workspace and App Group Next, we create a workspace / and add an app group 7. Two types of app groups exist * Desktop : full desktop © RemoteApp : individual apps Adding the following gives AVD users the full desktop experience: resource “azurerm_virtual_desktop_workspace” "avd" { name avd-vdws' location = local.avd_location resource_group_name = azurerm_resource_group.avd. name resource “azurerm_virtual_desktop_application_group" "avd" { name ‘desktop-vdag" location = local.avd_location resource_group_name = azurerm_resource_group.avd.name type “Desktop” host_pool_id = azurenm_virtual_desktop_host_pool.avd.id > When you participate in the comments, a cookie is used . Got it! to keep you logged in. workspace_1a = azurerm_virtual_gesktop_workspace.ava.1a hitpsischnerring neublogideploy-azure-vitual-dosktop-avd.tsing-t-raform-and-azure-active-direclory-domain-services-aadds! 55 7128122, 908 PM Deploy Azure Vitual Desktop (AVD) Using Terraform and Azure Retive Directory Domain Services (ADDS) application_group_id = azurerm_virtual_desktop_application_group.avd. is Session Hosts Let's add two session hosts to the AVD host pool. To be able to adjust the amount of VMs inside the host pool later, we define a variable: variable “avd_host_pool_size” { type number description = "Number of session hosts to add to the AVD host pool. Next, we add the VM NICs for the session hosts: resource “azurerm_network_interface" "avd" { count = var.avd_host_pool_size name avd-nic-${count.index}" location azurerm_resource_group.avd. location resource_group_name = azurerm_resource_group.avd.name ip_configuration { name avd-ipcon#" subnet_id azurerm_subnet.avd.id private_ip_address_allocation = "Dynamic" After, we add the session hosts: resource "random_password" “avd_local_admin" { length = 64 > When you participate in the comments, a cookie is used . Got it! to keep you logged in. oyte_sengtn = 4 hitpssschnerting neublogideploy-azure-vitual-dosktop-avd.ssing-te-raform-and-azure-active-direclory-domain-services-aadds! ens 7128122, 908 PM Deploy Azure Vitual Desktop (AVD) Using Terraform and Azure Retive Directory Domain Services (ADDS) } resource “azurerm_windows_virtual_machine" "avd" { count Length (random_id.avd) name = “avd-vm-${count. index}-${random_id.avd[-count. ind location = azurerm_resource_group.avd.location resource_group_name = azurerm_resource_group.avd.name size license_type admin_username admin_password network_interface_ids "Standard_D4s_v4" Windows_Client” "avd-local-admin" random_password.avd_local_admin.result [azurerm_network_interface.avd[count.index].id os_disk { caching “Readwrite” storage_account_type = "Premium_LRS" } source_image_reference { publisher = “MicrosoftWindowsDesktop" offer “windows-11" sku “winl1-21h2-avd" version = “latest” To ensure the session hosts utilize the licensing benefits available with AVD 7, we select Windows_Client as License_type value. ‘The reason we append a random number to the VM name is to prevent name conflicts with dangling host pool registrations 7 Understanding VM Extensions > When you participate in the comments, a cookie is used . Got it! to keep you logged in. hitpssschnerring neublogideploy-azure-vitual-dosKtop-avd.tsng-te-raform-and-azure-active-direclory-domain-services-aadds! m6 rn8z2, 908 Pet Deploy Azur Vial Desktop (AVD) Using Teraorm and Azure Active Directory Domain Services (AADOS) Sometimes, creating complex deployments via Azure Portal feels like magic. Backtracking the generated ARM templates is something I like to do to get a deeper understanding of what's happening under the hood. It's usually my initial step when trying to terraformify something for the first time that I can't find good examples of elsewhere. You can find the AVD ARM templates on official Azure GitHub github.com/Azure/RDS- ‘Templates/ARM-wvd-templates 7. The VM templates reside in the nestedtemplates directory containing the VM extension resources that we want to replicate with Terraform 7: “apiVersion": "2018-10-01", "type": "Microsoft.Compute/virtualMachines/extensions", name": “[concat(parameters('rdshPrefix'), add(copyindex(), parameters location": "[parameters('location')]", “dependsOn": [ "rdsh-vm-loop" ], "copy": { "name": “rdsh-dsc-loop", [parameters('rdshNumberOfInstances')]" "type": "DSC", "typeHandlerVersion": "2.73", "autoUpgradeMinorVersion": true, "settings": { “modulesur1" "[parameters('artifactsLocation')]", “configurationFunction": "Configuration.ps1\\AddSessionHost", “properties”: { hostPoo1Nam [parameters('hostpoolName')]", “registrationInfoToken": "[parameters('hostpoolToken')]", "aadJoin": "[parameters(‘aadJoin')]", “sessionHostConfigurationLastUpdateTime": "[parameters('SessionH > When you participate in the comments, a cookie is used . Got it! to keep you logged in. hitpssschnerring neublogideploy-azure-vitual-dosKtop-avd.tsng-te-raform-and-azure-active-direclory-domain-services-aadds! ans 7128122, 908 PM Deploy Azure Vitual Desktop (AVD) Using Terraform and Azure Retive Directory Domain Services (ADDS) condition”: "[not(parameters('aadJoin'))]", ‘apiVersion": "2018-10-21", "type": "Microsoft. Compute/virtualMachines/extensions", name": “[concat(parameters('rdshPrefix'), add(copyindex(), parameters location": "[parameters(*location’)]", “dependsOn": [ "rdsh-dsc-loop" ], "copy": { “rdsh-domain-join-loop", "[parameters('rdshNumberOfInstances')]" "properties": { "publisher": “Microsoft.Compute", "JsonADDomainExtension", "typeHandlerVersion": "1.3", "autoUpgradeMinorVersion": true, “settings”: ( “name": "[variables(‘domain')]", “ouPath": "[parameters('ouPath')]", "user": " [parameters('administratorAccountUsername')]", “restart! “options": ds “protectedSettings": { “password” [parameters (‘administratorAccountPassword')]" y hb However, the default parameters of the ARM template downloaded from the Azure Portal differ from the values found on GitHub, e.g, modulesParameter: © GitHub: https: //raw.githubusercontent.com/Azure/RDS- Templates/master/ARM-wvd-templates/DSC/Configuration.zip © Azure: https: //wvdportalstorageblob.blob.core.windows .net/galleryartif > When you participate in the comments, a cookie is used Got it! to keep you logged in. hitpssschnerring neublogideploy-azure-vitual-dosKtop-avd.tsng-te-raform-and-azure-active-direclory-domain-services-aadds! ons 712812, 908 PM Deploy Azure Vitus Desktop (AVD) Using Terraform and Azure Active Directory Domain Services (AADDS) peek inside the container, we can use the List Blobs operation of the Blob Service REST API. 7 ‘The URLs that the Azure Portal uses sometimes change. At the time of writing, it uses the Configuration_01-20-2022.zip file despite Configuration_02-23- 2022. zip being available. AADDS-join the VMs When AADDS-joining a computer, it will be added to the built-in AADDS Computers Organizational Unit (OU) 7 of the domain by default. To add the VM to a different OU, we can optionally specify the OU path during domain-join. Create an optional variable: variable “avd_ou_path" { type string description ‘OU path used to AADDS domain-join AVD session hosts default We then AADDS-join the session hosts with the JsonADDomainExtension VM extension: resource “azurerm_virtual_machine_extension" “avd_aadds_join" { count = length(azurerm_windows_virtual_machine.avi name = “aadds-join-vmext" virtual_machine_id azurerm_windows_virtual_machine.avd[count publisher = "Microsoft Compute” type "JsonADDomainExtension” type_handler_version auto_upgrade_minor_version settings ~ <<-SETTINGS i > When you participate in the comments, a cookie is used Got it! to keep you logged in. hitpssschnerring neublogideploy-azure-vitual-dosKtop-avd.tsng-te-raform-and-azure-active-direclory-domain-services-aadds! 1015 7128722, 908 PM Deploy Azure Vitual Desktop (AVD) Using Terraform and Azure Retive Directory Domain Services (ADDS) “Options”: "3" } SETTINGS protected_settings = <<-PROTECTED_SETTINGS { “password”: "${random_password.dc_admin.result}" } PROTECTED_SETTINGS lifecycle { ignore_changes = [settings, protected_settings] depends_on = [ azurerm_virtual_network_peering.aadds_to_avd, azurerm_virtual_network_peering.avd_to_aadds We have to ensure that the session hosts have line of sight to the AADDS DCs. To do that, we add the network peering resources to the depends_on list of the VM extension. After a VM has been AADDS-joined, it doesn't make sense to join it again when the settings or protected_settings of the VM extension change, so we ignore_changes of these properties Register VMs to the Host Pool First, let's add a variable containing the URL to the zip file containing the DSC configuration, making it easier to update it in the future: variable "avd_register_session_host_modules_url" { > When you participate in the comments, a cookie is used Got it! to keep you logged in. hitpssschnerring neublogideploy-azure-vitual-dosKtop-avd.tsng-te-raform-and-azure-active-direclory-domain-services-aadds! ns 7128122, 908 PM Deploy Azure Vitual Desktop (AVD) Using Terraform and Azure Retive Directory Domain Services (ADDS) Then, we register the session hosts to the host pool with the DSC VM extension: resource “azurerm_virtual_machine_extension" "avd_register_session_host" length (azurerm_windows_virtual_machine.avd) count name egister-session-host-vmext" virtual_machine_id = azurerm_windows_virtual_machine.avd[count. index publisher \icrosoft Powershell” type = "psc" type_handler_version -73" settings = <<-SETTINGS { “modulesUrl": "${var.avd_register_session_host_modules_url}", “configurationFunction": "Configuration.ps1\\AddSessionHost", “properties”: { "hostPoolName": "${azurerm_virtual_desktop_host_pool.avd.name}", "aadJoin": false + + SETTINGS protected_settings = <<-PROTECTED_SETTINGS { “properties”: { "registrationInfoToken": "${azurerm_virtual_desktop_host_pool_re; } PROTECTED_SETTINGS lifecycle { ignore_changes = [settings, protected_settings] y depends_on = [azurerm_virtual_machine_extension.avd_aadds_join] Js > When you participate in the comments, a cookie is used . Got it! to keep you logged in. pepe hitpssschnerring neublogideploy-azure-vitual-dosKtop-avd.tsng-te-raform-and-azure-active-direclory-domain-services-aadds! 126 7128722, 908 PM Deploy Azure Vital Desktop (AVD) Using Terraform and Azure Retive Directory Domain Services (ADDS) Role-based Access Control (RBAC) Let's create a group in AAD that authorizes its members to access the AVD application group we created earlier, To do so, we create a group and assign the AAD built-in Desktop Virtualization User role tot: data “azurerm_role_definition" "desktop_virtualization_user” { name = “Desktop Virtualization User" resource “azuread_group" "avd_users” { display_name = “AVD Users" security_enabled = true resource “azurerm_role_assignment" “avd_users_desktop_virtualization_use scope = azurerm_virtual_desktop_application_group.avd.id role_definition_id = data.azurerm_role_definition.desktop_virtualizati: principal_id = azuread_group.avd_users.id Assuming that we want to authorize users that already exist within our AAD, we create a variable containing the UPNs of these users: variable “avd_user_upns" { type list (string) description = “List of user UPNs authorized to access AVD." default a We are able then query those users with Terraform and add them to the group like this: > When you participate in the comments, a cookie is used . Got it! to keep you logged in. hitpssschnerring neublogideploy-azure-vitual-dosKtop-avd.tsng-te-raform-and-azure-active-direclory-domain-services-aadds! 1316 712812, 908 PM Deploy Azure Vitus Desktop (AVD) Using Terraform and Azure Active Directory Domain Services (AADDS) resource “ for_each group_object_id member_object_id } zuread_group_member" “avd_users" { data.azuread_user.avd_users azuread_group.avd_users. id each.value.id What’s Next? Great! We successfully created an AVD environment with Terraform. Test it by logging into one of the available AVD clients 7. Tl write about creating custom AVD images with Packer 7 next and follow it up by showing you how to configure FSLogix user profiles 7 on your AADDS-joined AVD session hosts. Stay tuned! Sharethispos: W ff} @ © > When you participate in the comments, a cookie is used Got it! to keep you logged in. hitpssschnerring neublogideploy-azure-vitual-dosKtop-avd.tsng-te-raform-and-azure-active-direclory-domain-services-aadds! 1416 7128722, 908 PM Deploy Azure Vitual Desktop (AVD) Using Terraform and Azure Retive Directory Domain Services (ADDS) MBI 6O® Your comment here Styling with Markdown is supported Sort by Recently updated v IM jgm 5/9/2022 at 5:11 PM 0 Hello Michael, Thanks for your article, Do you Know how to put the session host in Drain mode and delete the session host with terraform, when you deploy new Virtual Machines with a new image. Thanks Reply A Michael Schnerring —_ 6/9/2022 at 4:09 AM 0 I think this isn't possible with pure Terraform. I'd go about it this way: 1. Add patched session hosts via Terraform 2. Put the old session hosts into drain mode via Azure Portal or CLI 3. After you've ensured all users logged off, remove the old session hosts via Terraform Step 1 causes temporary code duplication, so it might be helpful to make the session host configuration reusable by modularizing it. Reply Powered by Remark42 © 2020 Michael Schnerring > When you participate in the comments, a cookie is used . Got it! to keep you logged in. hitpssschnerring neublogideploy-azure-vitual-dosKtop-avd.tsng-te-raform-and-azure-active-direclory-domain-services-aadds! 1915

You might also like