🤖

Copilot for Security (のようなもの) を自作する

2024/06/07に公開

はじめに

Copilot for Security はインシデントのサマリ作成や影響の分析、スクリプトの高度な分析などセキュリティの運用を支援するサービスです。こちら、大まかには以下のような仕組みで動いています。

  1. ユーザー入力したプロンプトを Azure OpenAI (AOAI) が分析し、使用するプラグイン (Microsoft Defender や Sentinel などの情報の取得元) を決定
  2. プラグインにアクセスし、回答に必要な情報を収集
  3. 取得した情報とプロンプトを組み合わせ、Azure Open AI で再度分析
  4. Azure OpenAI が回答を作成
  5. 必要に応じて後処理としてプラグインにアクセスし情報を補完
  6. ユーザーに回答

かなり簡略化しているため、詳細はこちらから確認ください。
https://learn.microsoft.com/ja-jp/copilot/security/microsoft-security-copilot#how-does-copilot-for-security-work

これを見ると Azure OpenAI を使って簡易版を自作できるのでは・・・と思ったので、勉強がてら検証してみようと思います。

Azure OpenAI の動作確認

まず、1. のプラグインの選択が正確に動くのか不安なので、Azure OpenAI Studio のチャット プレイグラウンドにて Azure OpenAI 単体で動作確認してみます。使用しているモデルは gpt-4o の ver.2024-05-13 です。

システム メッセージに以下のような指示をしてみました。

You are an excellent security analyst.
Please review the questions asked in the chat and select the connector and its parameters to be used from the following.
If you determine that more than one should be used, please include more than one in your response.

<Connector Info>----
GetSentinelIncidentInfo:
Get incident details from Sentinel. Parameter is the incident ID.

GetUserInfo:
Get user details from Microsoft Entra. Parameter is the user account name like email address format.
----

After making your selection, please reply in the following json format.
{
    "status": "succeeded",
    "connectors": [
        {
            "connector": "<connector that you select>", 
            "parameter": "<parameter that you select>"
        },
        {
            "connector": "<connector that you select>",
            "parameter": "<parameter that you select>"
        }
    ]
}

If the connector cannot be identified, please create a message requesting the user to provide the information necessary to determine the connector and respond in the following json format.
{
    "status": "failed",
    "message": "<your message to user>" 
}

以下のように分かりやすいプロンプトであれば、想定通り応答しています。(なぜか文字が大きく表示されますが)


想定外の質問についても回答してくれます。

Logic Apps で実装 (プロンプト受信~コネクタ決定)

上記の Azure OpenAI を使用して Logic Apps で Copilot for Security のようなものを自作していきます。

まず、HTTP リクエスト受信時に動作するようにトリガーを設定し、Request Body でプロンプトを受け取るようにします。


次に Azure OpenAI をキックします。本来は組み込みのコネクタを使用したかったのですが、どうやってもエラーが解消せずに諦めました。そのため、HTTP リクエストで REST API を叩きます。HTTP の Body をスッキリさせるため、システム メッセージを変数に格納し、HTTP リクエストの Body にシステム メッセージ、トリガーで受け取ったユーザーからのプロンプトを以下のように指定します。

なお、Azure OpenAI の REST API の仕様は以下で確認しています。
https://learn.microsoft.com/ja-jp/azure/ai-services/openai/reference

あとは Azure OpenAI からの応答を JSON 解析し、プロンプトに対する回答部分のみ抜き出し、Logic Apps の応答としてユーザーに返します。


なお、JSON 解析のスキーマは一度 Azure OpenAI への HTTP リクエスト実行までのフローでテスト実行し、Response Body を [サンプルのペイロードを使用してスキーマを生成する] から指定すれば簡単に設定可能です。responseFromAOAI は アプリ コードビューから @{body('JSON_の解析_-Response_from_AOAI')?['choices'][0]?['message']?['content']} を指定しています。


テストしてみます。


想定通りの応答が返ってきており、実行履歴からもすべて正常に処理されていることが確認できました。

Logic Apps で実装 (コネクタ処理~応答)

コネクタ決定の動作が確認できたので、応答コネクタは一旦削除して、AOAI からの json 形式の応答をもとに、Azure Monitor ログ コネクタを実行していきます。(Sentinel コネクタを使おうと思いましたが、ARM ID を指定する必要があったため Azure Monitor ログ コネクタで KQL クエリを使用してインシデント情報を取得します。)

まず、AOAI からの応答を json 解析し、Azure Monitor ログ コネクタからの応答を格納する配列変数 (複数回実行される可能性があるため) を初期化します。次に AOAI からの応答に基づいて connectors でループ処理させます。さらにループ内で AOAI からの応答に含まれる connector の文字列で条件判定し、GetSentinelIncidentInfo であれば、クエリを実行 -> クエリ結果のレコードを結合 (クエリによっては複数レコードになるため) -> 配列変数に格納をしています。


なお、使用している KQL クエリは以下です。インシデント ID を条件として、インシデント 1 件に含まれる複数のアラートを取得し、インシデントのテーブルを展開・結合しています。

let incidentNumber = "<parameter のインシデント ID を指定>";
SecurityIncident
| where TimeGenerated >= ago (90d)
| where IncidentNumber == incidentNumber
| mv-expand AlertIds
| extend AlertId = tostring(AlertIds)
| join kind=inner(SecurityAlert) on $left.AlertId == $right.SystemAlertId

同様に Microsoft Entra ID 側も以下のように作成します。こちらは複数レコードがコネクタの応答になることはないため、結合の処理を省いています。


各コネクタからデータを受け取ったところで、それらを利用して AOAI に回答作成を依頼します。以下のようにユーザーからのプロンプト、Microsoft Entra ID、Sentinel からの参照データをメッセージとして送ります。


最後に AOAI からの応答を Logic Apps の応答として返します。フロントのアプリで処理しやすいように応答も json 形式にしています。

動作確認

以下のプロンプトで動作確認してみます。


無事応答が返ってきました。改行コードを整理するとそれなりの文章になっています。なお、Copilot for Security 同様、応答におおよそ 50~60 秒はかかります。(なので Copilot for Security が決して遅いわけではない)


別の依頼をしてみます。こちらも Copilot for Security のような内容が返ってきています。

おまけ

簡易的な UI ですが、ChatGPT に python コード と html を書いてもらい、チャット形式にしました。

まとめ

同様の仕組みでコネクタや処理 (Copilot for Security でいうスキル) を増やしていけばよいかと思いますが、多数の機能の実装やメンテナンス、想定外のプロンプトの処理、エラーハンドリングなど、考慮すべきポイントが非常に多く、やはり Copilot for Security と同等のものを、というのは難易度がかなり高くコストもかかると思います。
Copilot for Security には Defender XDR ポータルなどへの組み込みも提供されており、SCU を作成すればすぐに使用可能、さらに多くの 3rd パーティー製品やカスタムのプラグインも準備されており、機能追加もされていくはずです。そのように考えると、今回自作を試したことで、Copilot for Security が非常に優れたサービスであることを実感できました。

Microsoft (有志)

Discussion