Terraform Azure VM 扩展不会将 VM 加入到 Azure 虚拟桌面的 Azure Active Directory
Terraform Azure VM extension does not join VM to Azure Active Directory for Azure Virtual Desktop
以 https://techcommunity.microsoft.com/t5/azure-virtual-desktop/arm-avd-with-terraform/m-p/2639806 为灵感,我想部署 AVD,但使用 Terraform 将 AAD 加入虚拟机。我根据文章在 Terraform 中定义了一个 VM 和扩展以及 Azure 虚拟桌面部署(主机池、应用程序组、工作区),并且我已经根据将 VM 添加到主机时由 Azure 生成的 ARM 模板调整了扩展池并加入 AAD 'manually'/通过门户。
terraform 已应用且扩展 运行 成功通过,但 VM 未加入域。
当我查看已部署 VM 上的日志时,主要错误之一是 'DsrCmdAzureHelper::GetTenantId: Unable to get Tenant Id, status code 400'。从 Targeting host name:169.254.169.254, url path: /metadata/identity/info?api-version=2018-02-01 和 'identity not found' 错误如下。
这里有什么问题?以下是扩展的地形,如果需要更多请告诉我。
locals {
registration_token = azurerm_virtual_desktop_host_pool.hostpool.registration_info[0].token
}
resource "azurerm_virtual_machine_extension" "domain_join" {
count = var.rdsh_count
name = "${var.prefix}-${count.index + 1}-domainJoin"
virtual_machine_id = azurerm_windows_virtual_machine.avd_vm.*.id[count.index]
publisher = "Microsoft.Azure.ActiveDirectory"
type = "AADLoginForWindows"
type_handler_version = "1.0"
auto_upgrade_minor_version = true
depends_on = [
azurerm_virtual_machine_extension.vmext_dsc
]
}
resource "azurerm_virtual_machine_extension" "vmext_dsc" {
count = var.rdsh_count
name = "${var.prefix}${count.index + 1}-avd_dsc"
# virtual_machine_id = azurerm_windows_virtual_machine.avd_vm.*.id[count.index]
virtual_machine_id = azurerm_windows_virtual_machine.avd_vm.*.id[count.index]
publisher = "Microsoft.Powershell"
type = "DSC"
type_handler_version = "2.73"
auto_upgrade_minor_version = true
settings = <<-SETTINGS
{
"modulesUrl": "https://wvdportalstorageblob.blob.core.windows.net/galleryartifacts/Configuration_9-30-2021.zip",
"configurationFunction": "Configuration.ps1\AddSessionHost",
"properties": {
"HostPoolName":"${azurerm_virtual_desktop_host_pool.hostpool.name}",
"aadJoin": true
}
}
SETTINGS
protected_settings = <<PROTECTED_SETTINGS
{
"properties": {
"registrationInfoToken": "${local.registration_token}"
}
}
PROTECTED_SETTINGS
depends_on = [
azurerm_virtual_desktop_host_pool.hostpool
]
}
我在我的环境中测试了它,问题如下:
根据这个 Microsoft Q & A Thread
中的讨论,提到一个键 AADJPrivate
应该出现在路径 HKLM\Software\microsoft\RDInfraAgent
下,如果它不存在,则 VM 将正确添加扩展但无法与 Azure AD 加入域.
因此,作为解决方案,我在代码中更改了一些内容,例如:
- The host had
custom_rdp_properties
as "audiocapturemode:i:1;audiomode:i:0;"
instead ,added "audiocapturemode:i:1;audiomode:i:0;targetisaadjoined:i:1;"
.
- Provided
auto_upgrade_minor_version = true
in the AADLoginForWindows extension.
- Added another Custom script extension to add the key
AADJPRIVATE
for the VM's.
修改后,我尝试了如下内容:
provider "azurerm" {
features {}
version = "2.90.0"
}
provider "azuread" {}
data "azuread_group" "aad_group" {
display_name = "xxxx"
security_enabled = true
}
data "azurerm_role_definition" "vm_user_login" {
name = "Virtual Machine User Login"
}
resource "azurerm_role_assignment" "vm_user_role" {
scope = azurerm_resource_group.rg-avd.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 = "Desktop Virtualization 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" "rg-avd" {
name = "avd-test"
location = "West Europe"
}
resource "azurerm_virtual_network" "vnet" {
name = "avd-vnet"
location = azurerm_resource_group.rg-avd.location
resource_group_name = azurerm_resource_group.rg-avd.name
address_space = ["10.0.0.0/16"]
}
resource "azurerm_subnet" "defaultSubnet" {
name = "avd-subnet"
resource_group_name = azurerm_resource_group.rg-avd.name
virtual_network_name = azurerm_virtual_network.vnet.name
address_prefixes = ["10.0.0.0/24"]
}
resource "azurerm_network_security_group" "nsg" {
name = "avd-nsg"
location = azurerm_resource_group.rg-avd.location
resource_group_name = azurerm_resource_group.rg-avd.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.defaultSubnet.id
network_security_group_id = azurerm_network_security_group.nsg.id
}
resource "time_rotating" "avd_token" {
rotation_days = 30
}
resource "azurerm_virtual_desktop_host_pool" "avd-hp" {
location = azurerm_resource_group.rg-avd.location
resource_group_name = azurerm_resource_group.rg-avd.name
name = "testhostpool"
friendly_name = "ansupool"
validate_environment = true
start_vm_on_connect = true
custom_rdp_properties = "audiocapturemode:i:1;audiomode:i:0;targetisaadjoined:i:1;"
description = "ansu host-poool demo"
type = "Pooled"
maximum_sessions_allowed = 10
load_balancer_type = "DepthFirst"
registration_info {
expiration_date = time_rotating.avd_token.rotation_rfc3339
}
}
resource "azurerm_virtual_desktop_application_group" "desktopapp" {
name = "ANS-Desktop"
location = azurerm_resource_group.rg-avd.location
resource_group_name = azurerm_resource_group.rg-avd.name
type = "Desktop"
host_pool_id = azurerm_virtual_desktop_host_pool.avd-hp.id
friendly_name = "ANS-application"
description = "ansuman applications"
}
resource "azurerm_virtual_desktop_workspace" "workspace" {
name = "ANS-WORKSPACE"
location = azurerm_resource_group.rg-avd.location
resource_group_name = azurerm_resource_group.rg-avd.name
friendly_name = "ANS-AVD_WRSPC"
description = "Work Purporse"
}
resource "azurerm_virtual_desktop_workspace_application_group_association" "workspaceremoteapp" {
workspace_id = azurerm_virtual_desktop_workspace.workspace.id
application_group_id = azurerm_virtual_desktop_application_group.desktopapp.id
}
resource "azurerm_network_interface" "sessionhost_nic" {
count=2
name = "nic-ansu-${count.index}"
location = azurerm_resource_group.rg-avd.location
resource_group_name = azurerm_resource_group.rg-avd.name
ip_configuration {
name = "internal"
subnet_id = azurerm_subnet.defaultSubnet.id
private_ip_address_allocation = "Dynamic"
}
}
resource "azurerm_windows_virtual_machine" "avd_sessionhost" {
depends_on = [
azurerm_network_interface.sessionhost_nic
]
count=2
name = "ansuvm-${count.index}"
resource_group_name = azurerm_resource_group.rg-avd.name
location = azurerm_resource_group.rg-avd.location
size = "Standard_B2MS"
admin_username = "adminuser"
admin_password = "Password@1234"
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.avd-hp.registration_info[0].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" "AVDModule" {
depends_on = [
azurerm_windows_virtual_machine.avd_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.avd-hp.name}",
"aadJoin": true
}
}
SETTINGS
protected_settings = <<PROTECTED_SETTINGS
{
"properties": {
"registrationInfoToken": "${local.registration_token}"
}
}
PROTECTED_SETTINGS
}
resource "azurerm_virtual_machine_extension" "AADLoginForWindows" {
depends_on = [
azurerm_windows_virtual_machine.avd_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" "addaadjprivate" {
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
}
输出:
注意:根据此 GitHub Issue
,您必须使用 azurerm 提供程序版本 2.90.0.
以 https://techcommunity.microsoft.com/t5/azure-virtual-desktop/arm-avd-with-terraform/m-p/2639806 为灵感,我想部署 AVD,但使用 Terraform 将 AAD 加入虚拟机。我根据文章在 Terraform 中定义了一个 VM 和扩展以及 Azure 虚拟桌面部署(主机池、应用程序组、工作区),并且我已经根据将 VM 添加到主机时由 Azure 生成的 ARM 模板调整了扩展池并加入 AAD 'manually'/通过门户。
terraform 已应用且扩展 运行 成功通过,但 VM 未加入域。
当我查看已部署 VM 上的日志时,主要错误之一是 'DsrCmdAzureHelper::GetTenantId: Unable to get Tenant Id, status code 400'。从 Targeting host name:169.254.169.254, url path: /metadata/identity/info?api-version=2018-02-01 和 'identity not found' 错误如下。
这里有什么问题?以下是扩展的地形,如果需要更多请告诉我。
locals {
registration_token = azurerm_virtual_desktop_host_pool.hostpool.registration_info[0].token
}
resource "azurerm_virtual_machine_extension" "domain_join" {
count = var.rdsh_count
name = "${var.prefix}-${count.index + 1}-domainJoin"
virtual_machine_id = azurerm_windows_virtual_machine.avd_vm.*.id[count.index]
publisher = "Microsoft.Azure.ActiveDirectory"
type = "AADLoginForWindows"
type_handler_version = "1.0"
auto_upgrade_minor_version = true
depends_on = [
azurerm_virtual_machine_extension.vmext_dsc
]
}
resource "azurerm_virtual_machine_extension" "vmext_dsc" {
count = var.rdsh_count
name = "${var.prefix}${count.index + 1}-avd_dsc"
# virtual_machine_id = azurerm_windows_virtual_machine.avd_vm.*.id[count.index]
virtual_machine_id = azurerm_windows_virtual_machine.avd_vm.*.id[count.index]
publisher = "Microsoft.Powershell"
type = "DSC"
type_handler_version = "2.73"
auto_upgrade_minor_version = true
settings = <<-SETTINGS
{
"modulesUrl": "https://wvdportalstorageblob.blob.core.windows.net/galleryartifacts/Configuration_9-30-2021.zip",
"configurationFunction": "Configuration.ps1\AddSessionHost",
"properties": {
"HostPoolName":"${azurerm_virtual_desktop_host_pool.hostpool.name}",
"aadJoin": true
}
}
SETTINGS
protected_settings = <<PROTECTED_SETTINGS
{
"properties": {
"registrationInfoToken": "${local.registration_token}"
}
}
PROTECTED_SETTINGS
depends_on = [
azurerm_virtual_desktop_host_pool.hostpool
]
}
我在我的环境中测试了它,问题如下:
根据这个 Microsoft Q & A Thread
中的讨论,提到一个键 AADJPrivate
应该出现在路径 HKLM\Software\microsoft\RDInfraAgent
下,如果它不存在,则 VM 将正确添加扩展但无法与 Azure AD 加入域.
因此,作为解决方案,我在代码中更改了一些内容,例如:
- The host had
custom_rdp_properties
as"audiocapturemode:i:1;audiomode:i:0;"
instead ,added"audiocapturemode:i:1;audiomode:i:0;targetisaadjoined:i:1;"
.- Provided
auto_upgrade_minor_version = true
in the AADLoginForWindows extension.- Added another Custom script extension to add the key
AADJPRIVATE
for the VM's.
修改后,我尝试了如下内容:
provider "azurerm" {
features {}
version = "2.90.0"
}
provider "azuread" {}
data "azuread_group" "aad_group" {
display_name = "xxxx"
security_enabled = true
}
data "azurerm_role_definition" "vm_user_login" {
name = "Virtual Machine User Login"
}
resource "azurerm_role_assignment" "vm_user_role" {
scope = azurerm_resource_group.rg-avd.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 = "Desktop Virtualization 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" "rg-avd" {
name = "avd-test"
location = "West Europe"
}
resource "azurerm_virtual_network" "vnet" {
name = "avd-vnet"
location = azurerm_resource_group.rg-avd.location
resource_group_name = azurerm_resource_group.rg-avd.name
address_space = ["10.0.0.0/16"]
}
resource "azurerm_subnet" "defaultSubnet" {
name = "avd-subnet"
resource_group_name = azurerm_resource_group.rg-avd.name
virtual_network_name = azurerm_virtual_network.vnet.name
address_prefixes = ["10.0.0.0/24"]
}
resource "azurerm_network_security_group" "nsg" {
name = "avd-nsg"
location = azurerm_resource_group.rg-avd.location
resource_group_name = azurerm_resource_group.rg-avd.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.defaultSubnet.id
network_security_group_id = azurerm_network_security_group.nsg.id
}
resource "time_rotating" "avd_token" {
rotation_days = 30
}
resource "azurerm_virtual_desktop_host_pool" "avd-hp" {
location = azurerm_resource_group.rg-avd.location
resource_group_name = azurerm_resource_group.rg-avd.name
name = "testhostpool"
friendly_name = "ansupool"
validate_environment = true
start_vm_on_connect = true
custom_rdp_properties = "audiocapturemode:i:1;audiomode:i:0;targetisaadjoined:i:1;"
description = "ansu host-poool demo"
type = "Pooled"
maximum_sessions_allowed = 10
load_balancer_type = "DepthFirst"
registration_info {
expiration_date = time_rotating.avd_token.rotation_rfc3339
}
}
resource "azurerm_virtual_desktop_application_group" "desktopapp" {
name = "ANS-Desktop"
location = azurerm_resource_group.rg-avd.location
resource_group_name = azurerm_resource_group.rg-avd.name
type = "Desktop"
host_pool_id = azurerm_virtual_desktop_host_pool.avd-hp.id
friendly_name = "ANS-application"
description = "ansuman applications"
}
resource "azurerm_virtual_desktop_workspace" "workspace" {
name = "ANS-WORKSPACE"
location = azurerm_resource_group.rg-avd.location
resource_group_name = azurerm_resource_group.rg-avd.name
friendly_name = "ANS-AVD_WRSPC"
description = "Work Purporse"
}
resource "azurerm_virtual_desktop_workspace_application_group_association" "workspaceremoteapp" {
workspace_id = azurerm_virtual_desktop_workspace.workspace.id
application_group_id = azurerm_virtual_desktop_application_group.desktopapp.id
}
resource "azurerm_network_interface" "sessionhost_nic" {
count=2
name = "nic-ansu-${count.index}"
location = azurerm_resource_group.rg-avd.location
resource_group_name = azurerm_resource_group.rg-avd.name
ip_configuration {
name = "internal"
subnet_id = azurerm_subnet.defaultSubnet.id
private_ip_address_allocation = "Dynamic"
}
}
resource "azurerm_windows_virtual_machine" "avd_sessionhost" {
depends_on = [
azurerm_network_interface.sessionhost_nic
]
count=2
name = "ansuvm-${count.index}"
resource_group_name = azurerm_resource_group.rg-avd.name
location = azurerm_resource_group.rg-avd.location
size = "Standard_B2MS"
admin_username = "adminuser"
admin_password = "Password@1234"
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.avd-hp.registration_info[0].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" "AVDModule" {
depends_on = [
azurerm_windows_virtual_machine.avd_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.avd-hp.name}",
"aadJoin": true
}
}
SETTINGS
protected_settings = <<PROTECTED_SETTINGS
{
"properties": {
"registrationInfoToken": "${local.registration_token}"
}
}
PROTECTED_SETTINGS
}
resource "azurerm_virtual_machine_extension" "AADLoginForWindows" {
depends_on = [
azurerm_windows_virtual_machine.avd_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" "addaadjprivate" {
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
}
输出:
注意:根据此 GitHub Issue
,您必须使用 azurerm 提供程序版本 2.90.0.