Azure Resource Graph で Azure リソースの変更を検知して通知する

本記事は、[Microsoft Azure Tech Advent Calendar 2023](https://qiita.com/advent-calendar/2023/microsoft-azure-tech) の 12/22 の投稿です。
ジングルベル～🎅🎅

こんにちは駆け出しアーキテクトのやまぱんです。
今回の記事では Azure Resource Graph を使って Azure リソースの変更を検知してみたいと思います。

もし、誤りなどがあったらコメントにて優しく指摘いただければ嬉しいです。
その他のコメントもお気軽にお願いします👌


## なにがうれしいのか
Azure Resource Graph を使って簡単に Azure リソースの変更や削除、追加などを検知することができます。
管理部門の方などにとってはシャドーITというか、シャドー Azure リソースの検知をすることができます。
また、本ページでは触れませんが Azure Resource Graph を使うことで、**使われていない Public IPアドレスを探したり、使われていないマネージドディスクを探したり、リソースの状態や設定を指定してクエリを発行することもできます**。具体的なサンプルは[こちらのページ](https://www.michikusayan.com/entry/20210321/1616288400)にあります。

## Azure Resource Graph とは
以下公式ドキュメントの抜粋です。
> Azure Resource Graph は Azure サービスであり、Azure Resource Management を拡張するよう設計されています。特定のサブスクリプションのセット全体で大規模なクエリを実行する機能を使用して、効率的でパフォーマンスの高いリソース探索を提供することで、環境を効果的に管理できます。 これらのクエリでは、次の機能を提供します。
複雑なフィルター処理、グループ化、およびリソースのプロパティでの並べ替えによりリソースのクエリを行う機能。
ガバナンスの要件に基づいてリソースを繰り返し探索する機能。
広大なクラウド環境にポリシーを適用することの影響を評価する機能。
リソース プロパティに加えられたクエリの変更。

https://learn.microsoft.com/ja-jp/azure/governance/resource-graph/overview

Azure Resource Graphの主な特徴や機能
+ クエリ言語: Kusto Query Language（KQL）を使用して、Azure Resource Graphで柔軟で強力なクエリを実行できます。これにより、複雑な条件でリソースを検索し、データをフィルタリングし、集計できます。

+ 高速で大規模なデータセット: ARGは、大規模なAzure環境でのクエリ処理に対応しており、数千以上のリソースにまたがるデータを高速に処理できます。

+ クロスリージョンおよびクロスサブスクリプション検索: Azure Resource Graphは、クロスリージョンおよびクロスサブスクリプションの範囲で検索をサポートします。これにより、広範囲なAzure環境でリソースを効率的に検索できます。

+ Azure Policyの評価: ARGを使用してAzure Policy の評価結果を取得し、ポリシーコンプライアンスの概要を把握できます。

+ Azure Portal、Azure PowerShell、Azure CLIとの統合: Azure Resource Graph はAzure Portal、Azure PowerShell、Azure CLIと統合されており、これらのツールを通じてクエリを実行できます。

## Azure Resource Graph を使ってみる
今回は Log Analytics Workspace と Azure Resource Graph エクスプローラー で試してみます。
Log Analytics Workspace で実行する場合は、Azure Resource Graph エクスプローラー で実行した<font color="red">クエリの頭に arg("") を付けます。</font>
arg はおそらく Azure Resource Graph を指していると思います。



### リソースの数をカウントする
```kql:KQL
Resources
| count
```
+ Azure Resource Graph エクスプローラー
![2023-12-08_06h47_16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2982508/a3d5f79a-af2d-d9ed-2f67-16433f96cf5e.png)

+ Log Analytics Workspace
```arg("")```がついてますね.
![2023-12-08_06h46_25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2982508/24069a45-9510-c861-d033-d80242b62955.png)

リソースの変更を検知したいので、リソースの数をカウントしておいて、それが変化すればいいかと思ってましたがそれじゃリソース数が変化しない場合に検知できないことに気づきました。😂😂
なので次はストレートにリソースの変更を検知するクエリです。

### リソースの変更を検知する
今回は後でメール通知も行いたいので Log Analytics Workspace で下記のクエリを実行します。
一日以内に変更のあったリソースを出してます。
```kql:KQL
arg("").resourcechanges
| extend timestamp = todatetime(parse_json(properties).changeAttributes.timestamp)
| extend hid = substring(id, indexof(id, "/providers/") + 1)
| project timestamp, subscriptionId, resourceGroup, hid, properties
| where timestamp >= ago(1d)
| order by timestamp asc
```
[クエリの説明]
> このクエリは、Azure Resource Graph で使用される resourcechanges テーブルからデータを取得しています。
> + extend timestamp = todatetime(parse_json(properties).changeAttributes.timestamp) : 
> properties カラムの JSON オブジェクトから changeAttributes.timestamp プロパティを取得し、timestamp カラムに変換します。
> + extend hid = substring(id, indexof(id, "/providers/") + 1) : 
id カラムから /providers/ の後ろの文字列を取得し、hid カラムに格納します。
> + project timestamp, subscriptionId, resourceGroup, hid, properties : 
timestamp, subscriptionId, resourceGroup, hid, properties カラムのみを残します。
> + where timestamp >= ago(1d) : 
timestamp カラムが 1 日以内のレコードのみを残します。
> + order by timestamp asc : 
timestamp カラムで昇順に並べ替えます。

+ 実行結果
私の環境では下記のように 3 件ヒットしました。✨
![2023-12-08_06h58_43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2982508/910e7767-6db3-4da4-227b-774f34a7868d.png)

続いてアラートを設定していきましょう。

## Azure Resource Graph クエリでアラートを設定する
:::note info
2023/12/08(金) 現在で本機能 (Azure Resource Graph とAzure Monitorの統合) はプレビュー段階です。

・Public Preview: Azure Log Alerts support for Azure Resource Graph (ARG)
https://azure.microsoft.com/ja-jp/updates/public-preview-azure-log-alerts-support-for-azure-resource-graph-arg/
:::
## アラートルールの作成
先ほどの画面ショットの黄色塗りつぶし部分の **"+ 新しいアラートルール"** から設定します。
+ 基本の設定
こんな感じ
![2023-12-08_07h05_02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2982508/9ecc96cc-166f-925c-d3fa-82875dbbb5ce.png)

+ 通知の設定
今回はメール通知のみを設定しますが、メール以外にも通知方法はあります。
また Webhook を利用して Teams や Slack に投稿することも可能です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2982508/f2e51bea-b866-3da5-3697-8ca10bc63da0.png)

+ 詳細の設定
下記のような感じで設定
![2023-12-08_11h13_00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2982508/4bda1be7-5119-4120-ec57-974acf086020.png)


+ 作成したアラートルールはこういう形で ”ログ検索警告ルール” としてリソースとして確認可能です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2982508/a3fe1069-54b9-36d4-252a-d7f54aa63b5d.png)

### マネージド ID の設定
先ほど選択した マネージドID (System assigned identity) に対して権限を設定します。
権限の設定がないと、正常にクエリの実行・および通知ができません。
クエリの対象のリソースに対して、閲覧者権限がついていればＯＫです。
今回は Subscription 全体に閲覧者権限を付けました。
![2023-12-08_11h21_34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2982508/f1144723-03fe-f03e-3093-b7be2b94bade.png)

:::note info
 ARG クラスターに対してクエリを実行する場合、クエリによってアクセスされるすべてのデータ ソースに対して<font color="red">閲覧者ロール</font>を追加する必要があります。 たとえば、クエリがリソース中心の場合、そのリソースに対する閲覧者ロールが必要です。
 ・警告ルールを作成または編集する
 https://learn.microsoft.com/ja-jp/azure/azure-monitor/alerts/alerts-create-new-alert-rule?tabs=log#set-the-alert-rule-details
:::

## アラートメールの確認
下記が実際に飛んできたアラートメールです。
実際にリソースの変更を検知して通知することができました！
*時刻は UTC 表記なので、日本時間に直すには +9:00 してください。

+ タイトル：Fired:Sev2 Azure Monitor Alert ResourceChange！ on law-test ( microsoft.operationalinsights/workspaces ) at 12/8/2023 2:01:12 AM
+ 差出人：Microsoft Azure <azure-noreply@microsoft.com>
+ 内容：下記画面ショット参考（後半は割愛しましたが、アラートルールの設定内容が記載されていました。)
![2023-12-08_11h31_57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2982508/dea5f338-c1f7-7dfd-0dc5-a4e9b9264505.png)

## CLI での実行
Azure CLI や Azure PowerShell でもクエリを実行することが可能なので、監視の仕組みを作りこむこともできるかと思います。

+ Azure CLI  や Azure PowerShell での実行例
```KQL:Azure CLI 
az graph query -q "Resources | summarize count()"
```

```PowerShell:Azure PowerShell
Search-AzGraph -Query "Resources | summarize count()"
```
Ref : [Resource Graph の初歩的なクエリのサンプル](https://learn.microsoft.com/ja-jp/azure/governance/resource-graph/samples/starter?tabs=azure-powershell)

## 参考
・Azure Resource Graph とは(公式)

https://learn.microsoft.com/ja-jp/azure/governance/resource-graph/overview

・Azure Resource Graph の公式クエリサンプル(初歩)

https://learn.microsoft.com/ja-jp/azure/governance/resource-graph/samples/starter?tabs=azure-cli

・Azure Resource Graph の公式クエリサンプル(詳細)

https://learn.microsoft.com/ja-jp/azure/governance/resource-graph/samples/advanced?tabs=azure-cli

・Azure Resource Graph のサンプル
使われていない Public IPアドレスを探したり、使われていないマネージドディスクを探したり。

https://www.michikusayan.com/entry/20210321/1616288400

・警告ルールを作成または編集する

https://learn.microsoft.com/ja-jp/azure/azure-monitor/alerts/alerts-create-new-alert-rule?tabs=metric

・KQLについて

https://qiita.com/YoshiakiOi/items/f2cb2b5626c2f7f71dba

・KQL 100+ Knocks
MS 社員が作ったKQL学習サイトです。

https://azure.github.io/fta-kusto100knocks/ja/docs/basic/

・Azure Resource Graphを触ってみる 
JBSさんの記事 (初学者向けに丁寧)

https://blog.jbs.co.jp/entry/2022/06/17/090929

・サポートチームからもこのトピックに関する記事が出ました (追記)

https://jpazmon-integ.github.io/blog/ame/HowToResourceChangeAlert/

## 謝辞
このエントリを書くにあたって、協力いただきました社内の有志のメンバーの皆さまありがとうございました。