Deploy Private Endpoints for Azure Virtual Desktop with Terraform

Hello and welcome to another Azure Virtual Desktop with Terraform blog post. In this blog I’ll show you how you can automate the deployment of private endpoints for AVD.

Networking and security are 2 very important components in Azure. By default, the Azure Virtual Desktop is available through the internet. With the option to use private endpoints for Azure Virtual Desktop that is currently in public preview, you can limit the access to your host pool.

To learn more about his feature, check the doc’s page here

Important to use the latest Azurerm or the custom interface name won’t work.

terraform {
  required_providers {
    azurerm = {
      source = "hashicorp/azurerm"
      version = "=3.34.0"
    }
  }
}

Prerequisite

Before you can use this feature, you have to enable it. Go to your subscription and select Preview Features in the left blade. Search for Private and select the correct feature and register.

DNS prerequisite

You need to have a DNS zone for the private endpoint to work. You can host the zone on your own domain controller, or you can create a Private DNS Zone in Azure.

In this blog I’ll show how to use a Private DNS zone in Azure.

resource "azurerm_private_dns_zone" "avd" {
  provider = azurerm.hub
  name ="privatelink.wvd.microsoft.com"
  resource_group_name = data.azurerm_virtual_network.avd-vnet.resource_group_name
      tags = {
    "Location" = "We"
    "Costcenter" = "IT"
    "Purpose" = "AVD Private DNS Zone"
    "Environment" = "Prd"
  }
}

Before you can resolve any DNS records in the Private DNS zone, you need to link it to your virtual network.

resource "azurerm_private_dns_zone_virtual_network_link" "avd-dns-vnet-link" {
  provider = azurerm.hub
  name = "link-privatelink.wvd.microsoft.com-vnet-prd-jvn-avd-we-01"
  private_dns_zone_name = azurerm_private_dns_zone.avd.name
  virtual_network_id = data.azurerm_virtual_network.avd-vnet.id
  resource_group_name = "rg-prd-jvn-avd-networking-01"
  
  depends_on = [azurerm_private_dns_zone.avd]
}

Subnet for private endpoints

Because structure is very important in Azure, I don’t want to have the private endpoints in the same subnet as my session hosts. For this reason, I create an extra subnet for the private endpoints.

Be aware to scope the subnet large enough because these are all the entries that will be created.

Private Endpoints deployment

When you deploy the private endpoints through the Azure portal, you see that for host pool there is only 1 sub resource. For Workspace you have 2 sub resources. This means we need 3 private endpoints.

Important to know is that since Octobre 2022 you can use a parameter called “custom_network_interface_name”. This will help you to comply with your company’s naming convention. General availability: Custom network interface name configurations of private endpoints | Azure updates | Microsoft Azure

Host pool private endpoint

resource "azurerm_private_endpoint" "hostpool" {
  name                = "pe-01-hp-prd-jvn-avd-we-01"
  location            = data.azurerm_resource_group.rg-backplane.location
  resource_group_name = data.azurerm_resource_group.rg-backplane.name
  subnet_id           = data.azurerm_subnet.avd-privatelink.id
  custom_network_interface_name = "nic-01-pe-01-hp-prd-jvn-avd-we-01"
   private_dns_zone_group {
    name = "privatelink.wvd.microsoft.com"
    private_dns_zone_ids = [azurerm_private_dns_zone.avd.id]

  }
    tags = {
    "Location" = "We"
    "Costcenter" = "IT"
    "Purpose" = "AVD Host Pool Private Endpoint"
    "Environment" = "Prd"
  }
  private_service_connection {
    name = "nic-01-pe-01-hp-prd-jvn-avd-we-01"
    private_connection_resource_id = azurerm_virtual_desktop_host_pool.hp.id
    is_manual_connection           = false
    subresource_names = ["connection"]
  }
  depends_on = [azurerm_virtual_desktop_host_pool.hp]
}

Workspace private endpoints

For the workspace you need 2 private endpoints. One for the “feed” sub resource and one for the “global” sub resource.

resource "azurerm_private_endpoint" "workspace-feed" {
  name                = "pe-01-ws-prd-jvn-avd-we-01"
  location            = data.azurerm_resource_group.rg-backplane.location
  resource_group_name = data.azurerm_resource_group.rg-backplane.name
  subnet_id           = data.azurerm_subnet.avd-privatelink.id
  custom_network_interface_name = "nic-01-01-pe-01-ws-prd-jvn-avd-we-01"
  private_dns_zone_group {
    name = "privatelink.wvd.microsoft.com"
    private_dns_zone_ids = [azurerm_private_dns_zone.avd.id]

  }
  tags = {
    "Location" = "We"
    "Costcenter" = "IT"
    "Purpose" = "AVD Workspace Private Endpoint"
    "Environment" = "Prd"
  }
  private_service_connection {
    name =  "nic-01-pe-01-ws-prd-jvn-avd-we-01"
    private_connection_resource_id = azurerm_virtual_desktop_workspace.ws.id
    is_manual_connection           = false
    subresource_names = ["feed"]
  }
  depends_on = [azurerm_virtual_desktop_workspace.ws]
}
resource "azurerm_private_endpoint" "workspace-global" {
  name                = "pe-02-ws-prd-jvn-avd-we-01"
  location            = data.azurerm_resource_group.rg-backplane.location
  resource_group_name = data.azurerm_resource_group.rg-backplane.name
  subnet_id           = data.azurerm_subnet.avd-privatelink.id
  custom_network_interface_name = "nic-02-pe-02-ws-prd-jvn-avd-we-01"
  private_dns_zone_group {
    name = "privatelink.wvd.microsoft.com"
    private_dns_zone_ids = [azurerm_private_dns_zone.avd.id]

  }
  tags = {
    "Location" = "We"
    "Costcenter" = "IT"
    "Purpose" = "AVD Workspace Private Endpoint"
    "Environment" = "Prd"
  }
  private_service_connection {
    name = "nic-02-pe-02-ws-prd-jvn-avd-we-01"
    private_connection_resource_id = azurerm_virtual_desktop_workspace.ws.id
    is_manual_connection           = false
    subresource_names = ["global"]
    
  }
  depends_on = [azurerm_virtual_desktop_workspace.ws]
}

When all the private endpoints have been deployed you can see them in the Private Link Center.

Deny public traffic

After you have enabled the private endpoints it’s important to deny the access to the host pool and workspace from the public network.

This concludes this blog post about enabling private endpoints for AVD. With this feature you can make sure that no public access is possible for your AVD environment.

As always, all the code can be found on my Github

I hope this blog post is helpful for you. If you have any questions about his, you can contact me on my socials.

3 thoughts on “Deploy Private Endpoints for Azure Virtual Desktop with Terraform

Leave a Reply

Your email address will not be published. Required fields are marked *