Funciones de Grafo IRQL -- De Resultados de Consultas a Visualización
Aplica la familia de funciones de grafo IRQL a resultados tabulares. Dada una consulta KQL o IRQL y la descripción del grafo por parte del usuario, genera un mapeo Lift_To_Graph y compone únicamente las funciones de grafo almacenadas necesarias para visualizar, plegar, extraer o enriquecer el grafo en Kusto Explorer. La consulta fuente no necesita usar IRQL.
Alcance y Enrutamiento
| Solicitud | Uso |
|---|---|
| Convertir filas KQL/IRQL proporcionadas en un grafo visual decorado con íconos | Esta habilidad: Lift_To_Graph + Graph_Render_View |
Plegar nodos o aplicar Extract_Node_*, Enrich_Node_* o Enrich_Graph_* | Esta habilidad |
Usar make-graph, graph-match, caminos más cortos, componentes conectados, modelos de grafo o instantáneas | azure-kusto-graph |
| Redactar una investigación no trivial en KQL/IRQL a partir de lenguaje natural | Una habilidad de generación de consultas Kusto o IRQL, luego esta habilidad |
Si una solicitud mezcla visualización y análisis de grafo nativo, usa esta habilidad para la parte de elevación/renderización y azure-kusto-graph para la semántica de operadores. No reemplaces las funciones de elevación de grafo con un grafo construido manualmente basado en aristas a menos que el usuario solicite operadores de grafo nativos.
Contrato de Entrada
- Entrada preferida: una consulta KQL o IRQL funcional que produzca resultados tabulares, más una descripción en lenguaje natural de los nodos, aristas, etiquetas, íconos, extracciones, enriquecimientos o pliegues deseados.
- Esta habilidad no es un convertidor de lenguaje natural a KQL o NL a IRQL. Transforma resultados de consultas existentes en visualizaciones de grafo. Para conversión general de NL a KQL o NL a IRQL, usa una habilidad dedicada de generación de consultas (disponible por separado).
- Preserva la recuperación, uniones, filtros y agregaciones de la consulta proporcionada. Añade solo proyecciones o IDs sintéticos requeridos por el mapeo del grafo.
- Una solicitud básica en lenguaje natural solo es compatible cuando mapea directamente a una tabla conocida o a un selector IRQL
Get_*con columnas obvias y filtros simples. Indica la fuente asumida y no inventes uniones, esquemas ni lógica de investigación. - Para construcción de consultas no triviales, usa primero una habilidad separada de generación de consultas Kusto/IRQL, luego aplica esta habilidad a su salida.
- Si no hay consulta ni esquema de salida disponible y la fuente no es trivial, solicita la consulta KQL o sus columnas de resultado antes de generar un mapeo.
Disparadores de Activación
Usa esta habilidad cuando el usuario:
- Proporcione resultados KQL/IRQL y solicite una visualización o mapeo de grafo IRQL
- Mencione
Lift_To_Graph,Graph_Render_ViewoGraph_Fold_By_Property - Solicite mapeos de nodos/aristas decorados con íconos en Kusto Explorer
- Desee plegar/colapsar nodos por una propiedad compartida
- Solicite extracción o enriquecimiento de grafo mediante
Extract_Node_*,Enrich_Node_*oEnrich_Graph_*
No actives esta habilidad únicamente para graph-match, caminos/componentes de grafo, grafos persistentes o construcción genérica de make-graph; esos pertenecen a azure-kusto-graph.
No es un convertidor de lenguaje natural a KQL/IRQL. La entrada generalmente debe ser una consulta KQL o IRQL funcional cuyos resultados necesiten visualización de grafo. Las solicitudes básicas en lenguaje natural solo funcionan para casos triviales de tabla/selector único. Para NL a KQL o NL a IRQL general, usa una habilidad dedicada de generación de consultas (disponible por separado).
Entorno
- Clúster:
https://kc7001.eastus.kusto.windows.net - Bases de datos:
ValdyTimes,JoJosHospital(funciones de grafo pre-desplegadas) - Renderizado: Aplicación de escritorio Kusto Explorer (ventana de visualización make-graph)
- Herramienta:
kusto_query(a través de Azure MCP Server)
Verificación Previa de Funciones
Lift_To_Graph y Graph_Render_View son funciones almacenadas, no operadores Kusto integrados. Antes de generar o ejecutar una tubería de elevación contra una base de datos objetivo, verifica qué está desplegado:
.show functions
| where Name in~ ("Lift_To_Graph", "Graph_Render_View", "Graph_Fold_By_Property")
| project Name
Lift_To_GraphyGraph_Render_Viewson obligatorios.Graph_Fold_By_Propertysolo es obligatorio cuando se solicita plegado.- Verifica cualquier función
Extract_Node_*,Enrich_Node_*oEnrich_Graph_*antes de usarla; omite el enriquecimiento opcional cuando no esté disponible a menos que el usuario quiera desplegarlo. - Si falta una función requerida y tienes permiso para alterar la base de datos, pide al usuario confirmación antes de desplegarla. Luego usa las definiciones de
.create-or-alter functionen references/DEPLOY_IRQL_FUNCTIONS.md. Ejecuta el bloque.create-or-altercorrespondiente, luego vuelve a ejecutar la verificación previa para confirmar. - Si no tienes permisos de alteración, informa al usuario qué funciones faltan y señálale
references/DEPLOY_IRQL_FUNCTIONS.mdpara despliegue manual.
Familia de Funciones de Grafo IRQL
Lift_To_Graph(T, mappingJson)
Transforma cualquier resultado tabular KQL en una tabla unificada de nodos + aristas.
Entrada: Cualquier tabla T + una cadena JSON de mapeo.
Salida: Filas con EntityType = "node" o "edge", listas para make-graph.
Graph_Render_View(T)
Toma la salida de Lift_To_Graph, divide nodos/aristas y llama a make-graph para abrir la ventana de grafo de Kusto Explorer.
Graph_Fold_By_Property(T, NodeType, PropertyName)
Colapsa nodos de un tipo dado que comparten un valor de propiedad en un solo nodo. Re-conecta aristas automáticamente.
Funciones de Extracción y Enriquecimiento de Grafo
Estas son funciones almacenadas adicionales que ya deben estar desplegadas en la base de datos objetivo. No están incluidas en references/DEPLOY_IRQL_FUNCTIONS.md. Usa .show functions para verificar disponibilidad antes de incluirlas en una tubería.
| Función | Operación | Propiedad Clave |
|---|---|---|
Extract_Node_Email_Sender_Domain(T, displayName) | Añade Domain a props de nodo | EmailSender |
Extract_Node_Employee_Firstname(T, displayName) | Añade Firstname a props de nodo | Name |
Extract_Node_Event_Network_Domain(T, displayName) | Añade DomainName a props de nodo | Url |
Enrich_Node_Ip_Employee(T, displayName) | Añade info de empleado a nodos IP | ClientIp |
Enrich_Node_Username_Employee(T, displayName) | Añade info de empleado a nodos de usuario | Username |
Enrich_Node_Event_Authentication_Username(T, displayName) | Añade contexto de autenticación | Username |
Enrich_Node_Ip_Domain(T, displayName) | Añade dominios DNS | ClientIp |
Enrich_Node_Ip_Event_NetworkOutbound(T, displayName) | Añade eventos salientes | ClientIp |
Enrich_Graph_Ip_Employee(T, mappingJson) | Expande grafo con nodos de empleado | ClientIp |
Enrich_Graph_Username_Employee(T, mappingJson) | Expande grafo con nodos de empleado | Username |
Enrich_Graph_Event_Authentication_Username(T, mappingJson) | Expande con nodos de autenticación | Username |
Esquema JSON de Mapeo
El mapeo JSON tiene dos arreglos: node_types y edges.
node_types[]
| Campo | Obligatorio | Descripción |
|---|---|---|
type | Sí | Etiqueta del tipo de nodo (ej. "User", "Host", "IP") |
id | Sí | Prefijo para el ID del nodo; generalmente igual que type |
key | Sí | Nombre de la columna cuyo valor se convierte en la identidad del nodo |
props | Sí | Arreglo de columnas a incluir como propiedades del nodo |
defaults | No | Objeto de valores de respaldo para propiedades nulas/vacías |
defIcon | No | URL del ícono por defecto para este tipo de nodo |
displayName | No | Columna a usar para la etiqueta de visualización (por defecto es id) |
color | No | Columna de la que obtener el color |
size | No | Columna de la que obtener el tamaño |
edges[]
| Campo | Obligatorio | Descripción |
|---|---|---|
type | Sí | Etiqueta del tipo de arista (ej. "AuthenticatesTo", "SentEmail") |
source | Sí | {"id": "<prefijo>", "type": "<NodeType>"} |
target | Sí | {"id": "<prefijo>", "type": "<NodeType>"} |
props | No | Arreglo de columnas a incluir como propiedades de la arista |
displayName | No | Columna para la etiqueta de la arista |
color | No | Columna para el color de la arista |
Repositorio de Íconos
Usa íconos de https://raw.githubusercontent.com/benc-uk/icon-collection/master/azure-icons/:
- IP:
Public-IP-Addresses-(Classic).svg - Host/VM:
Virtual-Machine.svg - Usuario:
Users.svg - Correo:
Mailbox.svg(oazure-cds/command-1070-Mail.svg) - Proceso:
App-Services.svg - Archivo:
Storage-Accounts.svg - Alerta:
Activity-Log.svg - Dominio:
DNS-Zones.svg
Reglas de Generación de Mapeo
Dadas las columnas de la consulta proporcionada y la descripción del grafo del usuario, genera el JSON de mapeo:
- Identificar entidades -> cada sustantivo distinto se convierte en un
node_type - Identificar relaciones -> cada verbo/preposición se convierte en una
edge - Mapear a columnas -> usa columnas reales producidas por la consulta proporcionada; nunca asumas columnas no disponibles
- Establecer dirección -> source es el actor, target es el actuado
- Añadir propiedades -> incluye columnas relevantes para la investigación (marcas de tiempo, resultados, hashes)
- Asignar íconos -> elige del conjunto de íconos anterior según el tipo de entidad
Referencia de Columnas (Esquema Unificado IRQL)
| Entidad | Columna Clave | Propiedades Disponibles |
|---|---|---|
| Usuario | Username | Username, Name, Role, Email |
| Host | Hostname | Hostname |
| IP | ClientIp | ClientIp |
| Mensaje de Correo | Subject | EnvTime, Subject, Verdict, Url |
| Remitente | EmailSender | EmailSender, Domain |
| Destinatario | EmailRecipient | EmailRecipient |
| Proceso | ProcessName | EnvTime, ProcessName, ProcessCommandLine, ProcessHash |
| Archivo | Filename | EnvTime, Filename, Path, Sha256 |
| Dominio | DomainName | DomainName |
| Evento de Autenticación | (ID sintético) | EnvTime, UserAgent, Result, Description |
Selección de Funciones
- Comienza con la tubería tabular KQL/IRQL proporcionada.
- Usa
Lift_To_Graph(mapping)para crear entidades de grafo. - Añade
Extract_Node_*,Enrich_Node_*oEnrich_Graph_*solo cuando se solicite y sea compatible con las claves mapeadas. - Añade
Graph_Fold_By_Property()solo cuando se solicite agrupación/colapso. - Termina la salida visual con
Graph_Render_View(). - Verifica previamente las funciones almacenadas exactas seleccionadas para la tubería.
Patrón de Tubería
// 1. Preserva la consulta KQL o IRQL proporcionada
<consulta de entrada>
// 2. Elevar a grafo
| invoke Lift_To_Graph(<mapping_json>)
// 3. Opcionalmente extraer o enriquecer entidades de grafo
| invoke <Extract_Node_* | Enrich_Node_* | Enrich_Graph_*>()
// 4. Opcionalmente plegar nodos cuando se solicite
| invoke Graph_Fold_By_Property("<NodeType>", "<PropertyName>")
// 5. Renderizar
| invoke Graph_Render_View()
Ejemplos
Para más indicaciones y ejemplos trabajados, consulta references/EXAMPLES.md.
Grafo de Autenticación: IP -> AuthEvent -> Usuario -> Host
Consulta de entrada: Get_Event_Authentication_All | where Result == "Failed Login" | take 200
Solicitud de grafo: "Mostrar IPs, eventos de autenticación, usuarios y hosts; plegar eventos por resultado."
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()
Grafo de Correo: Remitente -> Mensaje -> Destinatario
Consulta de entrada: Get_Email_All | take 400
Solicitud de grafo: "Visualizar flujo de remitente a mensaje a destinatario y plegar mensajes por veredicto."
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()
Investigación de Dominio Sospechoso (de extremo a extremo)
Solicitud básica: "Usar eventos de red salientes para estos dominios sospechosos y graficar conexiones IP-a-dominio enriquecidas con nombres de empleados."
Este es el caso de respaldo limitado: un selector conocido, un extractor y un filtro directo.
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_Network_Outbound_All
| where DomainName in ("suspicious.com", "malicious.net")
| take 300
| invoke Lift_To_Graph(suspicious_domain_mapping)
| invoke Enrich_Node_Ip_Employee("IP", "ClientIp")
| invoke Graph_Render_View()
Para más detalles, consulta la documentación completa de la habilidad o los ejemplos adicionales.