azure-kusto-irql-graph について
既存の KQL または IRQL の表形式結果をグラフに変換し、Kusto Explorer で可視化、折りたたみ、抽出、エンリッチメントを行うスキルです。クエリ結果を扱う Kusto ユーザー向けで、一般的な自然言語からのクエリ生成には対応しません。
主な機能
- 01Lift_To_Graph による表形式結果のマッピング
- 02Graph_Render_View によるグラフ描画
- 03プロパティ別のノード統合とエッジ再接続
- 04ノード属性の抽出やグラフの拡張
活用シーン
- 01認証クエリの結果をグラフで表示
- 02共通プロパティを持つノードの統合
- 03ノード情報の抽出や関連情報の追加
MCP 対応
Azure MCP Server 経由の `kusto_query` ツールで KQL を実行し、Kusto データベースにデプロイ済みのグラフ関数を使用します。
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ microsoft/ azure-skills --skill azure-kusto-irql-graphインストール後、Claude Code で/azure-kusto-irql-graphを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/DEPLOY_IRQL_FUNCTIONS.mdEXAMPLES.mdKUSTO_EXPLORER_LAUNCH.md詳細
IRQL グラフ関数 — クエリ結果を可視化
IRQL のグラフ関数ファミリーを表形式の結果に適用します。KQL または IRQL クエリとユーザーのグラフの説明に基づいて、Kusto Explorer でグラフを可視化、折りたたみ、抽出、または拡充するために必要な保存済みグラフ関数のみを組み合わせ、Lift_To_Graph マッピングを生成します。ソースクエリで IRQL を使用する必要はありません。
対象範囲と振り分け
| リクエスト | 使用するもの |
|---|---|
| 提供された KQL/IRQL の行を、アイコン付きのビジュアルグラフに変換する | このスキル:Lift_To_Graph + Graph_Render_View |
ノードを折りたたむ、または Extract_Node_*、Enrich_Node_*、Enrich_Graph_* を適用する | このスキル |
make-graph、graph-match、最短経路、連結成分、グラフモデル、スナップショットを使用する | azure-kusto-graph |
| 自然言語から高度な KQL/IRQL 調査クエリを作成する | Kusto または IRQL のクエリ生成スキルを使用し、その後このスキルを使用 |
リクエストに可視化とネイティブなグラフ分析が混在する場合は、リフトとレンダリングにこのスキルを使用し、演算子のセマンティクスには azure-kusto-graph を使用してください。ユーザーがネイティブなグラフ演算子を求めていない限り、グラフリフト関数を手作業で構築したエッジ優先のグラフに置き換えないでください。
入力仕様
- 推奨される入力:表形式の結果を生成する、動作する KQL/IRQL クエリと、希望するノード、エッジ、ラベル、アイコン、抽出、拡充、折りたたみの自然言語による説明。
- このスキルは自然言語から KQL/IRQL への変換ツールではありません。既存のクエリ結果をグラフの可視化に変換します。一般的な自然言語から KQL/IRQL への変換には、専用のクエリ生成スキル(別途利用可能)を使用してください。
- 提供されたクエリの取得、結合、フィルター、集計を維持してください。グラフマッピングに必要な射影または合成 ID のみを追加してください。
- 基本的な自然言語によるソースのリクエストがサポートされるのは、既知のテーブル 1 つ、または明確な列と単純なフィルターを持つ IRQL
Get_*セレクター 1 つに直接対応する場合に限られます。仮定したソースを明示し、結合、スキーマ、調査ロジックを作り出さないでください。 - 高度なクエリを構築する場合は、まず別の Kusto/IRQL クエリ生成スキルを使用し、その出力にこのスキルを適用してください。
- クエリも出力スキーマもなく、ソースが単純でない場合は、マッピングを生成する前に KQL クエリまたは結果の列を求めてください。
起動条件
次の場合にこのスキルを使用してください。
- ユーザーが KQL/IRQL の結果を提供し、IRQL グラフの可視化またはマッピングを求めている
Lift_To_Graph、Graph_Render_View、Graph_Fold_By_Propertyに言及している- Kusto Explorer でアイコン付きのノード/エッジマッピングを求めている
- 共通プロパティに基づいてノードを折りたたむよう求めている
Extract_Node_*、Enrich_Node_*、Enrich_Graph_*を使用したグラフの抽出または拡充を求めている
graph-match、グラフパス/連結成分、永続グラフ、一般的な make-graph の構築だけを求めている場合は、このスキルを起動しないでください。これらは azure-kusto-graph の対象です。
自然言語から KQL/IRQL への変換ツールではありません。 通常、入力には、結果をグラフとして可視化する必要がある動作する KQL または IRQL クエリを使用します。基本的な自然言語によるソースのリクエストに対応できるのは、単純な単一テーブル/セレクターの場合に限られます。一般的な自然言語から KQL/IRQL への変換には、専用のクエリ生成スキル(別途利用可能)を使用してください。
環境
- クラスター:
https://kc7001.eastus.kusto.windows.net - データベース:
ValdyTimes、JoJosHospital(グラフ関数は事前にデプロイ済み) - レンダリング:Kusto Explorer デスクトップアプリ(make-graph 可視化ウィンドウ)
- ツール:
kusto_query(Azure MCP Server 経由)
関数の事前確認
Lift_To_Graph と Graph_Render_View はストアド関数であり、Kusto の組み込み演算子ではありません。対象データベースに対するリフトパイプラインを生成または実行する前に、デプロイ状況を確認してください。
.show functions
| where Name in~ ("Lift_To_Graph", "Graph_Render_View", "Graph_Fold_By_Property")
| project Name
Lift_To_GraphとGraph_Render_Viewは必須です。Graph_Fold_By_Propertyは、折りたたみを要求する場合にのみ必要です。- 使用する前に、
Extract_Node_*、Enrich_Node_*、またはEnrich_Graph_*関数があるか確認してください。ユーザーがデプロイを希望しない限り、利用できないオプションのエンリッチメントは省略してください。 - 必須関数がなく、データベースを変更する権限がある場合は、デプロイする前にユーザーの確認を求めてください。その後、references/DEPLOY_IRQL_FUNCTIONS.md の
.create-or-alter function定義を使用します。該当する.create-or-alterブロックを実行し、事前確認を再実行してデプロイを確認してください。 - 変更権限がない場合は、不足している関数をユーザーに伝え、手動でデプロイするために
references/DEPLOY_IRQL_FUNCTIONS.mdを参照するよう案内してください。
IRQL グラフ関数ファミリー
Lift_To_Graph(T, mappingJson)
任意の表形式 KQL の結果を、ノードとエッジを統合したテーブルに変換します。
入力:任意のテーブル T と JSON マッピング文字列。
出力:EntityType が "node" または "edge" の行。make-graph で使用できます。
Graph_Render_View(T)
Lift_To_Graph の出力を受け取り、ノードとエッジに分割して、make-graph を呼び出し、Kusto Explorer のグラフウィンドウを開きます。
Graph_Fold_By_Property(T, NodeType, PropertyName)
指定したプロパティ値を共有する特定の型のノードを、単一のノードにまとめます。エッジは自動的に再接続されます。
グラフ抽出およびエンリッチメント関数
これらは、対象データベースにあらかじめデプロイされている必要がある追加のストアド関数です。references/DEPLOY_IRQL_FUNCTIONS.md には含まれていません。パイプラインに含める前に、.show functions を使用して利用可能か確認してください。
| 関数 | 操作 | キープロパティ |
|---|---|---|
Extract_Node_Email_Sender_Domain(T, displayName) | ノードのプロパティに Domain を追加 | EmailSender |
Extract_Node_Employee_Firstname(T, displayName) | ノードのプロパティに Firstname を追加 | Name |
Extract_Node_Event_Network_Domain(T, displayName) | ノードのプロパティに DomainName を追加 | Url |
Enrich_Node_Ip_Employee(T, displayName) | IP ノードに従業員情報を追加 | ClientIp |
Enrich_Node_Username_Employee(T, displayName) | ユーザーノードに従業員情報を追加 | Username |
Enrich_Node_Event_Authentication_Username(T, displayName) | 認証コンテキストを追加 | Username |
Enrich_Node_Ip_Domain(T, displayName) | DNS ドメインを追加 | ClientIp |
Enrich_Node_Ip_Event_NetworkOutbound(T, displayName) | アウトバウンドイベントを追加 | ClientIp |
Enrich_Graph_Ip_Employee(T, mappingJson) | グラフを従業員ノードで拡張 | ClientIp |
Enrich_Graph_Username_Employee(T, mappingJson) | グラフを従業員ノードで拡張 | Username |
Enrich_Graph_Event_Authentication_Username(T, mappingJson) | 認証ノードでグラフを拡張 | Username |
マッピング JSON スキーマ
JSON マッピングには、node_types と edges の 2 つの配列があります。
node_types[]
| フィールド | 必須 | 説明 |
|---|---|---|
type | はい | ノード型のラベル(例:"User"、"Host"、"IP") |
id | はい | ノード ID のプレフィックス。通常は型と同じです |
key | はい | 値がノードの識別情報になる列名 |
props | はい | ノードのプロパティとして引き継ぐ列の配列 |
defaults | いいえ | null または空のプロパティに使用する代替値のオブジェクト |
defIcon | いいえ | このノード型のデフォルトアイコン URL |
displayName | いいえ | 表示ラベルに使用する列(デフォルトは id) |
color | いいえ | 色の取得元となる列 |
size | いいえ | サイズの取得元となる列 |
edges[]
| Field | Required | Description |
|---|---|---|
type | はい | エッジの種類を表すラベル(例:"AuthenticatesTo"、"SentEmail") |
source | はい | {"id": "<prefix>", "type": "<NodeType>"} |
target | はい | {"id": "<prefix>", "type": "<NodeType>"} |
props | いいえ | エッジのプロパティとして保持する列の配列 |
displayName | いいえ | エッジのラベルに使う列 |
color | いいえ | エッジの色に使う列 |
アイコンリポジトリ
https://raw.githubusercontent.com/benc-uk/icon-collection/master/azure-icons/ のアイコンを使用します。
- IP:
Public-IP-Addresses-(Classic).svg - ホスト/VM:
Virtual-Machine.svg - ユーザー:
Users.svg - メール:
Mailbox.svg(またはazure-cds/command-1070-Mail.svg) - プロセス:
App-Services.svg - ファイル:
Storage-Accounts.svg - アラート:
Activity-Log.svg - ドメイン:
DNS-Zones.svg
マッピング生成ルール
指定されたクエリ列とユーザーのグラフの説明に基づき、次の手順でマッピング JSON を生成します。
- エンティティを特定する → 異なる名詞ごとに
node_typeを作成します - 関係を特定する → 動詞や前置詞ごとに
edgeを作成します - 列にマッピングする → 指定されたクエリで実際に生成される列を使います。利用できない列を想定してはいけません
- 方向を設定する → source は動作を行う側、target は動作の対象です
- プロパティを追加する → 調査に関連する列(タイムスタンプ、結果、ハッシュ)を含めます
- アイコンを割り当てる → 上記のアイコンセットからエンティティの種類に応じて選びます
列リファレンス(IRQL 統合スキーマ)
| Entity | Key Column | Available Props |
|---|---|---|
| ユーザー | Username | Username、Name、Role、Email |
| ホスト | Hostname | Hostname |
| IP | ClientIp | ClientIp |
| メールメッセージ | Subject | EnvTime、Subject、Verdict、Url |
| 送信者 | EmailSender | EmailSender、Domain |
| 宛先 | EmailRecipient | EmailRecipient |
| プロセス | ProcessName | EnvTime、ProcessName、ProcessCommandLine、ProcessHash |
| ファイル | Filename | EnvTime、Filename、Path、Sha256 |
| ドメイン | DomainName | DomainName |
| 認証イベント | (合成 ID) | EnvTime、UserAgent、Result、Description |
関数の選択
- 指定された KQL/IRQL の表形式パイプラインから始めます。
Lift_To_Graph(mapping)を使ってグラフエンティティを作成します。- マッピングされたキーと互換性があり、要求された場合にのみ
Extract_Node_*、Enrich_Node_*、またはEnrich_Graph_*を追加します。 - グループ化または折りたたみが要求された場合にのみ
Graph_Fold_By_Property()を追加します。 - 視覚化出力の末尾には
Graph_Render_View()を指定します。 - パイプラインで選択した保存済み関数を事前に検証します。
パイプラインのパターン
// 1. Preserve the supplied KQL or IRQL query
<input query>
// 2. Lift to graph
| invoke Lift_To_Graph(<mapping_json>)
// 3. Optionally extract or enrich graph entities
| invoke <Extract_Node_* | Enrich_Node_* | Enrich_Graph_*>()
// 4. Optionally fold nodes when requested
| invoke Graph_Fold_By_Property("<NodeType>", "<PropertyName>")
// 5. Render
| invoke Graph_Render_View()
例
追加のプロンプトと実例については、references/EXAMPLES.md を参照してください。
認証グラフ:IP -> AuthEvent -> User -> Host
入力クエリ:Get_Event_Authentication_All | where Result == "Failed Login" | take 200
グラフのリクエスト:「IP、認証イベント、ユーザー、ホストを表示し、結果ごとにイベントを折りたたむ。」
let auth_mapping = '{"node_types":[{"type":"SrcIp","id":"SrcIp","key":"ClientIp","props":["ClientIp"],"defaults":{},"defIcon":"https://raw.githubusercontent.com/benc-uk/icon-collection/master/azure-icons/Public-IP-Addresses-(Classic).svg"},{"type":"Host","id":"Host","key":"Hostname","props":["Hostname"],"defaults":{},"defIcon":"https://raw.githubusercontent.com/benc-uk/icon-collection/master/azure-icons/Virtual-Machine.svg"},{"type":"User","id":"User","key":"Username","props":["Username"],"defaults":{},"defIcon":"https://raw.githubusercontent.com/benc-uk/icon-collection/master/azure-icons/Users.svg"},{"type":"AuthEvent","id":"AuthEvent","key":"AuthEventId","props":["AuthEventId","EnvTime","UserAgent","Result","Description"],"defaults":{"Result":"unknown"},"defIcon":"https://raw.githubusercontent.com/benc-uk/icon-collection/master/azure-icons/Activity-Log.svg"}],"edges":[{"type":"RequestsAuth","source":{"id":"SrcIp","type":"SrcIp"},"target":{"id":"AuthEvent","type":"AuthEvent"},"props":["EnvTime"]},{"type":"TargetsUser","source":{"id":"AuthEvent","type":"AuthEvent"},"target":{"id":"User","type":"User"},"props":["EnvTime"]},{"type":"AgainstHost","source":{"id":"AuthEvent","type":"AuthEvent"},"target":{"id":"Host","type":"Host"},"props":["EnvTime"]}]}';
Get_Event_Authentication_All
| extend AuthEventId = strcat(Username, "_", Hostname, "_", EnvTime)
| where Result == "Failed Login"
| take 200
| invoke Lift_To_Graph(auth_mapping)
| invoke Graph_Fold_By_Property("AuthEvent", "Result")
| invoke Graph_Render_View()
メールグラフ:Sender -> Message -> Recipient
入力クエリ:Get_Email_All | take 400
グラフのリクエスト:「送信者からメッセージ、宛先への流れを可視化し、判定結果ごとにメッセージを折りたたむ。」
let mail_mapping = '{"node_types":[{"type":"EmailMessage","id":"Message","key":"Subject","props":["EnvTime","Subject","Verdict"],"defaults":{},"defIcon":"https://raw.githubusercontent.com/benc-uk/icon-collection/master/azure-icons/Media-File.svg"},{"type":"Sender","id":"Email","key":"EmailSender","props":["EmailSender"],"defaults":{},"defIcon":"https://raw.githubusercontent.com/benc-uk/icon-collection/master/azure-cds/command-1070-Mail.svg"},{"type":"Recipient","id":"Email","key":"EmailRecipient","props":["EmailRecipient"],"defaults":{},"defIcon":"https://raw.githubusercontent.com/benc-uk/icon-collection/master/azure-cds/command-1070-Mail.svg"}],"edges":[{"type":"SentBy","source":{"id":"Message","type":"EmailMessage"},"target":{"id":"Email","type":"Sender"},"props":["EnvTime","Verdict"]},{"type":"DeliveredTo","source":{"id":"Message","type":"EmailMessage"},"target":{"id":"Email","type":"Recipient"},"props":["EnvTime","Verdict"]}]}';
Get_Email_All
| take 400
| invoke Lift_To_Graph(mail_mapping)
| invoke Graph_Fold_By_Property("EmailMessage", "Verdict")
| invoke Graph_Render_View()
不審なドメインの調査(エンドツーエンド)
基本ソースのリクエスト:「これらの不審なドメインに関するアウトバウンドネットワークイベントを使い、従業員名でエンリッチした IP とドメインの接続をグラフ化してください。」
これは限定的なフォールバックです。既知のセレクターが 1 つ、エクストラクターが 1 つ、直接フィルターが 1 つです。
let suspicious_domain_mapping = '{"node_types":[{"type":"IP","id":"IP","key":"ClientIp","props":["ClientIp"],"defaults":{},"defIcon":"https://raw.githubusercontent.com/benc-uk/icon-collection/master/azure-icons/Public-IP-Addresses-(Classic).svg"},{"type":"Domain","id":"Domain","key":"DomainName","props":["DomainName"],"defaults":{},"defIcon":"https://raw.githubusercontent.com/benc-uk/icon-collection/master/azure-icons/DNS-Zones.svg"}],"edges":[{"type":"ConnectsTo","source":{"id":"IP","type":"IP"},"target":{"id":"Domain","type":"Domain"},"props":["EnvTime"]}]}';
Get_Event_NetworkOutbound
| invoke Extract_Event_Network_Domain()
| where DomainName has_any ("raisinkanes.com", "nothing-to-see-here.net", "totally-legit-domain.com")
| invoke Lift_To_Graph(suspicious_domain_mapping)
| invoke Enrich_Node_Ip_Employee("Name")
| invoke Graph_Fold_By_Property("Domain", "DomainName")
| invoke Graph_Render_View()
プロセス実行グラフ:User -> Process -> ParentProcess
入力クエリ:Get_Event_Process_All | where ProcessCommandLine has "powershell" | take 300
グラフのリクエスト:「プロセス、親プロセス、ホスト、ユーザー間の関係を可視化してください。」
let proc_mapping = '{"node_types":[{"type":"Process","id":"Proc","key":"ProcessName","props":["ProcessName","ProcessCommandLine","ProcessHash"],"defaults":{},"defIcon":"https://raw.githubusercontent.com/benc-uk/icon-collection/master/azure-icons/App-Services.svg"},{"type":"ParentProcess","id":"Proc","key":"ParentProcessName","props":["ParentProcessName","ParentProcessHash"],"defaults":{},"defIcon":"https://raw.githubusercontent.com/benc-uk/icon-collection/master/azure-icons/App-Services.svg"},{"type":"Host","id":"Host","key":"Hostname","props":["Hostname"],"defaults":{},"defIcon":"https://raw.githubusercontent.com/benc-uk/icon-collection/master/azure-icons/Virtual-Machine.svg"},{"type":"User","id":"User","key":"Username","props":["Username"],"defaults":{},"defIcon":"https://raw.githubusercontent.com/benc-uk/icon-collection/master/azure-icons/Users.svg"}],"edges":[{"type":"SpawnedBy","source":{"id":"Proc","type":"Process"},"target":{"id":"Proc","type":"ParentProcess"},"props":["EnvTime"]},{"type":"RanOn","source":{"id":"Proc","type":"Process"},"target":{"id":"Host","type":"Host"},"props":["EnvTime"]},{"type":"ExecutedBy","source":{"id":"Proc","type":"Process"},"target":{"id":"User","type":"User"},"props":["EnvTime"]}]}';
Get_Event_Process_All
| where ProcessCommandLine has "powershell"
| take 300
| invoke Lift_To_Graph(proc_mapping)
| invoke Graph_Render_View()
クエリ結果からマッピングへの変換
ユーザーがクエリを提示し、グラフについて説明した場合:
- クエリの最終出力列を確認します
- エンティティを表す名詞と関係を表す動詞を解析します
- それらの列のみを使用してマッピング JSON を生成します
- 提示されたパイプラインを維持し、末尾に
Lift_To_Graph()を追加します - 最後に
Graph_Render_View()を含めます - ユーザーがグループ化/折りたたみについて言及し、その関数が存在する場合は、
Graph_Fold_By_Property()を追加します
必要な関数の事前チェックに合格した後、完全な KQL(提示されたクエリに、文字列の let バインディングとしてインラインのマッピング JSON を加えたもの)を出力します。対象データベースを確認できない場合は、未確認の関数依存関係を明確に示します。
Kusto Explorer でクエリを開く(Windows のみ)
任意の便利機能です。 デフォルトのワークフローでは、チャットに KQL を出力し、ユーザーが手動で Kusto Explorer または VS Code Kusto 拡張機能にコピーします。自動起動はオプトインの場合に限ります。
チャットの回答には、ステップ 1(接続)とステップ 2(クエリ)を明確に分けて、完全な KQL クエリを必ず出力します。
// Step 1: Connect to your cluster (skip if already connected)
// Example: uncomment to connect to the KC7 training cluster
// #connect cluster('kc7001.eastus.kusto.windows.net').database('ValdyTimes')
// Or replace with your own cluster:
// #connect cluster('<YOUR_CLUSTER>').database('<YOUR_DATABASE>')
// Step 2: Run the query below
<KQL_QUERY>
ユーザーが Kusto Explorer での保存または起動を求めた場合は、references/KUSTO_EXPLORER_LAUNCH.md の手順に従います。主なルール:
- ファイルの書き込みや実行ファイルの起動前に、
ask_userを使用して確認します - 開く前に、ユーザーが確認できるようファイルの内容をチャットに表示します
- シェルの文字列補間やヒアドキュメントは使用せず、
Set-Content/Add-Contentでファイルを書き込みます - クエリをブラウザーの URL にエンコードしません
- macOS/Linux では、
.kqlファイルを保存し、VS Code Kusto 拡張機能または ADX Web Explorer を提案します