ほりひログ

所属組織の製品 (Azure とか) に関連する内容が多めだけど、個人の見解であって、所属組織を代表する公式情報ではないです。

オレ流 Azure RBAC のカスタム ロールの作り方 (3) ~ CLI ツール作りました

前回、前々回で紹介したカスタム ロール作成手順があまりに面倒だったので、少しでも手間を減らすために CLI ツール custom-role-generator を作りました。

github.com

初 Rust です。ググりながら作ったコードです。

ちなみに、前回・前々回はこちら。

uncaughtexception.hatenablog.com
uncaughtexception.hatenablog.com

こちらで紹介した下記の手順のうち、主に 1. と 2. あたりをサポートします。

  1. Azure CLI を使って必要な Azure REST API を確認する
  2. HTTP メソッドとエンドポイント URL からアクションを組み立てる
  3. とりあえずカスタム ロールを試す
  4. 地道にカスタム ロールを修正する

インストールは Releases から zip をダウンロードして解凍するだけです。さすが Rust 。ワンバイナリー*1

使い方

custom-role-generator は標準入力からインプットされた内容を解析します。

なので、az コマンドに --debug を付けて標準エラー出力にログを出力し、そのログを 2>&1 で標準出力にリダイレクトして、パイプ |custom-role-generator で渡せば動きます。

$ az [何かのコマンド] --debug 2>&1 | custom-role-generator

ファイルに出力したログも、< を使えば標準入力に渡せます。

$ az [何かのコマンド] --debug 2>az.log # 標準エラー出力を `az.log` に出力
$ custom-role-generator < az.log # `az.log` を標準入力から入力

まともに動けば、標準出力にカスタム ロールの定義ファイルが出力されます。

{
  "AssignableScopes": [
    "/subscriptions/..."
  ],
  "actions": [
    "Some.Provider/.../...",
      :
  ],
  "dataActions": [],
  "description": "Custom role definition for `az [何かのコマンド]` generated by custom-role-generator",
  "isCustom": true,
  "name": "<REPLACE_THIS>",
  "notActions": [],
  "notDataActions": []
}

既存のカスタム ロール定義ファイルを --append-to オプションで指定することで、ログから抽出した action を actions に追加することもできます。

$ az [何かのコマンド] --debug 2>&1 | custom-role-generator --append-to /path/to/existing/role-definition.json
{
  "AssignableScopes": [
    "/subscriptions/..."
  ],
  "actions": [
    "[もともとあった action1]",
    "[もともとあった action2]",
      :
    "[追加された action1]",
    "[追加された action2]",
      :
  ],
  "dataActions": [],
  "description": "Custom role definition for `az [何かのコマンド]` generated by custom-role-generator",
  "isCustom": true,
  "name": "<REPLACE_THIS>",
  "notActions": [],
  "notDataActions": []
}

あと custom-role-generator --debug のように --debug オプションを付けると、入力されたログをそのまま標準エラー出力に出力します。

実行例

やっぱり VNET 統合

まずは共同作成者なり、 VNET 統合を設定可能な権限を持ったユーザーでコマンドを実行し、ベースになるロール定義を作ります。

# 共同作成者ロールでの実行
$ az webapp vnet-integration add --id <WebApp のリソース ID> --vnet <VNET のリソース ID> --subnet <Subnet 名> --debug 2>&1 | custom-role-generator > role-vnet-integration1.json
$ cat role-vnet-integration1.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": "Custom role definition for `az webapp vnet-integration add` generated by custom-role-generator",
  "notActions": [],
  "notDataActions": []
}

これで、上述の 4 ステップのうち 1. と 2. が終了。

このロール定義を使ってカスタム ロールを作成し、テスト ユーザーに関連リソースのカスタム ロールに割り当てて、今度はそのテスト ユーザーで実行します。
これで成功したら嬉しいですが、前回のエントリーで書いた通り、VNET 統合の場合はこの段階ではまだ成功しません。
原因 (足りない action) を追加するため、あえて失敗するユーザーでの実行ログをもう一度 custom-role-generator に入れます

# テストユーザーでの実行
$ az webapp vnet-integration add --id <WebApp のリソース ID> --vnet <VNET のリソース ID> --subnet <Subnet 名> --debug 2>&1 \
| custom-role-generator --append-to role-vnet-integration1.json > role-vnet-integration2.json
$ cat role-vnet-integration2.json
{
  "AssignableScopes": [
    "/subscriptions/..."
  ],
  "actions": [
    "Microsoft.Network/locations/operations/read",
    "Microsoft.Network/virtualNetworks/read",
    "Microsoft.Network/virtualNetworks/subnets/join/action", # <- 追加される action
    "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": "Custom role definition for `az webapp vnet-integration add` generated by custom-role-generator",
  "notActions": [],
  "notDataActions": []
}

これをもう一回テストユーザーに割り当てると問題なく VNET 統合が設定できます。

他のコマンドでも似たようなものだと思うので、ぜひ手強そうなカスタム ロールづくりに試してもらってフィードバックいただければ。

なお Rust 始めたばかりで全然わかりません。リファクタリングしないといけないし、テストもまともに書いていない、書けない。
PR も絶賛募集中。

これにてカスタム ロールの作り方はおしまい。


*1:Rust だけじゃないですけど