I have created a VM in Azure as mentioned below
resource "azurerm_windows_virtual_machine" "virtual_machine_hub" {
name = "vm-hub"
resource_group_name = azurerm_resource_group.ipz12-dat-np-connection-rg.name
location = azurerm_resource_group.ipz12-dat-np-connection-rg.location
size = "Standard_B8ms"
admin_username = "xxxxx"
admin_password = "xxxxx"
network_interface_ids = [
azurerm_network_interface.virtual_machine_hub_nic.id
]
os_disk {
caching = "ReadWrite"
storage_account_type = "Standard_LRS"
}
source_image_reference {
publisher = "MicrosoftWindowsDesktop"
offer = "Windows-10"
sku = "21h1-pro"
version = "latest"
}
depends_on = [
azurerm_network_interface.virtual_machine_hub_nic
]
}
and enabled the AADLoginForWindows extension
resource "azurerm_virtual_machine_extension" "virtual_machine_hub_ext" {
name = "AADLoginForWindows"
virtual_machine_id = azurerm_windows_virtual_machine.virtual_machine_hub.id
type = "AADLoginForWindows"
type_handler_version = "1.0"
auto_upgrade_minor_version = true
publisher = "Microsoft.Azure.ActiveDirectory"
depends_on = [
azurerm_windows_virtual_machine.virtual_machine_hub
] }
however "dsregcmd /status" command shows that it is not connected with Azure AD domain like AzureADJoined is "No"
In order to register the VM in Azure AD, I don't feel that I have the appropriate permissions. If that's the case, what level of permission is required? and what am I missing?
Note: I have manually joined Azure AD like mentioned below
As discussed here, it is described that aadj private
extension also to be created for a virtual machine under path:
HKLM\SOFTWARE\Microsoft\RDInfraAgent\AADJPrivate
So, another Custom script extension was added to add the key AADJPRIVATE
for the VM.
Followed this template given by @Ansuman Bal in SO thread for Azure AD VM join and made a few changes to achieve the expected results as per your requirements.
vi main.tf:
terraform {
required_providers {
azurerm = {
source = "hashicorp/azurerm"
version = "3.37.0"
}
}
}
provider "azurerm" {
features {}
}
provider "azuread" {}
data "azuread_group" "aad_group" {
display_name = "<ADGroup>"
security_enabled = true
}
data "azurerm_role_definition" "vm_user_login" {
name = "<VM User Login>"
}
resource "azurerm_role_assignment" "vm_user_role" {
scope = azurerm_resource_group.rg-xxx.id
role_definition_id = data.azurerm_role_definition.vm_user_login.id
principal_id = data.azuread_group.aad_group.id
}
data "azurerm_role_definition" "desktop_user" {
name = "xxxxxx User"
}
resource "azurerm_role_assignment" "desktop_role" {
scope = azurerm_virtual_desktop_application_group.desktopapp.id
role_definition_id = data.azurerm_role_definition.desktop_user.id
principal_id = data.azuread_group.aad_group.id
}
resource "azurerm_resource_group" "eg-RG" {
name = "xxxxxtest"
location = "West Europe"
}
resource "azurerm_virtual_network" "vnet" {
name = "xxxx-vnet"
location = azurerm_resource_group.eg-RG.location
resource_group_name = azurerm_resource_group.eg-RG.name
address_space = ["10.0.0.0/16"]
}
resource "azurerm_subnet" "xxxxdefaultSubnet" {
name = "xxxxxsubnet"
resource_group_name = azurerm_resource_group.eg-RG.name
virtual_network_name = azurerm_virtual_network.vnet.name
address_prefixes = ["10.0.0.0/24"]
}
resource "azurerm_network_security_group" "nsg" {
name = "xxxx-nsg"
location = azurerm_resource_group.eg-RG.location
resource_group_name = azurerm_resource_group.eg-RG.name
security_rule {
name = "allow-rdp"
priority = 100
direction = "Inbound"
access = "Allow"
protocol = "Tcp"
source_port_range = "*"
destination_port_range = 3389
source_address_prefix = "*"
destination_address_prefix = "*"
}
}
resource "azurerm_subnet_network_security_group_association" "nsg_association" {
subnet_id = azurerm_subnet.xxxxdefaultSubnet.id
network_security_group_ID = azurerm_network_security_group.<nsg>.id
}
resource "time_rotating" Gen_token" {
rotation_days = 30
}
resource "azurerm_virtual_desktop_host_pool" "new-hp" {
location = azurerm_resource_group.eg-RG.location
resource_group_name = azurerm_resource_group.eg-RG.name
name = "xxxxxhostpool"
friendly_name = "samplepool"
validate_environment = true
start_vm_on_connect = true
custom_rdp_properties = "audiocapturemode:i:1;audiomode:i:0;targetisaadjoined:i:1;"
description = "host-poool demo"
type = "Pooled"
maximum_sessions_allowed = 10
load_balancer_type = "DepthFirst"
}
resource "azurerm_virtual_desktop_host_pool_registration_info" "reginfo" {
hostpool_id = azurerm_virtual_desktop_host_pool.new-hp.id
expiration_date = time_rotating.avd_token.rotation_rfc3339
}
resource "azurerm_virtual_desktop_application_group" "desktopapp" {
name = "xxxx-Desktop"
location = azurerm_resource_group.eg-RG.location
resource_group_name = azurerm_resource_group.eg-RG.name
type = "Desktop"
host_pool_id = azurerm_virtual_desktop_host_pool.new-hp.id
friendly_name = "xxxxx"
description = "xxxxapplications"
}
resource "azurerm_virtual_desktop_workspace" "workspace" {
name = "xxxxxx-WORKSPACE"
location = azurerm_resource_group.eg-RG.location
resource_group_name = azurerm_resource_group.eg-RG.name
friendly_name = "xxxxxxx"
description = "Purporse"
}
resource "azurerm_virtual_desktop_workspace_application_group_association" "sampleworkspaceremoteapp" {
workspace_id = azurerm_virtual_desktop_workspace.workspace.id
application_group_id = azurerm_virtual_desktop_application_group.desktopapp.id
}
resource "azurerm_network_interface" "xxxx_nic" {
count=2
name = "xxxx-${count.index}"
location = azurerm_resource_group.eg-RG.location
resource_group_name = azurerm_resource_group.eg-RG.name
ip_configuration {
name = "internal"
subnet_id = azurerm_subnet.xxxxxdefaultSubnet.id
private_ip_address_allocation = "Dynamic"
}
}
resource "azurerm_windows_virtual_machine" "sessionhost" {
depends_on = [
azurerm_network_interface.sessionhost_nic
]
count=2
name = "xxxvm-${count.index}"
resource_group_name = azurerm_resource_group.eg-RG.name
location = azurerm_resource_group.eg-RG.location
size = "Standard_B2MS"
admin_username = "useradmin"
admin_password = "<Password>"
provision_vm_agent = true
network_interface_ids = [azurerm_network_interface.sessionhost_nic.*.id[count.index]]
identity {
type = "SystemAssigned"
}
os_disk {
caching = "ReadWrite"
storage_account_type = "Premium_LRS"
}
source_image_reference {
publisher = "MicrosoftWindowsDesktop"
offer = "Windows-10"
sku = "20h2-evd"
version = "latest"
}
}
locals {
registration_token = "${azurerm_virtual_desktop_host_pool_registration_info.reginfo.token}"
shutdown_command = "shutdown -r -t 10"
exit_code_hack = "exit 0"
commandtorun = "New-Item -Path HKLM:/SOFTWARE/Microsoft/RDInfraAgent/AADJPrivate"
powershell_command = "${local.commandtorun}; ${local.shutdown_command}; ${local.exit_code_hack}"
}
resource "azurerm_virtual_machine_extension" "xxxAVDModule" {
depends_on = [
azurerm_windows_virtual_machine.xxx_sessionhost
]
count = 2
name = "Microsoft.PowerShell.DSC"
virtual_machine_id = azurerm_windows_virtual_machine.avd_sessionhost.*.id[count.index]
publisher = "Microsoft.Powershell"
type = "DSC"
type_handler_version = "2.73"
settings = <<-SETTINGS
{
"modulesUrl": "https://wvdportalstorageblob.blob.core.windows.net/galleryartifacts/Configuration_11-22-2021.zip",
"ConfigurationFunction": "Configuration.ps1\\AddSessionHost",
"Properties" : {
"hostPoolName" : "${azurerm_virtual_desktop_host_pool.new-hp.name}",
"aadJoin": true
}
}
SETTINGS
protected_settings = <<PROTECTED_SETTINGS
{
"properties": {
"registrationInfoToken": "${azurerm_virtual_desktop_host_pool_registration_info.reginfo.token}"
}
}
PROTECTED_SETTINGS
}
resource "azurerm_virtual_machine_extension" "AADLoginForWindows" {
depends_on = [
azurerm_windows_virtual_machine.xxxx_sessionhost,
azurerm_virtual_machine_extension.AVDModule
]
count = 2
name = "AADLoginForWindows"
virtual_machine_id = azurerm_windows_virtual_machine.avd_sessionhost.*.id[count.index]
publisher = "Microsoft.Azure.ActiveDirectory"
type = "AADLoginForWindows"
type_handler_version = "1.0"
auto_upgrade_minor_version = true
}
resource "azurerm_virtual_machine_extension" "xxxxaadjprivate" {
depends_on = [
azurerm_virtual_machine_extension.AADLoginForWindows
]
count = 2
name = "AADJPRIVATE"
virtual_machine_id = azurerm_windows_virtual_machine.avd_sessionhost.*.id[count.index]
publisher = "Microsoft.Compute"
type = "CustomScriptExtension"
type_handler_version = "1.9"
settings = <<SETTINGS
{
"commandToExecute": "powershell.exe -Command \"${local.powershell_command}\""
}
SETTINGS
}
terraform plan:
terraform apply:
VM Joined in AD after deployment:
Virtual Machine Overview: