【Microsoft Azure】AVDセッションホストを自動作成したい

価格面やセキュリティや資産管理の都合上、職場によってはクラウド上にVMを作成したままにすることができないルールがあり、都度都度作成が必要なケースがある。

自分の環境もAVDセッションホストでの検証が必要だけど、都度作成しなきゃいけない、でもAVDセッションホストは作るのがめんどくさい...。

ということで、自動作成する方法を考えてみた。

# 目次
[1. 構成](#1-構成)
[2. スクリプト](#2-スクリプト)
[3. あとがき](#3-あとがき)

# 1. スクリプト
AVDセッションホストを作成するAzure Powershellスクリプトを作成し、
それをAzure Automationで業務開始前に実行することで、
業務開始時からAVDセッションホストを使えるようになる目論見。

# 2. スクリプト
```createAvdSessionhost.ps1
###################################
#
# Common variable
#
###################################
$shInitialNumber = 1
$shCount = 1
$startIpAddress = "10.0.2.101"

$rgName = "rg-common"
$shPrefix = "sh"
$location = "japaneast"
$vnetName = "vnet-common"
$snetName = "snet-avd"
$vmSize = "Standard_D2s_v3"
$diskType = "Standard_LRS"
$vmPassword = "P@ssw0rd"
$vmUsername = "local-admin"
$domain = "<domain name>"
$domainUserName = "<domain>\<user>" # username\domain
$domainUserPass = "<P@ssw0rd>"
$hpName = "hp-1"

###################################
#
# Main function
#
###################################
function main {

	$parameters = @{
		HostPoolName = $hpName
		ResourceGroupName = $rgName
		ExpirationTime = $((Get-Date).ToUniversalTime().AddHours(24).ToString('yyyy-MM-ddTHH:mm:ss.fffffffZ'))
	}
	$token = New-AzWvdRegistrationInfo @parameters

	for($i = 0; $i -lt $shCount; $i++) {

		$shNumber = $shInitialNumber + $i
		$shName = $shPrefix + "-" + $shNumber
		$nicName = $shName + "-nic"
		$osDiskName = $shName + "-OsDisk"

		$startIpAddressFourthOctet = ([regex]::Matches($startIpAddress, "[0-9]+$")).Value
		[Int32]$startIpAddressFourthOctet = $startIpAddressFourthOctet
		$newIpAddressFourthOctet = $startIpAddressFourthOctet + $i
		$ipAddress = $startIpAddress -replace $startIpAddressFourthOctet,$newIpAddressFourthOctet

		Write-Host "Creating $shName"

		# create vm
		$vmConfig = New-AzVMConfig -Name $shName -VMSize $vmSize

		$vnet = Get-AzVirtualNetwork -Name $vnetName -ResourceGroupName $rgName
		$subnet = Get-AzVirtualNetworkSubnetConfig -Name $snetName -VirtualNetwork $vnet
		$ipConfig = New-AzNetworkInterfaceIpConfig -Name "IPConfig1" -PrivateIpAddressVersion IPv4 -PrivateIpAddress $ipAddress -SubnetId $subnet.Id
		$nic = New-AzNetworkInterface -Name $nicName -ResourceGroupName $rgName -Location $location  -IpConfiguration $ipConfig
		
		$vmConfig = Add-AzVMNetworkInterface -VM $vmConfig -Id $nic.Id
		$vmConfig = Set-AzVMSourceImage -VM $vmConfig -PublisherName  MicrosoftWindowsDesktop  -Offer Windows-10 -Skus win10-21h2-avd -Version latest
		$vmConfig = Set-AzVMOSDisk -VM $vmConfig -Name $osDiskName -DiskSizeInGB 128 -StorageAccountType $diskType -CreateOption FromImage

		$SecurePassword = ConvertTo-SecureString $vmPassword -AsPlainText -Force
		$Credential = New-Object System.Management.Automation.PSCredential ($vmUsername, $SecurePassword); 
		$vmConfig = Set-AzVMOperatingSystem -VM $vmConfig -Credential $Credential -Windows -ComputerName $shName

		New-AzVM -ResourceGroupName $rgName -Location $location -VM $vmConfig
		
		# domain join
		$domainPass = ConvertTo-SecureString $domainUserPass -AsPlainText -Force
		$domainCred = New-Object System.Management.Automation.PSCredential ($domainUserName, $domainPass); 
		Set-AzVMADDomainExtension `
			-ResourceGroupName $rgName `
			-VMName $shName `
			-Name "AADLoginForWindows" `
			-DomainName $domain `
			-Credential $domainCred `
			-JoinOption 0x00000001 -Restart

		# register to hostpool
		$Settings = '{
			"modulesUrl" : "https://wvdportalstorageblob.blob.core.windows.net/galleryartifacts/Configuration_09-08-2022.zip",
			"configurationFunction" : "Configuration.ps1\\AddSessionHost",
			"properties" : {
				"HostPoolName" : "' + $hpName + '",
				"aadJoin" : true
			}
		}' | ConvertFrom-Json -AsHashtable

		$ProtectedSettings = '{
			"properties" : {
				"registrationInfoToken" : "' + $token.Token + '"
			}
		}' | ConvertFrom-Json -AsHashtable

		Set-AzVMExtension `
			-ResourceGroupName $rgName `
			-Location $location `
			-VMName $shName `
			-Name "Microsoft.PowerShell.DSC" `
			-Publisher "Microsoft.Powershell" `
			-ExtensionType "DSC" `
			-TypeHandlerVersion "2.73" `
			-Settings $Settings `
			-ProtectedSettings $ProtectedSettings `
			-AsJob | Out-Null
	}
}

###################################
#
# Main process
#
###################################
main
```

# 2. あとがき
その日のうちに作成したリソースを削除しないといけないので、
そのうち削除するスクリプトも作成したい。