Azure Virtual Desktop の Azure AD join （パブリックプレビュー）版を Azure CLI で作ってみた

## 背景と目的

Windows Virtual Desktop (WVD) 改め Azure Virtual Desktop (AVD) の Azure AD join (AD や Azure AD DS は不要) がパブリックプレビューで試せるようになったので、Azure CLI で作ってみました。

## 前提条件

コマンドの実施環境は、Cloud Shell の Azure CLI です。

また、Microsoft 365 開発者プログラムのテナントで「全体管理者」かつ、Azure サブスクリプションの「所有者」権限を持っているアカウントを Azure CLI で使用します。

```bash:bash
az version
{
  "azure-cli": "2.26.0",
  "azure-cli-core": "2.26.0",
  "azure-cli-telemetry": "1.0.6",
  "extensions": {}
}
```

## 実施内容

Azure 管理ポータルから AVD を作成する際の手順や設定値を参考に Azure CLI でリソースを作成していきます。Azure CLI で用意されていないコマンドは、az rest を使用して Azure REST API や Microsoft Graph API を実行します。

```bash:bash
# 環境変数を設定します
region=japaneast
prefix=devavd

# リソースグループを作成します
az group create \
  --name ${prefix}-rg \
  --location $region

# VNET を作成します
az network vnet create \
  --resource-group ${prefix}-rg \
  --name ${prefix}-vnet \
  --address-prefixes 10.1.0.0/16 \
  --subnet-name default-subnet \
  --subnet-prefix 10.1.0.0/24

# NSG を作成します
az network nsg create \
  --resource-group ${prefix}-rg \
  --name ${prefix}-nsg

# NSG をサブネットに紐付けます
az network vnet subnet update \
  --resource-group ${prefix}-rg \
  --vnet-name ${prefix}-vnet \
  --name default-subnet \
  --network-security-group ${prefix}-nsg

# AVD のホストプールを作成します
az desktopvirtualization hostpool create \
  --resource-group ${prefix}-rg \
  --name ${prefix}-hp \
  --location westus2 \
  --host-pool-type Personal \
  --load-balancer-type Persistent \
  --max-session-limit 999999 \
  --personal-desktop-assignment-type Automatic \
  --validation-environment true

# AVD のアプリケーショングループを作成します
az desktopvirtualization applicationgroup create \
  --resource-group ${prefix}-rg \
  --name ${prefix}-dag \
  --location westus2 \
  --application-group-type Desktop \
  --host-pool-arm-path $(az desktopvirtualization hostpool show \
  --resource-group ${prefix}-rg \
  --name ${prefix}-hp \
  --query id \
  --output tsv)

# AVD のワークスペースを作成します
az desktopvirtualization workspace create \
  --resource-group ${prefix}-rg \
  --name ${prefix}-ws \
  --location westus2 \
  --application-group-references $(az desktopvirtualization applicationgroup show \
  --resource-group ${prefix}-rg \
  --name ${prefix}-dag \
  --query id \
  --output tsv)

# AVD のセッションホストに使用するイメージを探します
az vm image list \
  --location $region \
  --publisher microsoftwindowsdesktop \
  --offer Windows-10 \
  --sku 21h1-ent \
  --all \
  --output table

Offer              Publisher                Sku                Urn                                                                                Version
-----------------  -----------------------  -----------------  ---------------------------------------------------------------------------------  ---------------------   
Windows-10         MicrosoftWindowsDesktop  21h1-ent           MicrosoftWindowsDesktop:Windows-10:21h1-ent:19043.1083.2107060627                  19043.1083.2107060627   
Windows-10         MicrosoftWindowsDesktop  21h1-ent           MicrosoftWindowsDesktop:Windows-10:21h1-ent:19043.1110.2107101729                  19043.1110.2107101729   
Windows-10         MicrosoftWindowsDesktop  21h1-ent-g2        MicrosoftWindowsDesktop:Windows-10:21h1-ent-g2:19043.1083.2107060627               19043.1083.2107060627   
Windows-10         MicrosoftWindowsDesktop  21h1-ent-g2        MicrosoftWindowsDesktop:Windows-10:21h1-ent-g2:19043.1110.2107101729               19043.1110.2107101729   
Windows-10         MicrosoftWindowsDesktop  21h1-entn          MicrosoftWindowsDesktop:Windows-10:21h1-entn:19043.1083.2107060627                 19043.1083.2107060627   
Windows-10         MicrosoftWindowsDesktop  21h1-entn          MicrosoftWindowsDesktop:Windows-10:21h1-entn:19043.1110.2107101729                 19043.1110.2107101729   
Windows-10         MicrosoftWindowsDesktop  21h1-entn-g2       MicrosoftWindowsDesktop:Windows-10:21h1-entn-g2:19043.1083.2107060627              19043.1083.2107060627   
Windows-10         MicrosoftWindowsDesktop  21h1-entn-g2       MicrosoftWindowsDesktop:Windows-10:21h1-entn-g2:19043.1110.2107101729              19043.1110.2107101729   
windows-10ent-cpc  MicrosoftWindowsDesktop  21h1-ent-cpc-m365  MicrosoftWindowsDesktop:windows-10ent-cpc:21h1-ent-cpc-m365:19043.1052.2106081154  19043.1052.2106081154   
windows-10ent-cpc  MicrosoftWindowsDesktop  21h1-ent-cpc-m365  MicrosoftWindowsDesktop:windows-10ent-cpc:21h1-ent-cpc-m365:19043.985.2105141123   19043.985.2105141123    
windows-10ent-cpc  MicrosoftWindowsDesktop  21h1-ent-cpc-os    MicrosoftWindowsDesktop:windows-10ent-cpc:21h1-ent-cpc-os:19043.1052.2106081154    19043.1052.2106081154   
windows-10ent-cpc  MicrosoftWindowsDesktop  21h1-ent-cpc-os    MicrosoftWindowsDesktop:windows-10ent-cpc:21h1-ent-cpc-os:19043.985.2105141123     19043.985.2105141123    

# VM のローカルアカウントで使用するパスワードを生成します
vmpasswd=$(openssl rand -base64 16)
echo $vmpasswd

# VM を作成します
az vm create \
  --resource-group ${prefix}-rg \
  --name ${prefix}-vm \
  --os-disk-name ${prefix}-vmOSDisk \
  --image MicrosoftWindowsDesktop:Windows-10:21h1-ent:19043.1110.2107101729 \
  --license-type Windows_Client \
  --size Standard_A2_v2 \
  --admin-username azureuser \
  --admin-password $vmpasswd \
  --assign-identity \
  --vnet-name ${prefix}-vnet \
  --subnet default-subnet \
  --nsg "" \
  --public-ip-address "" \
  --storage-sku Standard_LRS

# VM のブート診断を有効にします
az vm boot-diagnostics enable \
  --resource-group ${prefix}-rg \
  --name ${prefix}-vm

# AVD のセッションホストとして VM を登録するためのトークンを生成します
regtoken=$(az desktopvirtualization hostpool update \
  --resource-group ${prefix}-rg \
  --name ${prefix}-hp \
  --registration-info expiration-time="$(date -u --iso-8601=seconds -d '1 day')" registration-token-operation="Update" \
  --query registrationInfo.token \
  --output tsv)

# VM の拡張機能を使用して VM を AVD のセッションホストに登録します
az vm extension set \
  --resource-group ${prefix}-rg \
  --vm-name ${prefix}-vm \
  --name DSC \
  --publisher Microsoft.Powershell \
  --version 2.73 \
  --no-auto-upgrade-minor-version false \
  --settings "{
    \"modulesUrl\": \"https://wvdportalstorageblob.blob.core.windows.net/galleryartifacts/Configuration_6-1-2021.zip\",
    \"configurationFunction\": \"Configuration.ps1\\\\AddSessionHost\",
    \"properties\": {
        \"hostPoolName\": \"${prefix}-hp\",
        \"registrationInfoToken\": \"$regtoken\",
        \"aadJoin\": true
    }
  }"

# VM の拡張機能を使用して Azure AD join を行います
az vm extension set \
  --resource-group ${prefix}-rg \
  --vm-name ${prefix}-vm \
  --name AADLoginForWindows \
  --publisher Microsoft.Azure.ActiveDirectory \
  --version 1.0 \
  --no-auto-upgrade-minor-version false

# UPN に使用するドメインを選択します
domain=$(az rest \
  --method get \
  --uri https://graph.microsoft.com/v1.0/domains \
  --query value[1].id \
  --output tsv)

# AD ユーザーが使用するパスワードを生成します
userpasswd=$(openssl rand -base64 16)
echo $userpasswd

# AD ユーザーを作成します
az ad user create \
  --display-name ${prefix}user \
  --password $userpasswd \
  --user-principal-name ${prefix}user@$domain

# Microsoft 365 開発者プログラムの E5 ライセンスの ID を探します
az rest \
  --method get \
  --uri https://graph.microsoft.com/v1.0/subscribedSkus \
  --query "value[].{skuId:skuId, skuPartNumber:skuPartNumber}[?contains(skuPartNumber,'DEVELOPERPACK_E5')]"
[
  {
    "skuId": "c42b9cae-ea4f-4ab7-9717-81576235ccac",
    "skuPartNumber": "DEVELOPERPACK_E5"
  }
]

# AD ユーザーのプロパティ（利用場所）を設定します
az rest \
  --method patch \
  --uri https://graph.microsoft.com/v1.0/users/$(az ad user show \
  --id ${prefix}user@$domain \
  --query objectId \
  --output tsv) \
  --body '{
    "usageLocation": "JP"
  }'

# AD ユーザーに E5 ライセンスを付与します
az rest \
  --method post \
  --uri https://graph.microsoft.com/v1.0/users/$(az ad user show \
  --id ${prefix}user@$domain \
  --query objectId \
  --output tsv)/assignLicense \
  --body '{
    "addLicenses": [
      {
        "disabledPlans": [],
        "skuId": "c42b9cae-ea4f-4ab7-9717-81576235ccac"
      }
    ],
    "removeLicenses": []
  }'

# セキュリティグループを作成します
az ad group create \
  --display-name ${prefix}-group \
  --mail-nickname ${prefix}-group

# セキュリティグループにユーザーを追加します
az ad group member add \
  --group ${prefix}-group \
  --member-id $(az ad user list \
  --display-name ${prefix}user \
  --query [].objectId \
  --output tsv)

# AVD のアプリケーショングループにセキュリティグループを登録します
az role assignment create \
  --assignee $(az ad group show \
  --group ${prefix}-group \
  --query objectId \
  --output tsv) \
  --role "Desktop Virtualization User" \
  --scope $(az desktopvirtualization applicationgroup show \
  --resource-group ${prefix}-rg \
  --name ${prefix}-dag \
  --query id \
  --output tsv)

# リソースグループに対して Virtual Machine Administrator Login または Virtual Machine User Login ロールをセキュリティグループに付与します
az role assignment create \
  --assignee $(az ad group show \
  --group ${prefix}-group \
  --query objectId \
  --output tsv) \
  --role "Virtual Machine Administrator Login" \
  --scope $(az group show \
  --name ${prefix}-rg \
  --query id \
  --output tsv)

# Azure AD join していない PC からも AVD セッションホストにログインできるよう RDP プロパティを設定します
az desktopvirtualization hostpool update \
  --resource-group ${prefix}-rg \
  --name ${prefix}-hp \
  --custom-rdp-property "targetisaadjoined:i:1"

# AVD のセッションホストで下記理由により「使用不可」状態となっている場合は、一度 VM を再起動してみてください
{
  "healthCheckName": "DomainJoinedCheck",
  "healthCheckResult": "HealthCheckFailed",
  "additionalFailureDetails": {
    "message": "SessionHost unhealthy: SessionHost is not joined to a domain",
    "errorCode": -2147467259,
    "lastHealthCheckDateTime": "2021-07-20T11:35:45.220726Z"
  }
}
```

## 実施結果

Azure Virtual Desktop に Web クライアントでアクセスしました。

[https://rdweb.wvd.microsoft.com/arm/webclient/index.html](https://rdweb.wvd.microsoft.com/arm/webclient/index.html)

先ほど作成した AD ユーザーでログインします。

![avd-aad-01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/675885/c3d23385-11be-2218-01d6-88fe48ab433d.png)

「SessionDe-ktop」をクリックし「許可」をクリックします。

![avd-aad-02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/675885/5f750d79-5c52-076b-b070-a338d4769de8.png)

パスワードを入力して「送信」をクリックします。（＊ example.com はスクショ用に書き換えていますが、ユーザー名は変更の必要はありません）

![avd-aad-03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/675885/028776ab-a03e-5186-4196-b1508a062535.png)

初回はユーザープロファイルを作成するために多少時間がかかります。

![avd-aad-04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/675885/53297014-5317-0cf6-f6f7-ab446b6006d3.png)

Azure Virtual Desktop (AVD) の Azure AD join で VM にログインできました。

![avd-aad-05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/675885/cf99fc99-4f15-4266-0732-0153e245ec24.png)

## 参考

試しに作ったリソースを削除する場合は、下記のコマンドを参考にしてください。

```bash:bash
# リソースグループを削除します
az group delete \
  --name ${prefix}-rg

# AVD のホストプールが残るので強制削除します
az desktopvirtualization hostpool delete \
  --resource-group ${prefix}-rg \
  --name ${prefix}-hp \
  --force true

# もう一度リソースグループを削除します
az group delete \
  --name ${prefix}-rg

# セキュリティグループを削除します
az ad group delete \
  --group ${prefix}-group

# AD ユーザーを削除します
az ad user delete \
  --id ${prefix}user@$domain

# Azure AD join したデバイスを探します（例）
az rest \
  --method get \
  --uri https://graph.microsoft.com/v1.0/devices \
  --query "value[].{id:id, displayName:displayName}[?contains(displayName, '${prefix}-vm')]"
[
  {
    "displayName": "devavd-vm",
    "id": "e490202d-648a-4d29-ab3a-37de0f2de61b"
  }
]

# Azure AD join したデバイスを削除します（例）
az rest \
  --method delete \
  --uri https://graph.microsoft.com/v1.0/devices/e490202d-648a-4d29-ab3a-37de0f2de61b
```

下記は、参考サイトです。

[General availability: Deliver a secure hybrid workplace with Azure Virtual Desktop and Windows 365](https://azure.microsoft.com/ja-jp/updates/new-ways-to-deliver-a-secure-hybrid-workplace-with-azure-virtual-desktop-and-windows-365/)

[New ways to deliver a secure hybrid workplace with Azure Virtual Desktop and Windows 365](https://techcommunity.microsoft.com/t5/azure-virtual-desktop/new-ways-to-deliver-a-secure-hybrid-workplace-with-azure-virtual/ba-p/2547291)

[Deploy Azure AD joined virtual machines in Azure Virtual Desktop](https://docs.microsoft.com/ja-jp/azure/virtual-desktop/deploy-azure-ad-joined-vm)

[Start Virtual Machine on Connect (preview)](https://docs.microsoft.com/en-us/azure/virtual-desktop/start-virtual-machine-connect)

[Microsoft 365 開発者プログラム](https://developer.microsoft.com/ja-jp/microsoft-365/dev-program)