ユーザー割り当てマネージド ID を使用した Azure VM から Azure Key Vault のシークレット取得を試してみた

## 背景と目的

個人的には、最近の Azure の傾向としてサービスプリンシパル利用よりマネージド ID を推奨しているように感じます。例えば、サービスプリンシパル利用が当たり前だった Azure Automation がマネージド ID に対応するなど、マネージド ID 対応強化の方向なのだと考えられます。セキュリティ的には、サービスプリンシパルのキーやシークレットや証明書を持ち出したら他の環境でも使用できてしまいます。マネージド ID ならトークンの有効期限が 3600 秒なのでサービスプリンシパルに比べてリスクは小さいからです。ということで、ユーザー割り当てマネージド ID を使用した Azure VM から Azure Key Vault のシークレット取得を試してみました。

## 検証用の Azure Key Vault を作成

```bash:bash
# 環境変数をセットします
region=japaneast
prefix=mnrumid

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

# Key Vault を作成します
az keyvault create \
  --name ${prefix}-kv \
  --resource-group ${prefix}-rg

# シークレットを作成します
az keyvault secret set \
  --vault-name ${prefix}-kv \
  --name SQLPassword \
  --value hVFkk965BuUv

# シークレットが取得できるか試します
az keyvault secret show \
  --vault-name ${prefix}-kv \
  --name SQLPassword \
  --query value \
  --output tsv
```

## ユーザー割り当てマネージド ID を使用した Azure VM を作成

```bash:bash
# ユーザー割り当てマネージド ID を作成します
az identity create \
  --name ${prefix} \
  --resource-group ${prefix}-rg

# Azure VM を作成します
az vm create \
  --resource-group ${prefix}-rg \
  --name ${prefix}-vm \
  --os-disk-name ${prefix}-vmOSDisk \
  --image UbuntuLTS \
  --admin-username azureuser \
  --generate-ssh-keys \
  --assign-identity ${prefix} \
  --size Standard_B1s \
  --nsg-rule NONE \
  --storage-sku Standard_LRS \
  --public-ip-address-dns-name ${prefix}

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

## ユーザー割り当てマネージド ID に Azure Key Vault へのアクセスポリシーを割り当て

```bash:bash
# シークレットに対して get list アクセスを許可します
az keyvault set-policy \
  --name ${prefix}-kv \
  --resource-group ${prefix}-rg \
  --secret-permissions get list \
  --object-id $(az identity show \
  --name ${prefix} \
  --resource-group ${prefix}-rg \
  --query principalId \
  --output tsv)
```

## Azure VM から Azure Key Vault シークレットを取得

```bash:bash
# SSH 接続します
ssh azureuser@${prefix}.japaneast.cloudapp.azure.com

# Azure CLI をインストールします
curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash

# Azure CLI でサインインします
az login --identity --allow-no-subscriptions

# シークレットの一覧を取得します
az keyvault secret list \
  --vault-name mnrumid-kv \
  --query "[].name"

[
  "SQLPassword"
]

# シークレットの値を取得します
az keyvault secret show \
  --vault-name mnrumid-kv \
  --name SQLPassword \
  --query value \
  --output tsv

hVFkk965BuUv

# VM から抜けます
exit
```

## 検証環境を削除

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

# 論理的に削除された Key Vault を表示します
az keyvault list-deleted \
  --subscription $(az account show \
  --query id \
  --output tsv) \
  --resource-type vault \
  --query [].name

# Key Vault を消去します
az keyvault purge \
  --subscription $(az account show \
  --query id \
  --output tsv) \
  --name ${prefix}-kv
```

## 参考

https://learn.microsoft.com/ja-jp/azure/active-directory/managed-identities-azure-resources/qs-configure-cli-windows-vm#user-assigned-managed-identity

https://learn.microsoft.com/ja-jp/azure/key-vault/general/key-vault-recovery?tabs=azure-cli