[Azure]テナント内のRBAC一覧をスクリプトで取得する
監査や構成管理の観点から付与したRBACを一覧で管理できるようにしたおきたいというニーズはAzureを使っている企業ならどこにでもあると思います。
ただし安易に手動更新するスプレッドシートなどを作成すると更新が漏れるべくして漏れますし、そもそも都度都度更新するのは非常に面倒なので全力で避けたいところです。
なのでなるべく楽にRBACを管理できるようにまずはRBAC一覧をスクリプトからCSV形式で取得できるようにします!
スクリプトにはPowerShellを使用します。
そもそもどのような情報があればいいのか
5W1HでRBACの管理要素を整理してみます。
5W1H | 要素 | APIのプロパティ※1 |
---|---|---|
①:Where | どのスコープに付与したのか? | scope |
②:What | 何の権限(ロール)を付与したのか? | roleDefinitionId |
③:Why | なぜ付与したのか? | Description※2 |
④:Who | 誰(ユーザ/グループ/サービスプリンシパル)への付与なのか? | principalId |
⑤:Who | 誰が付与したのか? | createdBy |
⑥:Who | 誰が更新したのか? | updatedBy |
⑦:When | いつ付与したのか? | createdOn |
⑧:When | いつ更新したのか? | updatedOn |
⑨:How | どのような方法で付与したのか?(CLI/GUI) | なし※3 |
- ※1…以下を参照
- ※2…人間の頭にある情報なのでRBACと紐づけて都度記録しておく必要がありますが、RBACのDescriptionに記録する運用にしておけばAzure上で管理できます。(後付けで既にあるRBACに情報を追記したい場合はSet-AzRoleAssignmentなどを使いましょう)
- ※3…取得できません。(あえて管理する必要もない要素なので、①〜⑧を取得対象とします)
どうやって情報を取得するのか
APIを直接叩くこともできますが、Get-AzRoleAssignment(Azure Powershell)かaz role assignment list(Azure CLI)から取得するのが一番簡単です。principalIdやroleDefinitionIdの表示名もよしなに一緒に取得してくれるというメリットもあります。
Azure Powershellで取得する場合の注意点
Azure PowershellのGet-AzRoleAssignmentは、戻り値のオブジェクトのクラス内で⑤~⑧のプロパティが定義されておらず、取得できない仕様になっています。Powershellで扱う分にはAzure Powershellの方が直接オブジェクトとして扱えるので便利ですが、この手の罠が多そうですね…
PS /home/dev> Get-AzRoleAssignment | Get-Member
TypeName: Microsoft.Azure.Commands.Resources.Models.Authorization.PSRoleAssignment
(略)
実装
基本的には取得したJSONをパース/加工してCSVに出力するだけなのでシンプルです。
Cloud Shellからの利用を想定して動作環境はAzure Powershell 7.3.3です。
RBACのスコープとなりうる管理グループ/サブスクリプション/リソースグループ/リソースについたRBACをテナント内から網羅的に取得できるようにします。
function ConvertTo-PsObject($json){
$json | ConvertFrom-Json
}
$role_assingments = @()
$subscriptions = ConvertTo-PsObject (az account list --all)
foreach($subscription in $subscriptions){
az account set --name $subscription.name
$role_assingments += ConvertTo-PsObject (az role assignment list --all)
}
#重複排除が必要
$role_assingments = $role_assingments | Sort-Object -Property id -Unique
#変換+フォーマットした時刻プロパティを後付け
for($i=0;$i -lt $role_assingments.length;$i++){
$role_assingments[$i] `
| Add-Member -MemberType NoteProperty -Name 'CreatedOnJST' -Value $role_assingments[$i].CreatedOn.AddHours(9).Tostring('yyyy/MM/dd HH:mm:ss')
$role_assingments[$i] `
| Add-Member -MemberType NoteProperty -Name 'UpdatedOnJST' -Value $role_assingments[$i].UpdatedOn.AddHours(9).Tostring('yyyy/MM/dd HH:mm:ss')
}
$role_assingments `
| Select-Object createdOnJST,createdBy,updatedOnJST,updatedBy,scope,roleDefinitionName,principalName,description `
| Export-Csv -Encoding Default $psscriptroot\role_assignments.csv
サンプル
Cloud Shellから実行してCSVを取得できました!
PS /home/dev> ./get_roleassign.ps1
PS /home/dev> Get-Content ./role_assignments.csv
"CreatedOnJST","createdBy","UpdatedOnJST","updatedBy","scope","roleDefinitionName","principalName","description"
"2023/01/02 21:01:01","***","2023/01/02 21:01:01","***","/providers/Microsoft.Management/managementGroups/mg-test","Owner","***",
"2023/03/26 09:04:55","***","2023/03/26 09:04:55","***","/subscriptions/8d76c2b5-c7bf-4821-9666-92fd4b6313cc/resourceGroups/rg-test-jpeast-vm","Contributor","***","基盤リソースを構築するため"
注意点など
- 認証処理はCloud Shellの利用を想定してスキップしています。
- 当然ながら、実行ユーザもしくはサービスプリンシパルにはすべてのスコープでRBACを閲覧できる権限が必要です。
- サブスクリプション配下のリソースグループやリソースのRBACを再帰的に取得できるようにaz role assignment listには'--all'を付けます。
- 複数のサブスクリプションがある環境では管理グループをスコープとしたRBACが重複してしまうため、重複排除が必要になります。
- 日時の戻り値はUTCなので、JSTへの変換やフォーマットの変更はスクリプト側で行います。
- Azure CLIやAzure Powershellの実行スコープは基本的にサブスクリプション単位になっています。それなりの会社規模でテナント内に複数のサブスクリプションがある環境ではサブスクリプションの数だけコマンドを実行するようにしないと漏れます。
まとめ
簡易的ながら最新のRBAC一覧がスクリプトでいつでも取得できるようになりました。
上記のスクリプトを定期実行させアウトプットをどこかに保存する仕組みを用意することで、RBACの構成管理が自動化が可能になりますが、また別の記事でまとめたいと思います。
Discussion