オレ流 Azure RBAC のカスタム ロールの作り方 (1)

今回は、Azure 上のリソースのアクセス管理ができる Azure RBAC のカスタム ロールの作り方です。

カスタム ロールを作って、(共同作成者みたいな巨大な権限ではなく)一部の操作のみができる権限をユーザーに割り当てるシーンはよくあると思います。

作り方はドキュメントに書いてあるのですが、、、

docs.microsoft.com f:id:horihiro:20220122121314p:plain

この「使用可能なアクションを把握」というのが割と大変なので、なんとなくいつもやってるはず、という手順をメモとして残しておきます。
もっと楽なやり方があれば教えてもらえるとありがたいです🙇‍♂️

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

まず最初に設定に必要な Azure REST API へのリクエスト パターンを把握するため、対象の操作を実行できる権限を持つユーザーで Azure CLI--debug オプション付きで実行します。

az <sub-command> <options ...> --debug

すると、標準エラー出力に大量のログが表示される中、以下のような Azure REST API へのリクエスト ログが確認できます。

f:id:horihiro:20220122122059p:plain

フォーマットは以下のようになっているはずです (2022 年 1 月現在)。

DEBUG: urllib3.connectionpool: https://management.azure.com:443 "<HTTP メソッド> <Azure REST API のエンドポイント URL > HTTP/1.1" <レスポンス コード> <レスポンス ボディの長さ>

このうち使うのは、HTTP メソッドと Azure REST API のエンドポイント URL です。
これを全てピックアップします。

なお、この REST API の実行は、リソースの状態によってスキップするリクエストもあるので、作り立てホヤホヤのリソースで試すことがお勧めです。

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

Azure REST API のエンドポイント URL は、一般的には以下のフォーマットです。

https://management.azure.com:443/subscriptions/<SUBSCRIPTION_ID>/resourceGroups/<RESOURCE_GROUP_NAME>/providers/<RESOURCE_PROVIDER>/<RESOURCE_TYPE_1>/<RESOURCE_NAME_1>/.../<RESOURCE_TYPE_n>/<RESOURCE_NAME_n>?api-version=<API_VERSION>

このうち使うのは、<RESOURCE_PROVIDER> と <RESOURCE_TYPE_[1..n]> で、以下のように連結します。

<RESOURCE_PROVIDER>/<RESOURCE_TYPE_1>/.../<RESOURCE_TYPE_n>

最後に以下の表から HTTP メソッドに対応した動詞を見つけてそれを足します。

HTTP メソッド 動詞
GET read
PUT write
PATCH write
DELETE detete
POST action

例えば、といったリクエスト ログが見つかったとします。

DEBUG: urllib3.connectionpool: https://management.azure.com:443 "PATCH /subscriptions/.../resourceGroups/.../providers/Microsoft.Web/sites/.../config/...?api-version=... HTTP/1.1" 200 ...

すると、これを実行するためにカスタム ロールに必要な action は

Microsoft.Web/sites/config/write

になります。

これをピックアップしたリクエスト ログすべてに対して実施して、action のリストを作ります。

全 action はこのドキュメントにあるので、作った action が載っているか確認しましょう。

docs.microsoft.com

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

action のリストができたら一度カスタム ロールを作ります。

作り方は Azure CLI でも Azure ポータルでもお好みで。

docs.microsoft.com

作成したロールをテスト ユーザーに割り当てて、そのユーザーとして最初に実行した Azure CLI を実行してみます。
ロール割り当ての反映には、時間がかかったりトークンを更新しないといけない場合が多く、追加したはずの action でエラーになる場合もありますが、根気よく試しましょう。

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

これで成功したらは完成ですが、そうはいかない場合も多々あります。

ここまででリスト アップした action は、最初にリクエスト ログを取得した Azure CLI のコマンドが、直接リクエストを実行しているログを元にしています。
一方で、Azure CLI からのリクエストを起点に、Azure Resource Manager が実行ユーザーの権限で裏で別の API を実行するケースがあります。

この場合、Azure CLI のログにはエンドポイント URL は記録されません。
このケースでの action 不足の時は、エラー ログとして以下のようなメッセージが表示されます。

Message: The client '...' with object id '...' has permission to perform action '<カスタム ロールに記載した action>' on scope '<ロールのスコープ>'; however, it does not have permission to perform action '<不足している action>' on the linked scope(s) '<不足 action の対象スコープ>' or the linked scope(s) are invalid.

however 以降が足りない action とスコープの説明になっているので、これを元に再度カスタム ロール用の action を追加してロールを割り当てて実行します。

これを繰り返して、エラーが消えれば、カスタム ロールの完成です。
結局、ここの部分が割と時間がかかりるのですが、諦めず頑張りましょう。

FAQ

Q1. write の action である機能の無効化もできますか?

一般的に write の action は既存のリソースの情報を書き換えるために必要な権限です。
その為、例えばある機能の有効化/無効化の切り替えを、既存のリソース情報の書き換え (プロパティ foobarEnabledtruefalse を入れる、など) で制御しているのであれば、write の action でも無効化は可能だと思います。

一方で、有効化に子リソースを追加、無効化に子リソースの削除、といった操作を伴う機能の場合、writeaction だけで対象リソースの削除はできないので、delete の action が必要になります。

ちなみに write の action で read の action をカバーすることもできないのでご注意を。

Q2. Azure ポータルでの操作と Azure CLI での操作を、一つのカスタム ロールでカバー出来ますか?

二つの操作は共通部分は多いですが、それぞれ独自に必要な action もあります。 Azure ポータルでの操作は、UI 上に表示するための情報取得のリクエストが発生する場合があり、逆に Azure CLI の場合はオプションでその辺りを決め打ちで指定するので、比較的 Azure ポータルでの操作の方が Azure CLI での操作よりも広い権限を求めることが多いようです。

なので一つのカスタム ロールにまとめたい場合は、それらの action 全てを含くんだ (= OR を取った) カスタム ロールを作る必要があります。

次は App Service の VNET 統合を例にして、以上のステップを試してみたいと思いますが、長くなったので別エントリーへ(書きました)。