オレ流 Azure RBAC のカスタム ロールの作り方 (2) ~ VNET 統合の場合

今回はですね、こちらのオレ流 Azure RBAC のカスタム ロールの作り方 (1)の手順を使って、App Service (Web Apps や Function App)の VNET 統合を Azure CLI から設定できるカスタム ロールを作ってみますよ。
VNET 統合は App Service だけでなく、VNET/Subnet も操作するので、割と面倒複雑なカスタム ロールになります。

ではやってみます。

1. Azure CLI を使って必要な Azure REST API を確認する

まず共同作成者ロールのユーザーで下記 Azure CLI で実行してみます。

az webapp vnet-integration add --id <WebApp のリソース ID> --vnet <VNET のリソース ID> --subnet <Subnet 名> --debug

このコマンドに出力されるログから、grep 等で Azure REST API のアクセス ログを探すと、以下の 17 件が抽出できます。

DEBUG: urllib3.connectionpool: https://management.azure.com:443 "GET /subscriptions/.../providers/Microsoft.Network/virtualNetworks?api-version=... HTTP/1.1" 200 749
DEBUG: urllib3.connectionpool: https://management.azure.com:443 "GET /subscriptions/.../resourceGroups/.../providers/Microsoft.Web/sites/...?api-version=... HTTP/1.1" 200 None
DEBUG: urllib3.connectionpool: https://management.azure.com:443 "GET /subscriptions/.../resourceGroups/.../providers/Microsoft.Web/sites/...?api-version=... HTTP/1.1" 200 None
DEBUG: urllib3.connectionpool: https://management.azure.com:443 "GET /subscriptions/.../resourceGroups/.../providers/Microsoft.Web/sites/.../config/web?api-version=... HTTP/1.1" 200 None
DEBUG: urllib3.connectionpool: https://management.azure.com:443 "POST /subscriptions/.../resourceGroups/.../providers/Microsoft.Web/sites/.../publishxml?api-version=... HTTP/1.1" 200 1589
DEBUG: urllib3.connectionpool: https://management.azure.com:443 "GET /subscriptions/.../resourceGroups/rg-linux-plan/providers/Microsoft.Web/serverfarms/...?api-version=... HTTP/1.1" 200 None
DEBUG: urllib3.connectionpool: https://management.azure.com:443 "GET /subscriptions/.../resourceGroups/.../providers/Microsoft.Network/virtualNetworks/...?api-version=... HTTP/1.1" 200 None
DEBUG: urllib3.connectionpool: https://management.azure.com:443 "GET /subscriptions/.../locations?api-version=... HTTP/1.1" 200 4592
DEBUG: urllib3.connectionpool: https://management.azure.com:443 "GET /subscriptions/.../locations?api-version=... HTTP/1.1" 200 4592
DEBUG: urllib3.connectionpool: https://management.azure.com:443 "GET /subscriptions/.../resourceGroups/.../providers/Microsoft.Network/virtualNetworks/.../subnets/...?api-version=... HTTP/1.1" 200 None
DEBUG: urllib3.connectionpool: https://management.azure.com:443 "PUT /subscriptions/.../resourceGroups/.../providers/Microsoft.Network/virtualNetworks/.../subnets/...?api-version=... HTTP/1.1" 200 None
DEBUG: urllib3.connectionpool: https://management.azure.com:443 "GET /subscriptions/.../providers/Microsoft.Network/locations/.../operations/...?api-version=... HTTP/1.1" 200 None
DEBUG: urllib3.connectionpool: https://management.azure.com:443 "GET /subscriptions/.../resourceGroups/.../providers/Microsoft.Network/virtualNetworks/.../subnets/...?api-version=... HTTP/1.1" 200 None
DEBUG: urllib3.connectionpool: https://management.azure.com:443 "PATCH /subscriptions/.../resourceGroups/.../providers/Microsoft.Web/sites/...?api-version=... HTTP/1.1" 200 None
DEBUG: urllib3.connectionpool: https://management.azure.com:443 "GET /subscriptions/.../resourceGroups/.../providers/Microsoft.Web/sites/.../config/web?api-version=... HTTP/1.1" 200 None
DEBUG: urllib3.connectionpool: https://management.azure.com:443 "GET /subscriptions/.../resourceGroups/.../providers/Microsoft.Web/sites/.../config/web?api-version=... HTTP/1.1" 200 None
DEBUG: urllib3.connectionpool: https://management.azure.com:443 "PATCH /subscriptions/.../resourceGroups/.../providers/Microsoft.Web/sites/.../config/web?api-version=... HTTP/1.1" 200 None

結構いろんなところにリクエストを投げてますね。

2. HTTP メソッドとエンドポイント URL からアクションを組み立てる

上の 17 件のアクセス ログ、それぞれについて、リソース プロバイダーとリソース タイプ、HTTP メソッドを元にして構築し重複分を除きます。

    "Microsoft.Network/locations/operations/read",
    "Microsoft.Network/virtualNetworks/read",
    "Microsoft.Network/virtualNetworks/subnets/read",
    "Microsoft.Network/virtualNetworks/subnets/write",
    "Microsoft.Resources/subscriptions/locations/read",
    "Microsoft.Web/serverfarms/read",
    "Microsoft.Web/sites/config/read",
    "Microsoft.Web/sites/config/write",
    "Microsoft.Web/sites/publishxml/action",
    "Microsoft.Web/sites/read",
    "Microsoft.Web/sites/write"

11 の action までまとまりました。

一点、GET /subscriptions/.../locations のアクセス ログはリソース プロバイダーを含まず、サブスクリプション直下のロケーション情報なので、対応する action である Microsoft.Resources/subscriptions/location/read に変換しています。

3. とりあえずカスタム ロールを試す

今回は Azure CLI でカスタム ロールを作ります。
上でまとめた 11 の action から下記の JSON を用意しました。

{
  "AssignableScopes": [
    "/subscriptions/..."
  ],
  "actions": [
    "Microsoft.Network/locations/operations/read",
    "Microsoft.Network/virtualNetworks/read",
    "Microsoft.Network/virtualNetworks/subnets/read",
    "Microsoft.Network/virtualNetworks/subnets/write",
    "Microsoft.Resources/subscriptions/locations/read",
    "Microsoft.Web/serverfarms/read",
    "Microsoft.Web/sites/config/read",
    "Microsoft.Web/sites/config/write",
    "Microsoft.Web/sites/publishxml/action",
    "Microsoft.Web/sites/read",
    "Microsoft.Web/sites/write"
  ],
  "dataActions": [],
  "description": "",
  "isCustom": true,
  "name": "<何か名前を付ける>",
  "notActions": [],
  "notDataActions": []
}

AssignableScopes に記載するサブスクリプション ID は適宜変更してください。

この JSON ファイルを使ってカスタム ロールの定義を作ります。

az role definition create --role-definition <JSON ファイルのパス>

上記の action では Microsoft.Web/sitesMicrosoft.Web/serverfarmsMicrosoft.Networks/virutalNetworks の 3 種類のリソースが出てきているので、VNET 統合に使う App Service 、App Service Plan、仮想ネットワークの 3 つのリソースに対して作ったカスタム ロールをテスト ユーザーに割り当てて、そのユーザーで最初の Azure CLI を実行してて結果を見ます。

4. 地道にカスタム ロールを修正する

ここで終わればラッキーですが、テスト ユーザーに作って実行してみると下記のエラーが出ます。
やはりまだ権限が足りていませんでした。

Message: The client '...' with object id '...' has permission to perform action 'Microsoft.Web/sites/write' on scope '/subscriptions/.../resourceGroups/.../providers/Microsoft.Web/sites/...'; however, it does not have permission to perform action 'join/action' on the linked scope(s) '/subscriptions/.../resourceGroups/../providers/Microsoft.Network/virtualNetworks/.../subnets/...' or the linked scope(s) are invalid.

App Service への書き込み権限はあるけど、Subnet への接続の権限がない、といった様子。

メッセージを元に、Microsoft.Network/virtualNetworks/subnets/join/action の action をカスタム ロールに追加し、再度ロールの割り当てからトライすると無事成功することが確認できました。

{
  "AssignableScopes": [
    "/subscriptions/..."
  ],
  "actions": [
    "Microsoft.Network/locations/operations/read",
    "Microsoft.Network/virtualNetworks/read",
    "Microsoft.Network/virtualNetworks/subnets/read",
    "Microsoft.Network/virtualNetworks/subnets/write",
    "Microsoft.Resources/subscriptions/locations/read",
    "Microsoft.Web/serverfarms/read",
    "Microsoft.Web/sites/config/read",
    "Microsoft.Web/sites/config/write",
    "Microsoft.Web/sites/publishxml/action",
    "Microsoft.Web/sites/read",
    "Microsoft.Web/sites/write",
    "Microsoft.Network/virtualNetworks/subnets/join/action"
  ],
  "dataActions": [],
  "description": "",
  "isCustom": true,
  "name": "<何か名前を付ける>",
  "notActions": [],
  "notDataActions": []
}

これで Azure CLI から VNET 統合を設定できるカスタム ロールの完成です。 成功しない (追加したはずの action でエラーが出る) 場合は、ロールの反映に時間がかかっている場合がほとんどなので、時間を置く and/or ログアウト&ログインを試せば、いずれ成功します。

おまけ (削除 & ポータル操作対応)

ついでに VNET 統合の無効化と Azure ポータルからの操作権限を追加したカスタム ロールこちらです。

{
  "AssignableScopes": [
    "/subscriptions/..."
  ],
  "actions": [
    "Microsoft.Network/locations/operations/read",
    "Microsoft.Network/virtualNetworks/read",
    "Microsoft.Network/virtualNetworks/subnets/read",
    "Microsoft.Network/virtualNetworks/subnets/write",
    "Microsoft.Resources/subscriptions/locations/read",
    "Microsoft.Web/serverfarms/read",
    "Microsoft.Web/sites/config/read",
    "Microsoft.Web/sites/config/write",
    "Microsoft.Web/sites/publishxml/action",
    "Microsoft.Web/sites/read",
    "Microsoft.Web/sites/write",
    "Microsoft.Network/virtualNetworks/subnets/join/action",
    "Microsoft.Web/sites/networkConfig/delete",
    "Microsoft.Web/sites/config/list/Action",
    "Microsoft.Web/sites/virtualnetworkconnections/read",
    "Microsoft.Web/sites/networkConfig/read"
  ],
  "dataActions": [],
  "description": "",
  "isCustom": true,
  "name": "<何か名前を付ける>",
  "notActions": [],
  "notDataActions": []
}

削除に必要な action Microsoft.Web/sites/networkConfig/deleteaz functionapp vnet-integration remove コマンドのリクエスト ログから、Azure ポータル上から VNET 統合を構成するために必要な action Microsoft.Web/sites/config/list/Action, Microsoft.Web/sites/virtualnetworkconnections/read, Microsoft.Web/sites/networkConfig/read の 3 つは Web ブラウザーのネットワーク トレースを地道に読み解いています。

以上、App Service の VNET 統合を Azure CLI で設定可能なカスタム ロール作成の実例でした。

「これじゃうまくいかない」といったことがあればコメントででもいただければ。