mcpField
A
azure-kusto-irql-graph

azure-kusto-irql-graph

github.com/microsoft数据与数据库1.6k750 次安装今天更新
代码仓库

关于 azure-kusto-irql-graph

此技能将现有 KQL 或 IRQL 表格结果映射为图,用于在 Kusto Explorer 中可视化、折叠、提取或丰富节点。它面向已有查询结果的 Kusto 用户,不负责把一般自然语言转换为查询。

主要功能

  1. 01用 Lift_To_Graph 映射表格结果
  2. 02通过 Graph_Render_View 渲染图
  3. 03按属性折叠节点并重连边
  4. 04提取节点属性或丰富图数据

适用场景

  1. 01把认证事件查询结果绘制为关系图
  2. 02按共享属性合并节点
  3. 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.md
EXAMPLES.md
KUSTO_EXPLORER_LAUNCH.md

详细介绍

IRQL 图函数——将查询结果转换为可视化图

将 IRQL 图函数系列应用于表格结果。根据 KQL 或 IRQL 查询以及用户对图的描述,生成 Lift_To_Graph 映射,并仅组合在 Kusto Explorer 中可视化、折叠、提取或丰富图所需的已存储图函数。源查询不需要使用 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。
  • 仅当基本的自然语言数据源请求可直接映射到一个已知表或 IRQL Get_* 选择器,且列明显、筛选简单时,才支持此类请求。请说明假定的数据源,不要臆造联接、架构或调查逻辑。
  • 对于非简单的查询构建,请先使用单独的 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。

node_types[]
字段必需描述
type是节点类型标签(例如 "User"、"Host"、"IP")
id是节点 ID 前缀,通常与类型相同
key是值将成为节点身份标识的列名
props是要作为节点属性携带的列数组
defaults否用于空属性的回退值对象
defIcon否此节点类型的默认图标 URL
displayName否用作显示标签的列(默认为 id)
color否用于提供颜色的列
size否用于提供大小的列
edges[]
字段必填描述
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:

  1. 识别实体 -> 每个不同的名词都成为一个 node_type
  2. 识别关系 -> 每个动词/介词都成为一条 edge
  3. 映射到列 -> 使用所提供查询实际生成的列;切勿假设存在不可用的列
  4. 设置方向 -> 源是动作的发出者,目标是动作的承受者
  5. 添加属性 -> 包含与调查相关的列(时间戳、结果、哈希)
  6. 分配图标 -> 根据实体类型从上述图标集中选择
列参考(IRQL 统一架构)
实体键列可用属性
用户UsernameUsername、Name、Role、Email
主机HostnameHostname
IPClientIpClientIp
电子邮件SubjectEnvTime、Subject、Verdict、Url
发件人EmailSenderEmailSender、Domain
收件人EmailRecipientEmailRecipient
进程ProcessNameEnvTime、ProcessName、ProcessCommandLine、ProcessHash
文件FilenameEnvTime、Filename、Path、Sha256
域DomainNameDomainName
身份验证事件(合成 ID)EnvTime、UserAgent、Result、Description

函数选择

  1. 从提供的 KQL/IRQL 表格管道开始。
  2. 使用 Lift_To_Graph(mapping) 创建图实体。
  3. 仅在用户要求且与映射键兼容时,添加 Extract_Node_*、Enrich_Node_* 或 Enrich_Graph_*。
  4. 仅在用户要求分组/折叠时,添加 Graph_Fold_By_Property()。
  5. 以 Graph_Render_View() 结束可视化输出。
  6. 对所选管道中准确存储的函数进行预检。

管道模式

// 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 -> 用户 -> 主机

输入查询: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()
电子邮件图:发件人 -> 邮件 -> 收件人

输入查询: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 到域名的连接图,并通过员工姓名丰富图数据。”

这是有限的回退方案:一个已知选择器、一个提取器和一个直接筛选条件。

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()
进程执行图:用户 -> 进程 -> 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()

查询结果 -> 映射转换

当用户提供查询并描述图时:

  1. 检查查询的最终输出列
  2. 解析实体名词和关系动词
  3. 仅使用这些列生成映射 JSON
  4. 保留提供的管道,并追加 Lift_To_Graph()
  5. 在末尾包含 Graph_Render_View()
  6. 如果用户提到分组/折叠,且该函数存在,则添加 Graph_Fold_By_Property()

在必需函数预检通过后,输出完整的 KQL —— 即用户提供的查询,以及作为字符串 let 绑定内联的映射 JSON。如果无法检查目标数据库,请明确标记未经验证的函数依赖项。

在 Kusto Explorer 中打开查询(仅限 Windows)

可选的便利功能。 默认工作流是在聊天中输出 KQL,让用户手动将其复制到 Kusto Explorer 或 VS Code Kusto 扩展中。仅在用户选择启用时自动启动。

始终在聊天回复中输出完整的 KQL 查询,并清楚标注步骤 1(连接)和步骤 2(查询):

// 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 确认
  • 在打开文件前,在聊天中显示文件内容,供用户检查
  • 绝不使用 shell 插值或 here-string;通过 Set-Content/Add-Content 写入文件
  • 绝不将查询编码到浏览器 URL 中
  • 在 macOS/Linux 上,保存 .kql 文件,并建议使用 VS Code Kusto 扩展或 ADX Web Explorer

评论

支持 Markdown