Microsoft Sentinelの分析ルール追加／更新を検出する

Microsoft Sentinelの分析ルールはデプロイすればすぐに利用可能なものが多数存在している。具体的には「規則のテンプレート」にリストアップされている。このルールについて、新しく追加もしくは更新されたとしてもユーザーに通知する仕組みが実装されておらず、自らが気づく仕組みづくりを作る必要がある。

一番簡単なのは定期的に手動でリスト画面を眺める方法があるが、GUIの構成仕様上バージョン情報等は1つずつルールを選択して確認していく必要がある。

# 目指すゴール
REST API経由ですべてのアラート ルール テンプレートを取得し、その結果をLog Analyticsの指定したテーブルに格納する。
その後、Sentinelの自作ルールで定期的に更新もしくは追加を確認し該当すればインシデントとして起票する。

# 実装
以下の流れで実装をすすめる。
 1. [Azure AD] REST APIのbearer token取得用にサービスプリンシパルを作成、設定する
 2. [Logic Apps] tokenの取得、REST API経由でルール一覧を取得、Log Analyticsにデータを送信する
 3. [Sentinel] 追加／更新を検出する

## 1. サービスプリンシパルの設定
ユーザーが画面経由で様々な操作をする際、操作している人を識別・認可しているがアプリケーションでも同様の仕組みで利用することができる。
人の場合はユーザープリンシパルだが、アプリケーションの場合はサービスプリンシパルとなる。アプリケーションを活用する例は今回のように自動化された仕組みのなかで自動的にリソースへアクセスする場合などである。詳細は以下の記事を参照すること。

https://learn.microsoft.com/ja-jp/azure/active-directory/develop/app-objects-and-service-principals

今回はサービスプリンシパルを利用するためその設定を行う。

### アプリケーションの作成・設定
以下の記事の「Azure AD にアプリケーションを登録し、サービス プリンシパルを作成する」を参考にしてアプリの作成を行う。

https://learn.microsoft.com/ja-jp/azure/active-directory/develop/howto-create-service-principal-portal#register-an-application-with-azure-ad-and-create-a-service-principal

パラメーターは以下のように設定する。

|項目|値|
|--|--|
|名前|（任意）|
|サポートされているアカウントの種類|この組織ディレクトリのみに含まれるアカウント (既定のディレクトリ のみ - シングル テナント)|
|リダイレクト URI（省略可能）|設定しない|

次に作成されたアプリケーションに対してシークレット（パスワードのようなもの）を設定する。
以下の記事の「オプション 2:新しいアプリケーション シークレットを作成する」を参考にシークレットを作成する。
なお、シークレットの値をメモしておく。

https://learn.microsoft.com/ja-jp/azure/active-directory/develop/howto-create-service-principal-portal#option-2-create-a-new-application-secret

最後に以下の記事の「サインインするためのテナントとアプリ ID の値を取得する」を参考にアプリケーションのテナントIDおよびアプリIDをメモする。

https://learn.microsoft.com/ja-jp/azure/active-directory/develop/howto-create-service-principal-portal#get-tenant-and-app-id-values-for-signing-in


### アプリケーションの設定
作成されたアプリケーションに対して権限を付与する。
最小権限の場合、Log Analytics ワークスペースが最小範囲となる。よって、Log Analytics ワークスペースへのRead権限を付与すれば良い。
対象のワークスペースを開き、左側のメニューペインから「アクセス制御（IAM）」を選択し画面上部の「+ 追加」 -> 「ロールの割り当ての追加」をクリックする。
ロールリストから「閲覧者」を選択しメンバーを付与する。なお、キーワード検索ではなく前方一致で選択肢が出てくるようなので、アプリ名を手打ちして選択すること。

![スクリーンショット 2023-01-04 12.57.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/118089/dbcfd3db-ffa8-075f-5935-0c1cb480fb06.png)

## 2. ルールの一覧取得ならびにLog Analyticsへのデータ送信
ロジックアプリを用いて実装する。完成イメージは以下の通り。
![スクリーンショット 2023-01-04 13.03.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/118089/7ca7ab53-f312-a42c-7b2f-6d9a17768702.png)

Recurrenceは自分の好きな時間帯／周期を設定すれば良い。また、変数を準備して各種パラメーターを設定する方法やハードコーディングする方法どちらでも良い。なお、Client Secretは定期的に更新する必要があるため変数化しておくことを推奨する。
それ以外の部分については詳しく記載していく。

### HTTP： Bearer Tokeの取得
パラメーターを以下の通り設定する。
|項目|値|
|--|--|
|方法|POST|
|URI|https://login.microsoftonline.com/{TenantID}/oauth2/token|
|ヘッダー|Content-Type／application/x-www-form-urlencoded|
|本文|grant_type=client_credentials&client_id={APP ID}&client_secret={Client Secret}&resource=https%3A%2F%2Fmanagement%2Eazure%2Ecom|

![スクリーンショット 2023-01-04 13.08.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/118089/7c5ccbb4-5845-bbe9-c5f9-83ee509155f4.png)

### JSON の解析： Bearer Token
パラメーターを以下の通り設定する。
|項目|値|
|--|--|
|コンテンツ|（HTTP: Bearer Tokenの取得）本文|
|スキーマ|下記コードセクション参照|

```JSON: スキーマ
{
    "properties": {
        "access_token": {
            "type": "string"
        },
        "expires_in": {
            "type": "string"
        },
        "expires_on": {
            "type": "string"
        },
        "ext_expires_in": {
            "type": "string"
        },
        "not_before": {
            "type": "string"
        },
        "resource": {
            "type": "string"
        },
        "token_type": {
            "type": "string"
        }
    },
    "type": "object"
}
```

### HTTP: ルールリストの取得
パラメーターを以下の通り設定する。
|項目|値|
|--|--|
|方法|GET|
|URI|https://management.azure.com/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.OperationalInsights/workspaces/{workspaceName}/providers/Microsoft.SecurityInsights/alertRuleTemplates?api-version=2022-11-01|
|ヘッダー|Authorization／Bearer {（JSONの解析: Bearer TOken）access token}|

![スクリーンショット 2023-01-04 13.15.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/118089/c98adb3f-a78e-3fbf-9436-556f4b5fc53f.png)

### JSON の解析
パラメーターを以下の通り設定する。
|項目|値|
|--|--|
|コンテンツ|本文／body('HTTP')|
|スキーマ|以下のコードブロックに示す値|

```JSON:スキーマ
{
    "properties": {
        "value": {
            "items": {
                "properties": {
                    "id": {
                        "type": "string"
                    },
                    "kind": {
                        "type": "string"
                    },
                    "name": {
                        "type": "string"
                    },
                    "properties": {
                        "properties": {
                            "alertRulesCreatedByTemplateCount": {
                                "type": "integer"
                            },
                            "createdDateUTC": {
                                "type": "string"
                            },
                            "description": {
                                "type": "string"
                            },
                            "displayName": {
                                "type": "string"
                            },
                            "entityMappings": {
                                "items": {
                                    "properties": {
                                        "entityType": {
                                            "type": "string"
                                        },
                                        "fieldMappings": {
                                            "items": {
                                                "properties": {
                                                    "columnName": {
                                                        "type": "string"
                                                    },
                                                    "identifier": {
                                                        "type": "string"
                                                    }
                                                },
                                                "required": [
                                                    "identifier",
                                                    "columnName"
                                                ],
                                                "type": "object"
                                            },
                                            "type": "array"
                                        }
                                    },
                                    "required": [
                                        "entityType",
                                        "fieldMappings"
                                    ],
                                    "type": "object"
                                },
                                "type": "array"
                            },
                            "lastUpdatedDateUTC": {
                                "type": "string"
                            },
                            "query": {
                                "type": "string"
                            },
                            "queryFrequency": {
                                "type": "string"
                            },
                            "queryPeriod": {
                                "type": "string"
                            },
                            "requiredDataConnectors": {
                                "items": {
                                    "properties": {
                                        "connectorId": {
                                            "type": "string"
                                        },
                                        "dataTypes": {
                                            "items": {
                                                "type": "string"
                                            },
                                            "type": "array"
                                        }
                                    },
                                    "required": [
                                        "connectorId",
                                        "dataTypes"
                                    ],
                                    "type": "object"
                                },
                                "type": "array"
                            },
                            "severity": {
                                "type": "string"
                            },
                            "status": {
                                "type": "string"
                            },
                            "tactics": {
                                "items": {
                                    "type": "string"
                                },
                                "type": "array"
                            },
                            "triggerOperator": {
                                "type": "string"
                            },
                            "triggerThreshold": {
                                "type": "integer"
                            },
                            "version": {
                                "type": "string"
                            }
                        },
                        "type": "object"
                    },
                    "type": {
                        "type": "string"
                    }
                },
                "required": [
                    "id",
                    "name",
                    "type",
                    "kind",
                    "properties"
                ],
                "type": "object"
            },
            "type": "array"
        }
    },
    "type": "object"
}
```

### データの送信
コネクタ「Azure Log Analytics Data Collector」、アクション「データの送信」を利用する。
なお、パラメーターを以下の通り設定する。
|項目|値|
|--|--|
|JSON 要求本文|（JSONの解析）value|
|カスタム ログの名前|（任意）SentinelAlertRules_CL|

## 3. Sentinelで追加／更新を検出する

### Log Analyticsでのデータ確認
以下のクエリを実行してデータ格納状況を確認する。なお、timeframe変数の値を調整する必要がある。
```Kusto:確認用クエリ
let timeframe = ago(30d);
SentinelAlertRules_CL
| where properties_severity_s != "" and properties_status_s == "Available" and properties_lastUpdatedDateUTC_t > timeframe
| summarize arg_max(TimeGenerated, *) by properties_displayName_s
| extend type=case(properties_lastUpdatedDateUTC_t == properties_createdDateUTC_t,"Add","Update")
| project ruleName=properties_displayName_s, ruleId=name_g, version=properties_version_s, lastUpdateDateUTC=properties_lastUpdatedDateUTC_t, createdDateUTC=properties_createdDateUTC_t, severity=properties_severity_s, kind_s, type, TimeGenerated
```

実行結果
![スクリーンショット 2023-01-04 13.18.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/118089/272df363-c8ab-ec9d-88f7-dfbd6f17f95d.png)

### Sentinelの独自ルール追加
1日に1回実行するという前提のクエリを以下に示す。

```Kusto:追加
let timeframe = ago(1d);
SentinelAlertRules_CL
| where properties_severity_s != "" and properties_status_s == "Available" and properties_lastUpdatedDateUTC_t > timeframe
| summarize arg_max(TimeGenerated, *) by properties_displayName_s
| extend type=case(properties_lastUpdatedDateUTC_t == properties_createdDateUTC_t,"Add","Update")
| where type == "Add"
| project ruleName=properties_displayName_s, ruleId=name_g, version=properties_version_s, lastUpdateDateUTC=properties_lastUpdatedDateUTC_t, createdDateUTC=properties_createdDateUTC_t, severity=properties_severity_s, kind_s, type, TimeGenerated
```

```Kusto:更新
let timeframe = ago(1d);
SentinelAlertRules_CL
| where properties_severity_s != "" and properties_status_s == "Available" and properties_lastUpdatedDateUTC_t > timeframe
| summarize arg_max(TimeGenerated, *) by properties_displayName_s
| extend type=case(properties_lastUpdatedDateUTC_t == properties_createdDateUTC_t,"Add","Update")
| where type == "Update"
| project ruleName=properties_displayName_s, ruleId=name_g, version=properties_version_s, lastUpdateDateUTC=properties_lastUpdatedDateUTC_t, createdDateUTC=properties_createdDateUTC_t, severity=properties_severity_s, kind_s, type, TimeGenerated
```

# おまけ
表示されたruleIDはsigmaファイルのIDとなるため、リポジトリでsigmaファイルを検索し確認すれば更に詳細情報を取得することが可能である。

https://github.com/Azure/Azure-Sentinel

以下のツールを使えばSigmaファイルの特定が楽にできる。

https://github.com/sanyamarseille/MicrosoftSentinel_rules

# 参考記事

https://www.managedsentinel.com/monitoring-the-publication-of-new-azure-sentinel-alert-rule-templates/

https://learn.microsoft.com/ja-jp/rest/api/securityinsights/

https://tech-lab.sios.jp/archives/23371