In the world of AI, OpenAI’s ChatGPT has made a remarkable impact, reaching over 100 million users in just two months. The technology’s potential is vast, and users worldwide are exploring its application across a broad range of scenarios. One question that often arises is, “How can I build something like ChatGPT that uses my own data as the basis for its responses?” Today, I will demonstrate and guide you through the process of creating a ChatGPT-like experience using your own data with Azure OpenAI and Cognitive Search.
Note – In this blog post I am not going to explain each of the Azure services. The best source is learn.microsoft.com to grab all those details.
What You’ll Need
To get started, you’ll need an Azure subscription with access enabled for the Azure OpenAI service. You can request access here. Additional the user should have Owner and Cognitive Services Contributor (Note if you dont add this role to your account the azd up command will come with a error why processing the preconfig.py files)
Github Codespaces – I am using this as its a preconfigured enviornment with all pre-requsites to run the code from the VScode IDE.
Install locally on your device – You’ll also need to have Azure Developer CLI, Python 3+, Node.js, Git, Powershell 7+ (pwsh) installed on your local machine.
The Power of Azure OpenAI and Cognitive Search
Azure OpenAI and Cognitive Search offer an effective solution for creating a ChatGPT-like experience using your own data. Azure Cognitive Search allows you to index, understand, and retrieve the right pieces of your data across large knowledge bases, while Azure OpenAI’s ChatGPT offers impressive capabilities for interacting in natural language to answer questions or engage in conversation.
Getting Started with the sample project
To begin, you’ll need to click on the Github Codespaces and login with your Github account.
The project gets cloned and a new one gets created under Codespaces with everything preconfigured for you. Note this step takes approx. 15 mins to complete as its a 4 CPU, 8 GB RAM compute environment been created.
Next Step create a folder in my case DellAz and further cd into the newly created folder within the terminal. Further login to the Azure Subcription.
Initialize the Azure-search-openai-demo (In my case I already did that earlier)
Uploading Your Data
To upload your data, follow these steps:
Upload Your Data: Within VScode do to you intialized project folder DellAz –> ./data and right click and select upload files and upload a few files. In my secnario I am uploading few Dell Azure Stack HCI pdf files. Azure Cognitive Search will be breaking up larger documents into smaller chunks or summarizing content to fit more candidates in a prompt.
You can do this by running the azd up command, which will provision Azure resources and deploy the sample application to those resources, including building the search index based on the files found in the folder. I had recieved the error intially but after overcoming the permissions mentioned above it went smoothly as expected.
Resources within Azure Subcription
All the resources required will be deployed within the resource group. (App Service, Form recongnizer, Azure OpenAI, Search Service, App Service Plan and Storage Account)
Storage Account (PDFs getting chunked)
App Service (front end portal)
Search Index using Azure Congnitive Search
Interaction, Trustworthy Responses and User Experience
One of the key aspects of creating a successful ChatGPT-like experience is ensuring that the responses generated by the model are trustworthy. This can be achieved by providing citations and source content tracking, as well as offering transparency into the interaction process. As you can see all the citations are from the documents I have uploaded to the ./data folder along with LLM making it easily consumable for an user.
Conclusion
Creating a ChatGPT-like experience using your own data with Azure OpenAI and Cognitive Search is a powerful way to leverage AI in your enterprise. Whether you’re looking to answer employee questions, provide customer support, or engage users in conversation, this combination of technologies offers a flexible and effective solution. So why wait? Start revolutionizing your enterprise data today!
References
Following are the references and important links worth going through for more details:
I hope you will find this helpful information for creating a custom ChatGPT with your own enterprise data. Please let me know if I have missed any steps or details, and I will be happy to update the post.
I have a blog post about creating a Windows 365 Cloud PC Provisioning Policy using PowerShell. In this post blog, I will demonstrate how to create the provisioning policy using PowerShell and MS Graph API with beta modules for Windows 365 Cloud PC – Frontline Workers.
Example – Each Windows 365 Frontline license can be shared with up to three employees. This means that if you have 30 employees, you only need to purchase 10 licenses to provision the CloudPC for all 30 employees with access over the day. However, note you are buying the frontline license based on the active sessions. You must purchase the license accordingly if you have more than 10 active workers in a shift.
What happens when license are exhausted?
In my demo tenant, I have two licenses for Frontline workers. When I try to log in to the third one (Note I have already logged into 2 active sessions and running them.) Get the following message.
Connect to MS Graph API
Step 1 – Install the MS Graph Powershell Module
#Install Microsoft Graph Module
PS C:WINDOWSsystem32> Install-Module Microsoft.Graph
Step 2 – Connect to scopes and specify which API you wish to authenticate to. If you are only doing read-only operations, I suggest you connect to “CloudPC.Read.All” in our case, we are creating the policy, so we need to change the scope to “CloudPC.ReadWrite.All”
#Read-only
PS C:WINDOWSsystem32> Connect-MgGraph -Scopes "CloudPC.Read.All"
Welcome To Microsoft Graph!
OR
#Read-Write
PS C:WINDOWSsystem32> Connect-MgGraph -Scopes "CloudPC.ReadWrite.All"
Welcome To Microsoft Graph!
Permissions for MS Graph API
Step 3 – Choose between v1.0 (Generally Available) and Beta API versions. Note for Windows 365 Cloud PC the API calls are BETA.
If you are doing on-premise network integration (Azure Network Connection) , then the following additional property and value is required. In my lab, I am leveraging the Microsoft Managed Network, so this is not required.
I hope you will find this helpful information for creating a frontline worker provisioning policy using PowerShell. 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.
Recent Comments