Azure Virtual Machines (VMs) are a powerful tool for running applications, hosting desktops, and performing various tasks in the cloud. However, the cost of running VMs can add up quickly, especially if they are left running when not in use. Microsoft has introduced a new feature called VM Hibernation, which allows you to save costs by hibernating your VMs when they are not needed. In this blog post, we will explore the benefits of VM Hibernation and how you can use it to optimize your Azure costs.
What is VM Hibernation
VM Hibernation is a cost-saving feature that allows you to deallocate a VM while preserving its in-memory state. When a VM is hibernated, you don’t pay for the compute costs associated with the VM. Instead, you only pay for the storage and networking resources associated with the VM. This means you can save a significant amount of money on your Azure bill by hibernating VMs when they are not in use. Obviously this wont work on its own you will have to intergrate this further with Scaling Plans & Azure Automation.
Use Cases for VM Hibernation
Category
Description
Virtual Desktops
If you use Azure Virtual Desktop to provide virtual desktops (Personal Only) to your employees, you can use VM Hibernation to save costs during non-business hours. By hibernating the VMs after business hours and resuming them the next morning, you can avoid paying for compute resources when they are not needed.
Dev/Test Environments
If you have development or testing environments that are not used 24/7, you can use VM Hibernation to save costs. By hibernating the VMs when they are not in use, you can avoid paying for compute resources that are not needed.
Prewarmed VMs
If you have applications that have long initialization times due to memory components, you can use VM Hibernation to save costs. By bringing up the apps and hibernating the VMs, you can quickly start the “prewarmed” VMs when needed, with the applications up and running in the desired state.
How to Enable Hibernation
Enabling hibernation is straightforward and can be done using various tools like Azure Portal, PowerShell, CLI, ARM, SDKs, and APIs. etc. I will be demonstrating within the Azure Portal:
Create a Host Pool – Select Personal
Under the Host Pool creation ensure you have Personal selected as this doesn’t work for Pooled
Under Host Pools –> Virtual Machine –> Select Hibernate
To take full advantage of VM Hibernation, you can configure scaling plans for your VMs. Scaling plans allow you to automatically hibernate VMs based on a schedule or based on user activity.
Start VM on Connect – Ensure that is “Yes“
Configure Hibernation Settings
Define hibernation after a user session disconnects or logs off for a configurable period.
Assign the Scaling Plan
Apply the scaling plan to one or more personal host pools.
Reference Links
Following are the list of helpful links:
Description
Links
Hibernation support now available for Azure Virtual Desktop
VM Hibernation is a powerful cost-saving feature that can help you optimize your Azure costs. By hibernating VMs when they are not in use, you can save a significant amount of money on your Azure bill. Whether you are using VMs for virtual desktops, dev/test environments, or prewarmed VMs, VM Hibernation can help you save costs without sacrificing performance or availability. Do give it a try in your enivornment and see how much you can save?
Recently the Apps on demand was released, essentially this an Azure market place offering from VMware aka Broadcom. You can deploy App Volumes manager virtual machine that runs Windows Server 2022 with App Volumes Manager pre-installed. Additionally, deploy Azure file share and database configuration.
What is an AppStack
An AppStack in VMware App Volumes is a virtual container that contains a set of applications packaged together. It’s used in virtual desktop environments such as (AVD and Windows 365) to dynamically deliver these applications to users. AppStacks are read-only, can be attached to user sessions transparently, and appear as if the applications are natively installed. They offer efficient application management, allowing for easy updates and maintenance without impacting the underlying system. This approach simplifies application lifecycle management and enhances user experience in virtualized desktop scenarios.
Prerequisites
You’ll need the following things ready before you can rollout App Volumes:
Azure Subscription: Have an active Microsoft Azure subscription. Azure Documentation
Azure Permissions: Ensure permissions to create virtual machines for App Volumes Manager, storage accounts, and file shares on Azure.
Access to On-Prem Active Directory: Required for identity and access control.
Azure Virtual Desktop Access: For remote connectivity.
Azure AD Connect: Install Azure AD Connect on the Active Directory Domain Controller.
Note: Microsoft Entra ID (Azure Active Directory) is not supported.
App Volumes License File: Download and install the App Volumes license file. App Volumes in Azure follows a Bring Your Own License model. VMware App Volumes Product Download Page
SQL Server Database for Production: For a production environment, ensure the availability of an existing SQL server database, as the default SQL Server Express Database is not recommended for production use.
My party came crashing on the requirement of Active Directory (AD) Domain Controller. In my entire Azure, Azure Virtual Desktop, Windows 365 Cloud PC and Microsoft Intune I have made deliberate choice to keep it with mordern management\authentication and follow the Microsoft best practice guidance. Though I am not able to complete the entire configurations due to AD I decided to share whatever configurations I manage to perform to deploy the AV Manager appliance within my Azure subscription for this blog post.
Starting in the Azure Portal
Access the Marketplace: Begin by navigating to the Microsoft Azure portal and clicking on ‘Marketplace’.
Find VMware App Volumes: Search for the ‘VMware App Volumes’ offer and click on it.
Select App Volumes Version: In the VMware App Volumes Azure Application page, choose the desired version from the Plan drop-down box.
Click ‘Create’
Deploy the Virtual Machine Appliance
Details: Select your Subscription and Resource group. You can also create a new resource group if needed.
Instance Details: Choose the Region and enter the name for your virtual machine. Set up the credentials for the local administrator. (#TIP – Ensure you deploy the Appliance where the session host pools are located)
Public IP Address: A new public IP address is created by default, but you can opt for an existing one or none at all. (#TIP – This allows accessing the App Volumes Manager over the internet )
DNS Prefix: If using a public IP address, consider creating a DNS prefix for easier access. (#TIP – Pick a friendly name I decided to leave it as defaults)
By default, a new virtual network and subnet are created. However, in my situation, I want to leverage the existing VNET and Subnet.
Database Selection: Choose between a Local SQL Server Express Database (not recommended for production) or a Remote SQL Server database. Enter the necessary database connection details. (#TIP – Explore for production use evaluate using the Azure SQL DB as its a managed SQL instance and you will not have the overhead of managing and maintaining a SQL Server)
File Share Configuration: Decide if you want Azure Marketplace to automatically provision storage with file shares or use existing storage. Configure accordingly. (#TIP – Same if you have Azure Dell or NetApp Files storage you can leverage that or using Azure storage account)
Tags: Add any desired tags. (#TIP – Ensure you add the tags as it will help you later during Billing and Automation)
Review and Launch Deployment: Review your setting Click ‘Create’ to start the deployment process.
Navigate to App Volumes Manager Admin UI: This is where you’ll configure Active Directory and other settings.
Configure Storage: If you opted out of automatic storage provisioning, manually configure the storage in the App Volumes Manager admin UI.
When you navigate to the Storage the newly created SMB shares are listed for templates and AppStacks stroage.
I will come back to this blog post once I learn more about the “No AD” mode as this will enable me to further integrate App Volumes into my Azure Virtual Desktop and Windows 365 Cloud PCs.
Resources deployed within the Azure Resource Group
Following resources are deployed within your Azure Resource Group for App Volumes
Whislist
I would like to see the following enhacements at a later day:
VMware aka Broadcom should evlaute a complete SaaS offering taking it to the next level instead of deploying an appliance and required to do alot of configuration. Just give me “as a Service” and the only responsiblity is to create/update and mange the applications with Entra ID Groups.
Microsoft Entra ID integration is a must
I hope you will find this helpful information for getting started with App Volumes for Windows 365 Cloud PC and Azure Virtual Desktop. Please let me know if I have missed any steps or details, and I will be happy to update the post.
In today’s digital age, managing cloud resources efficiently is paramount, not just for operational efficacy but also for cost management. Enter Azure Virtual Desktop (AVD) Scaling Plans – Microsoft’s answer to dynamic and intelligent scaling of your virtual desktop infrastructure. No longer do organizations need to overprovision resources or let them sit idle; with AVD Scaling Plans, you get a responsive environment tailored to your usage patterns. In this blog post, we’ll create the scaling plans using Terraform.
In the previous blog post, we delved into the distinctions between the Personal Desktop (1:1 mapping), Pooled Desktop (1:Many mapping) and Remote App configurations, providing a comprehensive guide on their creation via Terraform. The series continues as we further explore how to create the AVD Scaling Plan for Pooled Host Pool.
Permissions within the Azure Subscription for using Terraform
Terraform – Authenticating via Service Principal & Client Secret
Before running any Terraform code, we will execute the following PowerShell (Run as administrator)and store the credentials as environment variables. If we do this via the environment variable, we don’t have to keep the below information within the providers.tf file. In a future blog post, there are better ways to store the below details, and I hope to showcase them:
Azure Subcription ID – Azure Portal Subcription copy the ID
Client ID – From the above step you will have the details
Client Secret – From the above step you will have the details
Tenant ID – While creating the Enterprise Apps in ADD you will have the details
Terraform Folder Structure
The following is the folder structure for the terrraform code:
Azure Virtual Desktop Scaling Plan – Create a directory in which the below Terraform code will be published (providers.tf, main.tf, variables.tf and output.tf)
Create a file named main.tf and insert the following code. Let me explain what all we are attempting to accomplish here:
Leverage a existing Resource Group
Leverage a existing Host Pool
Create a custom role AVD AutoScale and assign to the Resource Group
This is a prerequisite for ensuring the scaling plan can increase and decrease the resources in your resource group.
Assign the role – AVD AutoScale to the service principal (AVD)
Create a a scaling plan with a production grade schedule
Associate the scaling plan with the host pool
# Generate a random UUID for role assignment
resource "random_uuid" "example" {}
# Fetch details of the existing Azure Resource Group
data "azurerm_resource_group" "example" {
name = var.resource_group_name
}
# Fetch details of the existing Azure Virtual Desktop Host Pool
data "azurerm_virtual_desktop_host_pool" "existing" {
name = var.existing_host_pool_name
resource_group_name = var.resource_group_name
}
# Define the Azure Role Definition for AVD AutoScale
resource "azurerm_role_definition" "example" {
name = "AVD-AutoScale"
scope = data.azurerm_resource_group.example.id
description = "AVD AutoScale Role"
# Define the permissions for this role
permissions {
actions = [
# List of required permissions.
"Microsoft.Insights/eventtypes/values/read",
"Microsoft.Compute/virtualMachines/deallocate/action",
"Microsoft.Compute/virtualMachines/restart/action",
"Microsoft.Compute/virtualMachines/powerOff/action",
"Microsoft.Compute/virtualMachines/start/action",
"Microsoft.Compute/virtualMachines/read",
"Microsoft.DesktopVirtualization/hostpools/read",
"Microsoft.DesktopVirtualization/hostpools/write",
"Microsoft.DesktopVirtualization/hostpools/sessionhosts/read",
"Microsoft.DesktopVirtualization/hostpools/sessionhosts/write",
"Microsoft.DesktopVirtualization/hostpools/sessionhosts/usersessions/delete",
"Microsoft.DesktopVirtualization/hostpools/sessionhosts/usersessions/read",
"Microsoft.DesktopVirtualization/hostpools/sessionhosts/usersessions/sendMessage/action",
"Microsoft.DesktopVirtualization/hostpools/sessionhosts/usersessions/read"
]
not_actions = []
}
assignable_scopes = [
data.azurerm_resource_group.example.id,
]
}
# Fetch the Azure AD Service Principal for Windows Virtual Desktop
data "azuread_service_principal" "example" {
display_name = "Azure Virtual Desktop"
}
# Assign the role to the service principal
resource "azurerm_role_assignment" "example" {
name = random_uuid.example.result
scope = data.azurerm_resource_group.example.id
role_definition_id = azurerm_role_definition.example.role_definition_resource_id
principal_id = data.azuread_service_principal.example.id
skip_service_principal_aad_check = true
}
# Define the Azure Virtual Desktop Scaling Plan
resource "azurerm_virtual_desktop_scaling_plan" "example" {
name = var.scaling_plan_name
location = var.location
resource_group_name = var.resource_group_name
friendly_name = var.friendly_name
description = var.scaling_plan_description
time_zone = var.timezone
tags = var.tags
dynamic "schedule" {
for_each = var.schedules
content {
name = schedule.value.name
days_of_week = schedule.value.days_of_week
ramp_up_start_time = schedule.value.ramp_up_start_time
ramp_up_load_balancing_algorithm = schedule.value.ramp_up_load_balancing_algorithm
ramp_up_minimum_hosts_percent = schedule.value.ramp_up_minimum_hosts_percent
ramp_up_capacity_threshold_percent= schedule.value.ramp_up_capacity_threshold_pct
peak_start_time = schedule.value.peak_start_time
peak_load_balancing_algorithm = schedule.value.peak_load_balancing_algorithm
ramp_down_start_time = schedule.value.ramp_down_start_time
ramp_down_load_balancing_algorithm= schedule.value.ramp_down_load_balancing_algorithm
ramp_down_minimum_hosts_percent = schedule.value.ramp_down_minimum_hosts_percent
ramp_down_force_logoff_users = schedule.value.ramp_down_force_logoff_users
ramp_down_wait_time_minutes = schedule.value.ramp_down_wait_time_minutes
ramp_down_notification_message = schedule.value.ramp_down_notification_message
ramp_down_capacity_threshold_percent = schedule.value.ramp_down_capacity_threshold_pct
ramp_down_stop_hosts_when = schedule.value.ramp_down_stop_hosts_when
off_peak_start_time = schedule.value.off_peak_start_time
off_peak_load_balancing_algorithm = schedule.value.off_peak_load_balancing_algorithm
}
}
# Associate the scaling plan with the host pool
host_pool {
hostpool_id = data.azurerm_virtual_desktop_host_pool.existing.id
scaling_plan_enabled = true
}
}
Configure AVD – ScalingPlans – variables.tf
Create a file named variables.tf and insert the following code. The place where we define existing or new variables:
# Define the resource group of the Azure Virtual Desktop Scaling Plan
variable "resource_group_name" {
description = "The name of the resource group."
type = string
default = "AE-DEV-AVD-01-PO-D-RG"
}
# Define the attributes of the Azure Virtual Desktop Scaling Plan
variable "scaling_plan_name" {
description = "The name of the Scaling plan to be created."
type = string
default = "AVD-RA-HP-01-SP-01"
}
# Define the description of the scaling plan
variable "scaling_plan_description" {
description = "The description of the Scaling plan to be created."
type = string
default = "AVD Host Pool Scaling plan"
}
# Define the timezone of the Azure Virtual Desktop Scaling Plan
variable "timezone" {
description = "Scaling plan autoscaling triggers and Start/Stop actions will execute in the time zone selected."
type = string
default = "AUS Eastern Standard Time"
}
# Define the freindlyname of the Azure Virtual Desktop Scaling Plan
variable "friendly_name" {
description = "The friendly name of the Scaling plan to be created."
type = string
default = "AVD-RA-HP-SP-01"
}
# Define the host pool type(Pooled or Dedicated) of the Azure Virtual Desktop Scaling Plan
variable "host_pool_type" {
description = "The host pool type of the Scaling plan to be created."
type = string
default = "Pooled"
}
# Define the details of the scaling plan schedule
variable "schedules" {
description = "The schedules of the Scaling plan to be created."
type = list(object({
name = string
days_of_week = list(string)
ramp_up_start_time = string
ramp_up_load_balancing_algorithm = string
ramp_up_minimum_hosts_percent = number
ramp_up_capacity_threshold_pct = number
peak_start_time = string
peak_load_balancing_algorithm = string
ramp_down_start_time = string
ramp_down_load_balancing_algorithm = string
ramp_down_minimum_hosts_percent = number
ramp_down_capacity_threshold_pct = number
ramp_down_wait_time_minutes = number
ramp_down_stop_hosts_when = string
ramp_down_notification_message = string
off_peak_start_time = string
off_peak_load_balancing_algorithm = string
ramp_down_force_logoff_users = bool
}))
default = [
{
name = "weekdays_schedule"
days_of_week = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday"]
ramp_up_start_time = "08:00"
ramp_up_load_balancing_algorithm = "BreadthFirst"
ramp_up_minimum_hosts_percent = 20
ramp_up_capacity_threshold_pct = 60
peak_start_time = "09:00"
peak_load_balancing_algorithm = "DepthFirst"
ramp_down_start_time = "18:00"
ramp_down_load_balancing_algorithm = "DepthFirst"
ramp_down_minimum_hosts_percent = 10
ramp_down_capacity_threshold_pct = 90
ramp_down_wait_time_minutes = 30
ramp_down_stop_hosts_when = "ZeroActiveSessions"
ramp_down_notification_message = "You will be logged off in 30 min. Make sure to save your work."
off_peak_start_time = "20:00"
off_peak_load_balancing_algorithm = "DepthFirst"
ramp_down_force_logoff_users = false
}
]
}
# Define the location of the Azure Virtual Desktop Scaling Plan
variable "location" {
description = "The location where the resources will be deployed."
type = string
default = "australiaeast"
}
# Define the tags of the Azure Virtual Desktop Scaling Plan
variable "tags" {
description = "The tags to be assigned to the Scaling plan."
type = map(string)
default = {
"Billing" = "IT"
"Department" = "IT"
"Location" = "AUS-East"
}
}
# Define the name of the Azure Virtual Desktop Host Pool
variable "existing_host_pool_name" {
description = "The name of the existing Azure Virtual Desktop Host Pool."
type = string
default = "AE-DEV-AVD-01-PO-D-HP"
}
Configure AVD – ScalingPlans – output.tf
Create a file named output.tf and insert the following code. This will showcase in the console what is getting deployed in form of a output.
# Output the ID of the Azure Virtual Desktop Scaling Plan
output "scaling_plan_id" {
description = "The ID of the Virtual Desktop Scaling Plan."
value = azurerm_virtual_desktop_scaling_plan.example.id
}
Intialize Terraform – AVD – ScalingPlans
Run terraform init to initialize the Terraform deployment. This command downloads the Azure provider required to manage your Azure resources. (Its pulling the AzureRM and AzureAD)
terraform init -upgrade
Create Terraform Execution Plan – AVD – ScalingPlans
Run terraform plan to create an execution plan.
terraform plan -out scaleplan.tfplan
Apply Terraform Execution Plan – AVD – ScalingPlans
Run terraform apply to apply the execution plan to your cloud infrastructure.
terraform apply "scaleplan.tfplan"
Validate the Output in Azure Portal
Go to the Azure portal, Select Azure Virtual Desktop and Select Scaling Plans and validate all the details such as Host Pool Assignment and Schedule:
Clean-up the above resources (Optional)
If you want to delete all the above resources then you can use the following commands to destroy. Run terraform plan and specify the destroy flag.
terraform plan -destroy -out scaleplan.destory.tfplan
terraform apply "scaleplan.destory.tfplan"
Quick Start Links
The intention here is to get you quickly started with Terraform on Azure Virtual Desktop Solution:
Description
Links
Create an autoscale scaling plan for Azure Virtual Desktop
I hope you will find this helpful information for getting started with Terraform to deploy the Azure Virtual Desktop – Scaling Plans. Please let me know if I have missed any steps or details, and I will be happy to update the post.
In the July 2023 release for Azure Virtual Desktop, the Watermarking and Session capture protection features became generally available. Numerous blog posts already showcase how to enable the feature using Group Policy. In today’s post, I will showcase how to enable Watermarking and Session Capture protection using Microsoft Intune for Session Host Virtual machines that are Azure AD joined.
Prerequisites
You’ll need the following things ready before you can rollout watermarking/session capture protection:
Azure Virtual Desktop: You must have Azure Virtual Desktop deployed (Pooled or Personal Desktops) and set up in your Azure environment.
Microsoft Intune: You should have an active subscription to Microsoft Intune, which is a cloud-based service that enables device management and security. The role within Intune Portal for creating and assigning the configuration profiles is – Policy and Profile manager built-in role-based access control (RBAC) role.
Azure Active Directory: Your Azure Virtual Desktop environment should be integrated with Azure Active Directory (AD) (The Host pools RDP properties – targetisaadjoined:i:1). The AAD Security groups must be in place, which has the members as the session’s host in AVD.
Azure AD Joined Devices: The session host virtual machines (VMs) you want to enable Watermarking and Session Capture protection for should be Azure AD joined. This means they must be connected to Azure AD and registered as members of your organization’s directory.
Windows 11 operating system for the client along with the Azure Virtual Desktop Client or Remote Desktop Client versions 1.2.x and higher
Configuration Profiles – Intune
To enable the Watermarking and Session Capture protection features in Azure Virtual Desktop using Microsoft Intune Configuration profiles and Azure AD joined devices, you can follow these steps:
In the settings picker, browse to Administrative templates > Windows Components > Remote Desktop Services > Remote Desktop Session Host > Azure Virtual Desktop. You should see settings in the Azure Virtual Desktop subcategory available for you to configure, such as “Enable watermarking” and “Enable screen capture protection”
Select the “Enable screen capture protection” settings, too and leave the values as defaults. (Feel free to tweak it based on your requirements)
Assigning the configuration to the AAD group, which has all the session host devices
Reboot the session host after applying or wait until the next maintenance cycle
Client Validation
Connect to a remote session with a supported client (Azure Virtual Desktop Client or Remote Desktop Client versions 1.2.x), where you should see QR codes appear.
The QR code only works for Windows 11 Multi-session\Windows 11 Enterprise (pooled or personal desktops). The RemoteApps will not show the QR code as its not supported.
Screenshot protection – In the session, it will be completely blank if you try to take a screenshot. Below is an example. I was trying to take a screenshot of the text file, and the screenshot was completely blank.
Mobile Phone Photo
When you try to take a screenshot from the mobile phone, this is how it will look, and it will pop the Connection ID. You have this connection ID you can match in Azure Insights.
Azure Virtual Desktop Insights
To find out the session information from the QR code by using Azure Virtual Desktop Insights:
Open a web browser and go to https://aka.ms/avdi to open Azure Virtual Desktop Insights. Sign-in using your Azure credentials when prompted.
Select the relevant subscription, resource group, host pool and time range, then select the Connection Diagnostics tab.
In the section Success rate of (re)establishing a connection (% of connections), there’s a list of all connections showing First attempt, Connection Id, User, and Attempts. You can look for the connection ID from the QR code in this list, or export to Excel.
I hope you will find this helpful information for getting started with Watermarking and Screenshot protection for the Azure Virtual Desktop – Session Host. Please let me know if I have missed any steps or details, and I will be happy to update the post.
We are going to create the following three types of configurations using Terraform:
Azure Virtual Desktop – Personal Desktop (1×1) – Part 1
Azure Virtual Desktop – Pooled Desktop (Multi-Session Full Desktop Experience) – Part 2
Azure Virtual Desktop – Remote App (Multi-Session Application aka Published Apps) – Part 3
Note – We are creating the Pooled RemoteApp in this post and in the subsequent post the other types were. In this post In this post I will not show case the creation of service principal and secret please refer for the Part 1 for that activity.
Pre-requisites
Following are the pre-requisites before you begin
An Azure subscription
The Terraform CLI
The Azure CLI
Permissions within the Azure Subscription for using Terraform
Terraform – Authenticating via Service Principal & Client Secret
Before running any Terraform code the following powershell (Make sure run as administrator) we will execute and store the credentials as enviornment variables. If we do this via the environment variable we dont have to store the below information within the providers.tf file. In the future blog post there are better way to store the below details and I hope to showcase them:
Azure Subcription ID – Azure Portal Subcription copy the ID
Client ID – From the above step you will have the details
Client Secret – From the above step you will have the details
Tenant ID – While creating the Enterprise Apps in ADD you will have the details
Terraform Folder Structure
The following is the folder structure for the terrraform code:
Azure Virtual Desktop Pooled RemoteApp – Create a directory in which the below Terraform code will be published (providers.tf, main.tf, variables.tf and output.tf)
Create a file named main.tf and insert the following code. Let me explain what all we are attempting to accomplish here:
Create a Resource Group
Create a Workspace
Create a Host Pool
Create a Remote Application Group (RAG)
Associate Workspace and RAG
Assign Azure AD Group to the Desktop Application Group (RAG)
Assign Azure AD Group to the Resource Group for RBAC for the Session Host (Virtual Machine User Login)
# Resource group name is output when execution plan is applied.
resource "azurerm_resource_group" "rg" {
name = var.rg_name
location = var.resource_group_location
tags = var.tags
}
# Create AVD workspace
resource "azurerm_virtual_desktop_workspace" "workspace" {
name = var.workspace
resource_group_name = azurerm_resource_group.rg.name
location = azurerm_resource_group.rg.location
friendly_name = "${var.prefix} Workspace"
description = "${var.prefix} Workspace"
tags = var.tags
}
# Create AVD host pool
resource "azurerm_virtual_desktop_host_pool" "hostpool" {
resource_group_name = azurerm_resource_group.rg.name
location = azurerm_resource_group.rg.location
name = var.hostpool
friendly_name = var.hostpool
validate_environment = true #[true false]
start_vm_on_connect = true
custom_rdp_properties = "targetisaadjoined:i:1;drivestoredirect:s:*;audiomode:i:0;videoplaybackmode:i:1;redirectclipboard:i:1;redirectprinters:i:1;devicestoredirect:s:*;redirectcomports:i:1;redirectsmartcards:i:1;usbdevicestoredirect:s:*;enablecredsspsupport:i:1;redirectwebauthn:i:1;use multimon:i:1;enablerdsaadauth:i:1;"
description = "${var.prefix} HostPool"
type = "Pooled" #[Pooled or Personal]
preferred_app_group_type = "RailApplications" #[Desktop or RailApplications]
maximum_sessions_allowed = 5 #[Tweak based on your vm tshirt size]
load_balancer_type = "DepthFirst" #[BreadthFirst or DepthFirst]
tags = var.tags
scheduled_agent_updates {
enabled = true
timezone = "AUS Eastern Standard Time" # Update this value with your desired timezone
schedule {
day_of_week = "Saturday"
hour_of_day = 1 #[1 here means 1:00 am]
}
}
}
resource "azurerm_virtual_desktop_host_pool_registration_info" "registrationinfo" {
hostpool_id = azurerm_virtual_desktop_host_pool.hostpool.id
expiration_date = var.rfc3339
}
# Create AVD RAG
resource "azurerm_virtual_desktop_application_group" "rag" {
resource_group_name = azurerm_resource_group.rg.name
host_pool_id = azurerm_virtual_desktop_host_pool.hostpool.id
location = azurerm_resource_group.rg.location
type = "RemoteApp"
name = var.app_group_name
friendly_name = "RemoteApp AppGroup"
description = "${var.prefix} AVD RemoteApp application group"
depends_on = [azurerm_virtual_desktop_host_pool.hostpool, azurerm_virtual_desktop_workspace.workspace]
tags = var.tags
}
# Associate Workspace and DAG
resource "azurerm_virtual_desktop_workspace_application_group_association" "ws-dag" {
application_group_id = azurerm_virtual_desktop_application_group.rag.id
workspace_id = azurerm_virtual_desktop_workspace.workspace.id
}
# Assign AAD Group to the Remote Application Group (RAG)
resource "azurerm_role_assignment" "AVDGroupRemoteAppAssignment" {
scope = azurerm_virtual_desktop_application_group.rag.id
role_definition_name = "Desktop Virtualization User"
principal_id = data.azuread_group.AVDGroup.object_id
}
# Assign AAD Group to the Resource Group for RBAC for the Session Host
resource "azurerm_role_assignment" "RBACAssignment" {
scope = azurerm_resource_group.rg.id
role_definition_name = "Virtual Machine User Login"
principal_id = data.azuread_group.AVDGroup.object_id
}
Note – The individual applications are not published yet. They can be published once you have the session host created. After which, using Terraform, the individual applications can be published too. The exe path of apps needs to be mapped within the operating system. I plan to create a separate blog post on session host creation via Terraform.
Configure AVD – Pooled RemoteApp – variables.tf
Create a file named variables.tf and insert the following code:
variable "resource_group_location" {
default = "australiaeast"
description = "Location of the resource group - Australia East"
}
variable "rg_name" {
type = string
default = "AE-DEV-AVD-01-PO-A-RG"
description = "Name of the Resource group in which to deploy service objects"
}
variable "workspace" {
type = string
description = "Name of the Azure Virtual Desktop workspace"
default = "AE-DEV-AVD-01-WS"
}
variable "hostpool" {
type = string
description = "Name of the Azure Virtual Desktop host pool"
default = "AE-DEV-AVD-01-PO-A-HP"
}
variable "app_group_name" {
description = "Name of the Azure Virtual Desktop application group"
type = string
default = "AE-DEV-AVD-01-RAG"
}
variable "rfc3339" {
type = string
default = "2023-05-20T12:43:13Z" #Update this value with a future date
description = "Registration token expiration"
}
variable "prefix" {
type = string
default = "AE-DEV-AVD-01-HP-"
description = "Prefix of the name of the AVD HostPools"
}
variable "tags" {
type = map(string)
default = {
Environment = "Dev"
Department = "IT"
Location = "AustraliaEast"
ServiceClass = "DEV"
Workload = "Host Pool 01"
}
}
data "azuread_client_config" "AzureAD" {}
data "azuread_group" "AVDGroup" {
display_name = "Win365-Users"
}
Configure AVD – Pooled RemoteApp – output.tf
Create a file named output.tf and insert the following code. This will showcase in the console what is getting deployed in form of a output.
output "azure_virtual_desktop_compute_resource_group" {
description = "Name of the Resource group in which to deploy session host"
value = azurerm_resource_group.rg.name
}
output "azure_virtual_desktop_host_pool" {
description = "Name of the Azure Virtual Desktop host pool"
value = azurerm_virtual_desktop_host_pool.hostpool.name
}
output "azurerm_virtual_desktop_application_group" {
description = "Name of the Azure Virtual Desktop DAG"
value = azurerm_virtual_desktop_application_group.rag.name
}
output "azurerm_virtual_desktop_workspace" {
description = "Name of the Azure Virtual Desktop workspace"
value = azurerm_virtual_desktop_workspace.workspace.name
}
output "location" {
description = "The Azure region"
value = azurerm_resource_group.rg.location
}
data "azuread_group" "aad_group" {
display_name = "Win365-Users"
}
output "AVD_user_groupname" {
description = "Azure Active Directory Group for AVD users"
value = data.azuread_group.aad_group.display_name
}
Intialize Terraform – AVD – Pooled RemoteApp
Run terraform init to initialize the Terraform deployment. This command downloads the Azure provider required to manage your Azure resources. (Its pulling the AzureRM and AzureAD)
terraform init -upgrade
Create Terraform Execution Plan – AVD – Pooled RemoteApp
Run terraform plan to create an execution plan.
terraform plan -out mainavdremoteapp.tfplan
Apply Terraform Execution Plan – AVD – Pooled RemoteApp
Run terraform apply to apply the execution plan to your cloud infrastructure.
terraform apply mainavdremoteapp.tfplan
Validate the Output in Azure Portal
Go to the Azure portal, Select Azure Virtual Desktop and Select Host pools, Application Group and Workspace created using Terraform.
Clean-up the above resources (Optional)
If you want to delete all the above resources then you can use the following commands to destroy. Run terraform plan and specify the destroy flag.
terraform plan -destroy -out mainavdremoteapp.destroy.tfplan
Run terraform apply to apply the execution plan.
terraform apply mainavdremoteapp.destroy.tfplan
Quick Start Links
The intention here is to get you quickly started with Terraform on Azure Virtual Desktop Solution:
Description
Links
Setting up your computer to get started with Terrafor using Powershell
I hope you will find this helpful information for getting started with Terraform to deploy the Azure Virtual Desktop – Pooled Remote App. Please let me know if I have missed any steps or details, and I will be happy to update the post.
We are going to create the following three types of configurations using Terraform:
Azure Virtual Desktop – Personal Desktop (1×1) – Part 1
Azure Virtual Desktop – Pooled Desktop (Multi-Session Full Desktop Experience) – Part 2
Azure Virtual Desktop – Remote App (Multi-Session Application aka Published Apps) – Part 3
Note – We are creating the Pooled Desktop in this post and in the subsequent post the other types will be created. In this post In this post I will not show case the creation of service principal and secret please refer for the Part 1 for that activity.
Pre-requisites
Following are the pre-requisites before you begin
An Azure subscription
The Terraform CLI
The Azure CLI
Permissions within the Azure Subscription for using Terraform
Terraform – Authenticating via Service Principal & Client Secret
Before running any Terraform code the following powershell (Make sure run as administrator) we will execute and store the credentials as enviornment variables. If we do this via the environment variable we dont have to store the below information within the providers.tf file. In the future blog post there are better way to store the below details and I hope to showcase them:
Azure Subcription ID – Azure Portal Subcription copy the ID
Client ID – From the above step you will have the details
Client Secret – From the above step you will have the details
Tenant ID – While creating the Enterprise Apps in ADD you will have the details
Terraform Folder Structure
The following is the folder structure for the terrraform code:
Azure Virtual Desktop Pooled Desktop – Create a directory in which the below Terraform code will be published (providers.tf, main.tf, variables.tf and output.tf)
Create a file named main.tf and insert the following code. Let me explain what all we are attempting to accomplish here:
Create a Resource Group
Create a Workspace
Create a Host Pool (Pooled Desktops and Depth first load balancing)
Create a Desktop Application Group (DAG)
Associate Workspace and DAG
Assign Azure AD Group to the Desktop Application Group (DAG)
Assign Azure AD Group to the Resource Group for RBAC for the Session Host (Virtual Machine User Login)
# Resource group name is output when execution plan is applied.
resource "azurerm_resource_group" "rg" {
name = var.rg_name
location = var.resource_group_location
tags = var.tags
}
# Create AVD workspace
resource "azurerm_virtual_desktop_workspace" "workspace" {
name = var.workspace
resource_group_name = azurerm_resource_group.rg.name
location = azurerm_resource_group.rg.location
friendly_name = "${var.prefix} Workspace"
description = "${var.prefix} Workspace"
tags = var.tags
}
# Create AVD host pool
resource "azurerm_virtual_desktop_host_pool" "hostpool" {
resource_group_name = azurerm_resource_group.rg.name
location = azurerm_resource_group.rg.location
name = var.hostpool
friendly_name = var.hostpool
validate_environment = true #[true false]
start_vm_on_connect = true
custom_rdp_properties = "targetisaadjoined:i:1;drivestoredirect:s:*;audiomode:i:0;videoplaybackmode:i:1;redirectclipboard:i:1;redirectprinters:i:1;devicestoredirect:s:*;redirectcomports:i:1;redirectsmartcards:i:1;usbdevicestoredirect:s:*;enablecredsspsupport:i:1;redirectwebauthn:i:1;use multimon:i:1;enablerdsaadauth:i:1;"
description = "${var.prefix} HostPool"
type = "Pooled" #[Pooled or Personal]
maximum_sessions_allowed = 5
load_balancer_type = "DepthFirst" #[BreadthFirst DepthFirst]
tags = var.tags
scheduled_agent_updates {
enabled = true
timezone = "AUS Eastern Standard Time" # Update this value with your desired timezone
schedule {
day_of_week = "Saturday"
hour_of_day = 1 #[1 here means 1:00 am]
}
}
}
resource "azurerm_virtual_desktop_host_pool_registration_info" "registrationinfo" {
hostpool_id = azurerm_virtual_desktop_host_pool.hostpool.id
expiration_date = var.rfc3339
}
# Create AVD DAG
resource "azurerm_virtual_desktop_application_group" "dag" {
resource_group_name = azurerm_resource_group.rg.name
host_pool_id = azurerm_virtual_desktop_host_pool.hostpool.id
location = azurerm_resource_group.rg.location
type = "Desktop"
name = var.app_group_name
friendly_name = "Desktop AppGroup"
description = "${var.prefix} AVD application group"
depends_on = [azurerm_virtual_desktop_host_pool.hostpool, azurerm_virtual_desktop_workspace.workspace]
tags = var.tags
}
# Associate Workspace and DAG
resource "azurerm_virtual_desktop_workspace_application_group_association" "ws-dag" {
application_group_id = azurerm_virtual_desktop_application_group.dag.id
workspace_id = azurerm_virtual_desktop_workspace.workspace.id
}
# Assign AAD Group to the Desktop Application Group (DAG)
resource "azurerm_role_assignment" "AVDGroupDesktopAssignment" {
scope = azurerm_virtual_desktop_application_group.dag.id
role_definition_name = "Desktop Virtualization User"
principal_id = data.azuread_group.AVDGroup.object_id
}
# Assign AAD Group to the Resource Group for RBAC for the Session Host
resource "azurerm_role_assignment" "RBACAssignment" {
scope = azurerm_resource_group.rg.id
role_definition_name = "Virtual Machine User Login"
principal_id = data.azuread_group.AVDGroup.object_id
}
Configure AVD – Pooled Desktop Pool – variables.tf
Create a file named variables.tf and insert the following code:
variable "resource_group_location" {
default = "australiaeast"
description = "Location of the resource group - Australia East"
}
variable "rg_name" {
type = string
default = "AE-DEV-AVD-01-PO-D-RG"
description = "Name of the Resource group in which to deploy service objects"
}
variable "workspace" {
type = string
description = "Name of the Azure Virtual Desktop workspace"
default = "AE-DEV-AVD-01-WS"
}
variable "hostpool" {
type = string
description = "Name of the Azure Virtual Desktop host pool"
default = "AE-DEV-AVD-01-PO-D-HP"
}
variable "app_group_name" {
description = "Name of the Azure Virtual Desktop application group"
type = string
default = "AE-DEV-AVD-01-DAG"
}
variable "rfc3339" {
type = string
default = "2023-05-20T12:43:13Z" #Update this value with a future date
description = "Registration token expiration"
}
variable "prefix" {
type = string
default = "AE-DEV-AVD-01-HP-"
description = "Prefix of the name of the AVD machine(s)"
}
variable "tags" {
type = map(string)
default = {
Environment = "Dev"
Department = "IT"
Location = "AustraliaEast"
ServiceClass = "DEV"
Workload = "Host Pool 01"
}
}
data "azuread_client_config" "AzureAD" {}
data "azuread_group" "AVDGroup" {
display_name = "Win365-Users"
}
Configure AVD – Pooled Desktop Pool – output.tf
Create a file named output.tf and insert the following code. This will showcase in the console what is getting deployed in form of a output.
output "azure_virtual_desktop_compute_resource_group" {
description = "Name of the Resource group in which to deploy session host"
value = azurerm_resource_group.rg.name
}
output "azure_virtual_desktop_host_pool" {
description = "Name of the Azure Virtual Desktop host pool"
value = azurerm_virtual_desktop_host_pool.hostpool.name
}
output "azurerm_virtual_desktop_application_group" {
description = "Name of the Azure Virtual Desktop DAG"
value = azurerm_virtual_desktop_application_group.dag.name
}
output "azurerm_virtual_desktop_workspace" {
description = "Name of the Azure Virtual Desktop workspace"
value = azurerm_virtual_desktop_workspace.workspace.name
}
output "location" {
description = "The Azure region"
value = azurerm_resource_group.rg.location
}
data "azuread_group" "aad_group" {
display_name = "Win365-Users"
}
output "AVD_user_groupname" {
description = "Azure Active Directory Group for AVD users"
value = data.azuread_group.aad_group.display_name
}
Intialize Terraform – AVD – Pooled Desktop Pool
Run terraform init to initialize the Terraform deployment. This command downloads the Azure provider required to manage your Azure resources. (Its pulling the AzureRM and AzureAD)
terraform init -upgrade
Create Terraform Execution Plan – AVD – Pooled Desktop Pool
Run terraform plan to create an execution plan.
terraform plan -out mainavdpooled.tfplan
Apply Terraform Execution Plan – AVD – Pooled Desktop Pool
Run terraform apply to apply the execution plan to your cloud infrastructure.
terraform apply mainavdpooled.tfplan
Validate the Output in Azure Portal
Go to the Azure portal, Select Azure Virtual Desktop and Select Host pools, Application Group and Workspace created using Terraform.
Clean-up the above resources (Optional)
If you want to delete all the above resources then you can use the following commands to destroy. Run terraform plan and specify the destroy flag.
terraform plan -destroy -out mainavdpooled.destroy.tfplan
Run terraform apply to apply the execution plan.
terraform apply mainavdpooled.destroy.tfplan
Quick Start Links
The intention here is to get you quickly started with Terraform on Azure Virtual Desktop Solution:
Description
Links
Setting up your computer to get started with Terrafor using Powershell
I hope you will find this helpful information for getting started with Terraform to deploy the Azure Virtual Desktop – Pooled Desktop. Please let me know if I have missed any steps or details, and I will be happy to update the post.
In the past, I have written blog posts on creating the Azure Virtual Desktop (AVD) solution using PowerShell. In this blog post series, I will demonstrate how to create the AVD Host Pool, Application Group and Workspace using Terraform. Terraform is an open-source infrastructure as code (IaC) software tool that enables you to safely and predictably create, change, and improve infrastructure. Terraform can be used to manage infrastructure on various cloud providers, including Azure.
We are going to create the following three types of configurations using Terraform:
Azure Virtual Desktop – Personal Desktop (1×1)
Azure Virtual Desktop – Pooled Desktop (Multi-Session Full Desktop Experience)
Note – We are creating the Personal Desktop in this post, and the other desktop/app types will be created in the subsequent post. In this post, I will showcase the creation of service principal and secret. In the next part, we shall move straight onto the Terraform code. Referring to part 1 in the series will be essential if you are doing the basics.
Permissions within the Azure Subscription for using Terraform
Terraform Service Principal and Secret (Azure AD – App Registrations)
Let’s pre-create the application ID and client secret we will use to connect and leverage the Terraform code in VScode.
Connect to Azure Portal and go to Azure Active Directory
Click on App Registrations and select – New Registration
Give the App a Name – Terraform
You will get two important information created for later use within Terraform
Application ID
Tenant ID
Now let’s grant this App Terraform Permission. Click on Add a permission and select MS Graph and search for AppRoleAssignment.ReadWrite.All and select read/write permissions and Add Permissions
Select Grant admin consent for domain
We are using client secret so now lets enable that. Click on Certificates & Secrets – Client Secrets and select New client secret\
Give it a name (Terra-secret) and expiry date (12 months)
Copy the Secret Value
Terraform – Authenticating via Service Principal & Client Secret
In the above step, we created the Service Principal and Client secret. We will use it before running any Terraform code in PowerShell (Ensure to run as administrator). We will execute and store the credentials as environment variables. If we do this via the environment variable, we don’t have to store the below information within the providers.tf file. In a future blog post, there are better ways to keep the below details, and I hope to showcase them:
Azure Subscription ID – Azure Portal Subscription copy the ID.
Client ID – From the above step, you will have the details
Client Secret – From the above step, you will have the details
Tenant ID – While creating the Enterprise Apps in Azure AD, you will have the details
Terraform Folder Structure
The following is the folder structure for the Terraform code:
Azure Virtual Desktop Personal Pool – Create a directory in which the below Terraform code will be published (providers.tf, main.tf, variables.tf and output.tf)
Create a file named main.tf and insert the following code. Let me explain what we are attempting to accomplish here: (Note I have # commented the lines with additional info)
Create a Resource Group
Create a Workspace
Create a Host Pool
Create a Desktop Application Group (DAG)
Associate Workspace and DAG
Assign Azure AD Group to the Desktop Application Group (DAG)
Assign Azure AD Group to the Resource Group for RBAC for the Session Host (Virtual Machine User Login)
# Resource group name is output when execution plan is applied.
resource "azurerm_resource_group" "rg" {
name = var.rg_name
location = var.resource_group_location
tags = var.tags
}
# Create AVD workspace
resource "azurerm_virtual_desktop_workspace" "workspace" {
name = var.workspace
resource_group_name = azurerm_resource_group.rg.name
location = azurerm_resource_group.rg.location
friendly_name = "${var.prefix} Workspace"
description = "${var.prefix} Workspace"
tags = var.tags
}
# Create AVD host pool
resource "azurerm_virtual_desktop_host_pool" "hostpool" {
resource_group_name = azurerm_resource_group.rg.name
location = azurerm_resource_group.rg.location
name = var.hostpool
friendly_name = var.hostpool
validate_environment = true #[true false]
start_vm_on_connect = true
custom_rdp_properties = "targetisaadjoined:i:1;drivestoredirect:s:*;audiomode:i:0;videoplaybackmode:i:1;redirectclipboard:i:1;redirectprinters:i:1;devicestoredirect:s:*;redirectcomports:i:1;redirectsmartcards:i:1;usbdevicestoredirect:s:*;enablecredsspsupport:i:1;redirectwebauthn:i:1;use multimon:i:1;enablerdsaadauth:i:1;"
description = "${var.prefix} HostPool"
type = "Personal" #[Pooled or Personal]
personal_desktop_assignment_type = "Automatic"
load_balancer_type = "Persistent"
tags = var.tags
scheduled_agent_updates {
enabled = true
timezone = "AUS Eastern Standard Time" # Update this value with your desired timezone
schedule {
day_of_week = "Saturday"
hour_of_day = 1 #[1 here means 1:00 am]
}
}
}
resource "azurerm_virtual_desktop_host_pool_registration_info" "registrationinfo" {
hostpool_id = azurerm_virtual_desktop_host_pool.hostpool.id
expiration_date = var.rfc3339
}
# Create AVD DAG
resource "azurerm_virtual_desktop_application_group" "dag" {
resource_group_name = azurerm_resource_group.rg.name
host_pool_id = azurerm_virtual_desktop_host_pool.hostpool.id
location = azurerm_resource_group.rg.location
type = "Desktop"
name = var.app_group_name
friendly_name = "Desktop AppGroup"
description = "${var.prefix} AVD application group"
depends_on = [azurerm_virtual_desktop_host_pool.hostpool, azurerm_virtual_desktop_workspace.workspace]
tags = var.tags
}
# Associate Workspace and DAG
resource "azurerm_virtual_desktop_workspace_application_group_association" "ws-dag" {
application_group_id = azurerm_virtual_desktop_application_group.dag.id
workspace_id = azurerm_virtual_desktop_workspace.workspace.id
}
# Assign AAD Group to the Desktop Application Group (DAG)
resource "azurerm_role_assignment" "AVDGroupDesktopAssignment" {
scope = azurerm_virtual_desktop_application_group.dag.id
role_definition_name = "Desktop Virtualization User"
principal_id = data.azuread_group.AVDGroup.object_id
}
# Assign AAD Group to the Resource Group for RBAC for the Session Host
resource "azurerm_role_assignment" "RBACAssignment" {
scope = azurerm_resource_group.rg.id
role_definition_name = "Virtual Machine User Login"
principal_id = data.azuread_group.AVDGroup.object_id
}
Configure AVD – Personal Desktop Pool – variables.tf
Create a file named variables.tf and insert the following code. I have followed a naming convention that includes the following:
AE – Australia East
Environment – PROD or DEV
Instance – 01
RG – Resource Group
WS – Workspace
DAG – Desktop Application Group
variable "resource_group_location" {
default = "australiaeast"
description = "Location of the resource group - Australia East"
}
variable "rg_name" {
type = string
default = "AE-DEV-AVD-01-RG"
description = "Name of the Resource group in which to deploy service objects"
}
variable "workspace" {
type = string
description = "Name of the Azure Virtual Desktop workspace"
default = "AE-DEV-AVD-01-WS"
}
variable "hostpool" {
type = string
description = "Name of the Azure Virtual Desktop host pool"
default = "AE-DEV-AVD-01-PE-D-HP"
}
variable "app_group_name" {
description = "Name of the Azure Virtual Desktop application group"
type = string
default = "AE-DEV-AVD-01-DAG"
}
variable "rfc3339" {
type = string
default = "2023-05-20T12:43:13Z" #Update this value with a future date
description = "Registration token expiration"
}
variable "prefix" {
type = string
default = "AE-DEV-AVD-01-HP-"
description = "Prefix of the name of the AVD machine(s)"
}
variable "tags" {
type = map(string)
default = {
Environment = "Dev"
Department = "IT"
Location = "AustraliaEast"
ServiceClass = "DEV"
Workload = "Host Pool 01"
}
}
data "azuread_client_config" "AzureAD" {}
data "azuread_group" "AVDGroup" {
display_name = "Win365-Users"
}
Configure AVD – Personal Desktop Pool – output.tf
Create a file named output.tf and insert the following code. This will showcase in the console what is getting deployed as output.
output "azure_virtual_desktop_compute_resource_group" {
description = "Name of the Resource group in which to deploy session host"
value = azurerm_resource_group.rg.name
}
output "azure_virtual_desktop_host_pool" {
description = "Name of the Azure Virtual Desktop host pool"
value = azurerm_virtual_desktop_host_pool.hostpool.name
}
output "azurerm_virtual_desktop_application_group" {
description = "Name of the Azure Virtual Desktop DAG"
value = azurerm_virtual_desktop_application_group.dag.name
}
output "azurerm_virtual_desktop_workspace" {
description = "Name of the Azure Virtual Desktop workspace"
value = azurerm_virtual_desktop_workspace.workspace.name
}
output "location" {
description = "The Azure region"
value = azurerm_resource_group.rg.location
}
data "azuread_group" "aad_group" {
display_name = "Win365-Users"
}
output "AVD_user_groupname" {
description = "Azure Active Directory Group for AVD users"
value = data.azuread_group.aad_group.display_name
}
Intialize Terraform – AVD – Personal Desktop Pool
Run the following command to initialize the Terraform deployment. This command downloads the Azure provider required to manage your Azure resources.
terraform init -upgrade
Create Terraform Execution Plan – AVD – Personal Desktop Pool
Run the following command to create an execution plan.
terraform plan -out mainavdpersonal.tfplan
Apply Terraform Execution Plan – AVD – Personal Desktop Pool
Run the following command to apply the execution plan to your cloud infrastructure.
terraform apply mainavdpersonal.tfplan
Validate the Output in Azure Portal
Go to the Azure portal, Select Azure Virtual Desktop and Select Host pools, Application Group and Workspace created using Terraform.
Clean-up the above resources (Optional)
If you want to delete all the above resources then you can use the following commands to destroy. Run terraform plan and specify the destroy flag.
terraform plan -destroy -out mainavdpersonal.destroy.tfplan
Run terraform apply to apply the execution plan.(Destroy)
terraform apply mainavdpersonal.destroy.tfplan
Quick Start Links
The intention here is to get you quickly started with Terraform on Azure Virtual Desktop Solution:
Description
Links
Setting up your computer to get started with Terrafor using Powershell
I hope you will find this helpful information for getting started with Terraform to deploy the Azure Virtual Desktop – Personal Desktop Pool. Please let me know if I have missed any steps or details, and I will be happy to update the post.
Search Highlight is a feature in Windows 11 (Enterprise\Multi-session) that highlights search results in the Start menu and taskbar search box. While this feature can be helpful for some users, others may find it distracting or unnecessary. Fortunately, it is possible to disable the Search Highlight feature in Windows 11 using Microsoft Intune. Plenty of information is available on disabling the Windows 11 Search Highlight using Group policy, Registry and UI. However, we will leverage Custom OMA-URI settings from Microsoft Intune in this blog post.
Search – CSP Details
The Search – Policy configuration service provider enables the enterprise to configure policies on Windows 11. Following are the details on the one we are using for disabling the search highlights:
How to disable Search Highlights in Microsoft Endpoint Manager
To disable the Search Highlight feature in Windows 11 (Enterprise/Multi-session) using Microsoft Intune, follow these steps:
For Profile type, select Templates > Custom and select Create.
Enter a Name – DisableSearchHighlight and description and choose Next
Under the OMA-URI Settings, clicks on Add
Enter the Name, Description, and OMA-URI fetched in the references from the MS CSP link below. The value is an integer based on the documentation, and as we disable the setting, the value is 0.
Remember the MS documentation called out this setting only applies to Devices. In the case of Assignments, we will target Windows 365 Device Group and Azure Virtual Desktop Session Host Pools.
Click on Review and Save
Validate the Policy is applying
After 10-15 mins of waiting, go into the newly configured configuration profiles policy, and you will start seeing it getting applied to the targeted devices (MEM Portal > Devices > Configuration Profiles > DisableSearchHighlights)
Cloud PC – Within Windows 11
Login to the Windows 365 Cloud PC, and now when you click on Search, the advertisements and search highlights are gone.
I hope you will find this helpful information towards disabling the annoying Search Highlights on Windows 365, AVD environment and physical endpoints using Microsoft Endpoint Manager. Please let me know if I have missed any steps or details, and I will be happy to update the post.
In today’s world, online security has become more important than ever, especially for businesses. As more and more companies shift their workloads to the cloud, the need for effective security measures has increased. One of the most critical aspects of security is web content filtering. Microsoft Defender for Endpoint is an excellent solution for protecting your Windows 365 Cloud PC and Azure Virtual Desktop environments. If you haven’t see my previous blog post on – Microsoft Defender for Endpoint (MDE) – Getting started for Windows 365 Cloud PC and Azure Virtual Desktop check that first.
Usecase
Web content filtering is a critical aspect of online security that can be used in many different scenarios. Here are some common use cases for web content filtering:
Business Security: Blocking access to malicious websites and other dangerous content, web content filtering helps prevent cyber attacks and data breaches.
Compliance: Many organizations are required to comply with industry-specific regulations and standards, such as HIPAA or PCI-DSS. Web content filtering can help ensure that employees are not accessing websites or content that violates these regulations.
Employee Productivity: Web content filtering can also be used to enhance employee productivity by blocking access to non-work-related websites, such as social media or gaming sites.
Education: Educational institutions can use web content filtering to prevent students from accessing websites that are not educational or age-appropriate.
Guest Wi-Fi: Businesses that offer guest Wi-Fi can use web content filtering to protect their network and guests from online threats.
Overall, web content filtering is a versatile tool that can be used in a variety of settings to enhance online security, productivity, and compliance.
Pre-requisites
To use Microsoft Defender for Endpoint web content filtering on Windows 365 Cloud PC and Azure Virtual Desktop, there are a few prerequisites that you need to meet:
I hope you will find this helpful information towards web content filtering journey to secure your Windows 365 and AVD environments using Microsoft Defender for Endpoint. Please let me know if I have missed any steps or details, and I will be happy to update the post.
If you are using Windows 365 Cloud PC and Azure Virtual Desktop, the Microsoft Defender for Endpoint (MDE) is a security solution designed for protecting endpoints, such as Windows 11/Windows 11 Mutli-Session computers, servers, Azure Virtual Desktops and more from various types of cyber threats. The main reason it’s evident to use MDE is that it seamlessly integrates with the solution with minimal to less effort compared to other solutions. This blog post will discuss how to get started with Microsoft Defender for Endpoint in the Windows 365 Cloud and Azure Virtual Desktop.
Prerequisites
Rights to use and deploy Windows 365 Cloud PC and Azure Virtual Desktop and the ncessary licenses
Microsoft Defender for Endpoint Plan 1 or Plan 2 depending upon the requirements and $$$.
Make sure the license is available and listed Microsoft admin center
Enable MDE in Microsoft 365 Security Portal/Intune
To enable Microsoft Defender for Endpoint (MDE) in the Microsoft Defender Security Center, you need to follow these steps:
Log in to the Microsoft Defender Security Center: Go to https://security.microsoft.com/ and log in with your Microsoft 365 account.
Navigate to Settings and select Endpoints
Click on On for Microsoft Intune Connection & Device Discovery
Scroll to the bottom and select Save Preferences
We will manage the endpoints via Intune, so all the rest of the actions and fun will be within the https://endpoint.microsoft.com/ and Endpoint Security. After a brief period of 10-15 mins, you can see the connection status being Available and synchronized.
Create the Endpoint detection and response policy (onboarding)
Our environment is managed via Modern Management, and we don’t have the overhead of legacy setup. We will use the Intune Endpoint detection response (EDR) policy to onboard the devices. This is the simplest method as it doesn’t involve installing the agent manually or via GPOs.
Sign in to the Microsoft Endpoint Manager admin center.
On the onboarded device, go and run the following command to verify the status
Get-MpComputerStatus
Device Compliance Policy (Update)
I already have my existing Windows 10/11 compliance policy after enabling MDE, and I will go ahead and update the compliance policy to accommodate the changes further. This will allow reporting within the tenant on what device compliance level the endpoints are on and whether corporate governance is maintained.
Create Antivirus Policy in Intune
The next step is creating the Antivirus (AV) Policy with the options that your organization demands. I am starting with a few, but remember most choices will require nailing out with internal security/endpoint/governance teams.
Below configurations are not an exhaustive list – Consult with the endpoint/security teams to meet the organization’s requirements.
Sign in to the Microsoft Endpoint Manager admin center.
For Platform, select Windows 10, Windows 11, and Windows Servers.
For Profile type, select Microsoft Defender Antivirus, and then select Create.
Enter a Name – W365-AVD-AV-P01 and description and choose Next
Under the Configuration Settings
Configuration Settings
Status (Value)
Allow Archive Scanning (Scanning through zip and cab files)
Allowed
Allow Behaviour Monitoring
Allowed
Allow Cloud Protection (Joining Microsoft MAPS Community)
Allowed
Allow Email Scanning (Very useful if you are using Microsoft 365)
Allowed
Allow Full Scan Removable Drive Scanning (Scanning of Pen Drives)
Allowed
Allow Intrusion Prevention System
Allowed
Allow scanning of all downloaded files and attachments
Allowed
Allow Realtime Monitoring
Allowed
Cloud Block Level
High
Allow Users UI Access (Defender Client)
Allowed
Enable Network Protection
Enabled (Audit mode)
Avg CPU Load Factor
Enabled (30%)
Schedule Quick Scan Time
Enable (120)
Signature Update Interval
Enable (8 hours)
Next, the most critical part is the target assignments. I am explicitly creating this policy to target Windows 365 Cloud PC and Azure Virtual Desktop
Review and Create the policy and it will go ahead and enable AV across the fleet.
After sometime all your devices will show whether they are onboarded or not.
Create Attack surface reduction (ASR) Policy in Intune
The attack surface reduction set of capabilities provide the first line of defense in the stack. By ensuring configuration settings are properly set and exploit mitigation techniques are applied, these set of capabilities resist attacks and exploitation. This set of capabilities also includes network protection and web protection, which regulate access to malicious IP addresses, domains, and URLs. In my case I am starting with few, but remember most of the options will require nailing out with internal security/endpoint/governeance teams.
Below configurations are not an exhaustive list – Consult with the endpoint/security teams to meet the organization’s requirements. Here I would like to take the approach of Audit mode first, followed by adding exclusions to refine the block rules (production).
Sign in to the Microsoft Endpoint Manager admin center.
Next step, I plan to write a few blog posts on specific topics like URLs, Networks etc, blocking (TikTok, Facebook etc,) concerning MDE. I hope you will find this helpful information towards your journey to secure your Windows 365 and AVD environments using Microsoft Defender for Endpoint. Please let me know if I have missed any steps or details, and I will be happy to update the post.
Recent Comments