Microsoft Sentinel クエリ関数の活用

# はじめに
Microsoft Sentinel を利用中のユーザーであれば Log Analytics や分析ルール、Azure ブック等でクエリを使用している方が多いかと思いますが、この記事ではクエリそのものではなく "関数" という機能にスポットを当ててその活用法を紹介します。

関数を使用することによって、多数のクエリを管理しやくすくなったり、クエリ単体では実現しにくい挙動が可能になったりとメリットもあります。
このメリットは特に Azure ブックで利用しやすいため、Azure ブックを利用する方は是非ご参考ください。 

# そもそも関数とは
Microsoft Sentinel の "ログ" には、関数という機能が用意されています。
この機能は端的に言うと「複数行からなるクエリに名前を付けて保存でき、その名前を指定するだけでいつでもそのクエリを実行可能にする」ものです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3564376/5c6e3aca-0228-c2fa-3259-7bf270a51b85.png)


この "関数" は前述のとおり Azure ブックでは活用しやすい機能です。
ブックを作成した際、１つのブック内で同じクエリを繰り返し記述するようなことはありませんか？
これを1つの関数として保存しておくとブック全体の管理が楽になります。
特にアップデートなどでクエリ修正を行う場合は元のクエリ１つを修正すれば参照している全箇所も自動的に修正されるので効果が高いです。
他のやり方もあると思いますが、関数はブック自体の機能ではなく KQL を利用できるシーンならどこにでも利用できる点で他にも応用が利きます。

また、関数として保存されたクエリは演算子やテーブル名と同様に予測候補に挙がってくるようになるので、わかりやすい名前にしておけば手打ちでクエリを実行する際も利用はスムーズです。


※例：あらかじめ関数として保存しておいた「TestFunction」を候補予測で呼び出す
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3564376/ce7a73d3-a88a-4198-b4dc-39265201acf3.png)





# 関数の機能「パラメーター」
今回の記事のメインはこのパラメーターになります。

※例：パラメーターを用いた関数 "TestTII2" 
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3564376/92b8747f-81e8-4634-9d68-08e31c6f1200.png)

このパラメーターの機能は、使用すると「関数の外部からクエリ条件となる変数を指定できる」ようになります。
例えば、関数内に使う where 文の参照値をパラメータにしておくと毎回指定を変えられるので「同じ関数を使っても異なる where 文を実行できる」というものです。

関数は基本的に「関数に記述した内容をそのまま実行する」だけの機能ですが、パラメーターによって使用タイミングごとに異なる結果が得られるようになるわけです。
また、正しいパラメーターを指定しない場合はクエリが実行エラーとなるため、疑似的に関数内のクエリを隠す効果もあります。もちろん見ようと思えば見られますが、シナリオによっては必要最低限の効果は得られます。

利用上のデメリットとしては、前述のとおり正しいパラメータ指定が必要になるため全ての関数に使用してしまうと扱いが面倒になってしまう場合もあります。正しく検討して利用しましょう。




# パラメーターの設定と使い方

実際に簡単なクエリを使ってパラメーター設定例を解説します。
例えば以下のようなクエリを、パラメーターを使って関数化するとします。

ThreatIntelligenceIndicator
| where ThreatType == "Botnet"

この時、パラメーターを指定せずに上記のクエリ関数を作成すると必ず Botnet に該当する結果のみが出力されますが、今回はパラメーターで ThreatType の指定を変えられるようにしたいと思います。




<b>■ステップ１：クエリでパラメーターにする箇所を決定し、パラメーター名にする予定の名前で置き換える</b>

ではやってみましょう。
といっても関数のクエリ自体は以下のような簡単な置き換えをするだけです。

■もともとのクエリ
　ThreatIntelligenceIndicator
　　| where ThreatType == "Botnet"

■パラメーター名を指定する形に置き換えたクエリ
　ThreatIntelligenceIndicator
　　| where ThreatType == Param_ThreatType

※この時点でパラメーター値は設定していませんが、あらかじめ設定する予定のパラメーター名を決めておいてそれを指定します。





<b>■ステップ２：パラメーターの値を指定して関数として保存</b>

クエリが決まったら、関数として保存します。
この時にパラメーターも指定します。


「保存」-> 「関数として保存」を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3564376/f20944ba-29c2-35fb-08d2-6b7831d8c11f.png)


画面下部の項目でパラメーターを設定（他の設定項目は割愛）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3564376/622d32ca-2a72-6459-8211-031355953101.png)

各項目を指定します。（複数パラメーターを指定可）
「タイプ」には、設定するパラメーター値のスキーマを指定（※１）
「名前」にはパラメーターとして使用する変数の名前を指定（ステップ１で指定したもの）
「既定値」には、パラメーターを指定せずに関数を実行した場合に代入したい値を指定（※２）

（※１）今回のように既存の列への参照値として使用する場合は、当然その列と同じスキーマを指定する必要があるので予め getschema 等でスキーマを確認しておきます。

（※２）今回は文字列（string型）を指定するので、ダブルコーテーションでくくった状態で
　"Botnet" と指定します。既定値を用いない場合は空欄でOKです。


問題なければ関数を保存してください。


<b>■ステップ３：関数を使ってみる</b>

関数作成に成功すると、その後は予測候補に挙がってくるようになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3564376/de8dc1a7-a206-341e-847a-2bfa15e181d4.png)


パラメーターを指定せずに関数をそのまま実行してみると、既定値で指定した条件通りに実行されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3564376/4193ad6b-bdb3-48f6-37f2-d7859541c81a.png)

上記は以下の条件で実行されています。
| where ThreatType == Param_ThreatType　
※Param_ThreatType = "Botnet"（既定値）



今度は、パラメーターを指定して実行してみます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3564376/f90678a6-511b-6164-3586-d2b2da8ded04.png)


この場合は以下の条件で実行されています。
| where ThreatType == Param_ThreatType　
※Param_ThreatType = "Phishing"




<b>■ステップ４：複数パラメータを指定する場合のあれこれ</b>

パラメーターを複数指定することもできるので、３つ指定してみましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3564376/93e3979c-023b-0668-f2e5-7a81bd109fb1.png)




前述と同様に関数を保存しますが、このとき Param_ThreatType だけ同じ既定値を指定し、
新しい２つは既定値なしとします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3564376/015b1941-bd25-f7f7-7d3b-6116e5d370fa.png)






この内容で保存した場合、前回のようにそのまま実行したらどうなるでしょうか？
やってみましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3564376/b1398094-adcd-b0e8-569f-742d63724d93.png)


エラーになってしまいました。パラメーターが指定されていないといわれていますね。
これはパラメーターの２つを既定値なしとしたにも関わらず指定せずに実行したからです。
ではこのような複数パラメーターを使用する場合の指定方法はどうなるでしょうか。

複数パラメーターを指定する場合は、「関数を表示した際のパラメーター欄の上から」の順序で記述します。
※関数を作成したときの記述の順序ではないため注意。下記画面の表示順序が扱われます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3564376/08b7abab-912c-0b81-895e-974bf7b06bfa.png)


上記画面の内容によると、今回はこのような順序で指定すればよいことになります。
(1) Param_ConfidenceScore
(2) Param_Action
(3) Param_ThreatType

というわけで、関数使用の際に指定する順序も同じように(1)～(3)の並びになるように指定します。

※既定値を変更しない（指定しない）で関数を実行する場合
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3564376/9bb04729-c904-c4cf-4663-d81111229eed.png)


※既定値を変更して（指定して）関数を実行する場合
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3564376/21a9b474-0c5e-0fbd-65b6-4fa968a5e886.png)


上記のように指定すれば、作成した関数は意図通りに使用できますが、
ここで指定方法を間違えた場合の出力結果も確認しておきましょう。


まず、以下の画像のような指定を行った場合はどのような結果になっていると言えるでしょうか？
クエリエラーにはなっていないので、パラメーターの指定は足りないわけではありません。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3564376/6aec1c55-53b6-6072-99c3-a652e33d9a6c.png)

正解は・・
上記の記述ではこのように指定されています。
(1) Param_ConfidenceScore == "alert"
(2) Param_Action == "Malware"
(3) Param_ThreatType == "Botnet"



さらに、パラメーターを１つだけ指定した場合は Param_Action の指定がない（＝(2)の指定がない）というエラーになりました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3564376/f7e06ccc-7adb-2235-a91c-7a7fcf84b572.png)

この場合はこのように代入されています。
(1) Param_ConfidenceScore == 100
(2) Param_Action == 
(3) Param_ThreatType == "Botnet"

(2)の指定がないので、空欄で where されてしまってクエリエラーになったわけです。
(3)は既定値のまま。

逆にこのように指定した場合はクエリエラーになりません。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3564376/ef921921-802a-02aa-1f26-7447e3bc23bf.png)

この場合はこのように代入されています。
(1) Param_ConfidenceScore == 100
(2) Param_Action == ""
(3) Param_ThreatType == "Botnet"

where の条件に "" を使用することは誤った記述ではないためクエリが正常に処理されたわけです。



このようにパラメーターを正しく指定しない場合、エラーになるだけでなく意図しない結果になることもあります。
クエリがエラーになってくれればまだ気づけますが今回の例のように where 文では「"該当なしという結果" が正常に出力される」こともあるため間違いに気づきにくい点に注意が必要です。



# Azure ブックでの応用

ブックのパラメーター値を代入させることができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3564376/2c2e6296-06f5-1dd8-5c86-8e05315f48bf.png)

個別に同じようなクエリを記述していると管理も大変ですが、
関数とパラメーターをうまく使えば運用をかなり簡素化できます。




# まとめ

メリット
・関数化することで同じクエリの使いまわしとアップデートを簡素化
・１つの関数でも、パラメーターで拡張性を持たせらせる
・その関数のパラメーターの規則を知らない人間には利用させづらくできる

デメリット
・パラメーターの設計と運用上の指定方法には十分な検討が必要


クエリの利用方法として、「関数」と「パラメーター」の機能について紹介しました。
パラメーター自体のコントロールは少し面倒なところもありますが、全体的にはメリットを享受できる結果が得られると思います。
Azure ブックをよく使うシナリオでは活用しやすいので、ご参考頂ければ幸いです。