異なる Azure サブスクリプションにある Web サービスを Azure Private Link サービスを使ってアクセスできるか試してみた

## 背景と目的

異なる仮想ネットワーク間でピアリングしてアクセスする例は沢山見てきましたが、異なる仮想ネットワークや異なるサブスクリプションで Azure Private Link サービスを使ってアクセスする例は見たことがありません。料金的にもセキュリティ的にも優っていると思われるサービスが使われ無いのは何故かはわかりません。そこで今回は、異なる Azure サブスクリプションにある Web サービスを Azure Private Link サービスを使ってアクセスできるか試してみました。

## A サブスクリプションで検証用 Web サービスを作成

```bash:bash
# 検証用 Web サービスを作る方のサブスクリプションに切り替えます
az account set -s < A サブスクリプション ID >

# サブスクリプションを確認します
az account show

# 環境変数をセットします
region=japaneast
prefix=mnrpls

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

# Azure 仮想マシンスケールセットを作成します
az vmss create \
  --resource-group ${prefix}-rg \
  --name ${prefix}-vmss \
  --image UbuntuLTS \
  --vm-sku Standard_B1s \
  --storage-sku Standard_LRS \
  --lb-sku Standard \
  --upgrade-policy-mode automatic \
  --admin-username azureuser \
  --generate-ssh-keys

# SSH 接続は不要なのでルールを削除します
az network nsg rule delete \
  --resource-group ${prefix}-rg \
  --nsg-name ${prefix}-vmssNSG \
  --name default-allow-ssh

# 自分の IP アドレスから HTTP アクセスできるようにします
az network nsg rule create \
  --resource-group ${prefix}-rg \
  --name Allow-HTTP \
  --nsg-name ${prefix}-vmssNSG \
  --priority 100 \
  --destination-port-ranges 80 \
  --source-address-prefixes $(curl -s inet-ip.info) \
  --access Allow \
  --protocol Tcp

# Nginx をインストールします
az vmss extension set \
  --publisher Microsoft.Azure.Extensions \
  --version 2.0 \
  --name CustomScript \
  --resource-group ${prefix}-rg \
  --vmss-name ${prefix}-vmss \
  --settings '{"fileUris":["https://raw.githubusercontent.com/Azure-Samples/compute-automation-configurations/master/automate_nginx.sh"],"commandToExecute":"./automate_nginx.sh"}'

# ロードバランサーの IP アドレスを取得します
pip=$(az network public-ip show \
  --resource-group ${prefix}-rg \
  --name ${prefix}-vmssLBPublicIP \
  --query "ipAddress" \
  --output tsv)

# 何回かアクセスして動作を確認します
curl -s $pip

# 下記のようなレスポンスが出力されます
Hello World from host mnrpldc08000002 !
```

## A サブスクリプションで Private Link サービスを作成

```bash:bash
# Private Link サービスのネットワークポリシーを無効にします
az network vnet subnet update \
  --name ${prefix}-vmssSubnet \
  --resource-group ${prefix}-rg \
  --vnet-name ${prefix}-vmssVNET \
  --disable-private-link-service-network-policies true

# ロードバランサーを使用する Private Link サービスを作成します
az network private-link-service create \
  --resource-group ${prefix}-rg \
  --name ${prefix}-pls \
  --vnet-name ${prefix}-vmssVNET \
  --subnet ${prefix}-vmssSubnet \
  --lb-name ${prefix}-vmssLB \
  --lb-frontend-ip-configs loadBalancerFrontEnd

# Private Link サービスの ID を取得します
plsid=$(az network private-link-service show \
  --name ${prefix}-pls \
  --resource-group ${prefix}-rg \
  --query id \
  --output tsv)
```

## B サブスクリプションでアクセス元になる仮想マシンを作成

```bash:bash
# 検証用仮想マシンを作る方のサブスクリプションに切り替えます
az account set -s < B サブスクリプション ID >

# サブスクリプションを確認します
az account show

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

# 検証用仮想マシンを作成します
az vm create \
  --resource-group ${prefix}-rg \
  --name ${prefix}-vm \
  --os-disk-name ${prefix}-vmOSDisk \
  --image UbuntuLTS \
  --size Standard_B1s \
  --admin-username azureuser \
  --generate-ssh-keys \
  --nsg-rule NONE \
  --public-ip-address-dns-name ${prefix}
```

## B サブスクリプションでプライベートエンドポイントを作成

```bash:bash
# プライベートエンドポイントのネットワークポリシーを無効にします
az network vnet subnet update \
  --name ${prefix}-vmSubnet \
  --resource-group ${prefix}-rg \
  --vnet-name ${prefix}-vmVNET \
  --disable-private-endpoint-network-policies true

# プライベートエンドポイントを作成します
az network private-endpoint create \
  --connection-name ${prefix}-pls \
  --name ${prefix}-pe \
  --private-connection-resource-id $plsid \
  --resource-group ${prefix}-rg \
  --manual-request false \
  --subnet ${prefix}-vmSubnet \
  --vnet-name ${prefix}-vmVNET

# プライベートエンドポイントの IP アドレスを取得します
peip=$(az resource show \
  --ids $(az network private-endpoint show \
  --name ${prefix}-pe \
  --resource-group ${prefix}-rg \
  --query networkInterfaces[0].id \
  --output tsv) \
  --query properties.ipConfigurations[0].properties.privateIPAddress \
  --output tsv)
```

## B サブスクリプションから A サブスクリプションの Web サービスへアクセス

```bash:bash
# 検証用 Web サービスにアクセスできるか試します
az vm run-command invoke \
  --command-id RunShellScript \
  --resource-group ${prefix}-rg \
  --name ${prefix}-vm \
  --query "value[0].message" \
  --output tsv \
  --scripts "curl -s $peip"

# 下記のようにアクセスできました
Enable succeeded: 
[stdout]
Hello World from host mnrpldc08000002 !

[stderr]

```

## 検証環境を削除

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

# 検証用 Wdb サービスを作る方のサブスクリプションに切り替えます
az account set -s < A サブスクリプション ID >

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

## 参考

https://learn.microsoft.com/ja-jp/azure/private-link/private-link-service-overview

https://learn.microsoft.com/ja-jp/azure/private-link/create-private-link-service-cli

https://learn.microsoft.com/ja-jp/azure/private-link/create-private-endpoint-cli