Nota:
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
Importante
Parte de la información contenida en este artículo se refiere a un producto preliminar que puede sufrir modificaciones sustanciales antes de su lanzamiento comercial. Microsoft no otorga garantías, expresas o implícitas, con respecto a la información que aquí se proporciona.
Microsoft Defender detecta automáticamente los agentes de IA locales compatibles y los servidores MCP configurados en los dispositivos incorporados, y los muestra en el inventario de agentes de IA y en la búsqueda avanzada. Para más información sobre la detección de agentes de inteligencia artificial local, consulte Detección de agentes de inteligencia artificial local con Microsoft Defender para punto de conexión.
En este artículo, aprendes a ver los agentes descubiertos en el inventario, revisar su configuración y riesgo, explorar sus relaciones con dispositivos e identidades, e investigar la presencia de agentes utilizando caza avanzada.
Requisitos previos
Para poder detectar agentes de inteligencia artificial locales en puntos de conexión, asegúrese de cumplir los siguientes requisitos:
- El entorno está en la nube comercial. No se admiten nubes soberanas ni nacionales.
- Su organización tiene una licencia de Microsoft Defender para punto de conexión Plan 2. Para obtener más información, consulte Licencias.
- Los dispositivos se incorporan a Microsoft Defender para punto de conexión.
- Los dispositivos ejecutan una versión compatible de Windows o macOS, y Microsoft Defender Antivirus se actualiza con las actualizaciones actuales de la plataforma mensual y del motor.
- El antivirus Microsoft Defender está funcionando en modo activo en tus dispositivos, con la protección en tiempo real activada.
No necesita scripts, configuración o implementación adicionales más allá de los requisitos de incorporación de dispositivos. Si el dispositivo cumple todos los requisitos previos, la detección de agentes comienza automáticamente.
Licencias
Microsoft Defender para punto de conexión Plan 2 es la licencia mínima para el descubrimiento de agentes de IA locales. Las capacidades de postura de seguridad para los agentes que Defender descubre requieren otra licencia, como se describe en la siguiente tabla.
| Capacidad | Licencia necesaria |
|---|---|
| Descubre agentes de IA locales y míralos en el inventario de agentes de IA, incluyendo los datos del agente, el dispositivo y la cuenta, y los servidores MCP configurados | Microsoft Defender para punto de conexión Plan 2 |
Consultar agentes de IA locales en búsqueda avanzada, incluida la tabla AgentsInfo |
Microsoft Defender para punto de conexión Plan 2 |
| Consulta el nivel de riesgo, los indicadores de riesgo y las recomendaciones de seguridad para los agentes de IA locales descubiertos | Microsoft 365 E7, o Microsoft Agent 365 junto con Microsoft Defender para punto de conexión Plan 2 |
Microsoft 365 E5 y Microsoft 365 E7 incluyen ambos Microsoft Defender para punto de conexión Plan 2. Si tu organización tiene Microsoft Defender para punto de conexión Plan 2 sin Microsoft 365 E7 o Microsoft Agent 365, puedes descubrir agentes de IA locales, ver el inventario y consultar agentes en búsqueda avanzada, pero el nivel de riesgo, los indicadores de riesgo ni las recomendaciones de seguridad no están disponibles.
Visualización de agentes de inteligencia artificial locales en el inventario
Inicie sesión en el portal de Microsoft Defender.
En el panel de navegación de la izquierda, seleccione Recursos>agentes de IA.
Selecciona la pestaña de agentes locales para ver los agentes de IA locales descubiertos en tus dispositivos.
Las tarjetas de información de Agentes resumen el número total de agentes monitorizados, el número de agentes con alto riesgo y el número de agentes críticos.
La lista muestra una entrada por cada instalación de agente, por lo que un agente que se ejecuta en varios dispositivos, o bajo varias cuentas en el mismo dispositivo, aparece más de una vez. Usa los filtros para reducir la lista, selecciona Personalizar columnas para cambiar qué columnas aparecen o selecciona Exportar para descargar la lista.
| Columna | Description |
|---|---|
| Nombre del agente, versión | El agente descubierto y la versión instalada. |
| Nombre del dispositivo, ID del dispositivo, plataforma del sistema operativo, tipo de dispositivo | El dispositivo donde se descubrió al agente. |
| Nombre de cuenta, dominio de cuenta | La cuenta bajo la que opera el agente. |
| Nivel de riesgo | El nivel de riesgo global del agente. |
| Indicadores de riesgo | Por qué el agente se considera arriesgado, como ejecutarse en un dispositivo crítico o ser usado por un usuario crítico. |
| Recomendaciones | Las recomendaciones de seguridad que se aplican al agente. |
| Servidores MCP, MCPs locales | El número de servidores MCP remotos y de servidores MCP locales configurados para el agente. |
| Primero visto | Cuando el agente fue descubierto por primera vez. |
Nota:
Los niveles de riesgo, indicadores de riesgo y recomendaciones de seguridad requieren Microsoft 365 E7 o Microsoft Agent 365. Sin una de estas licencias, aún puedes ver el inventario y los detalles de cada agente. Para obtener más información, consulte Licencias.
Consulta los detalles de un agente local de IA
Desde la lista de agentes locales , selecciona un agente para abrir su panel de detalles:
- Detalles muestra el nombre del agente, el proveedor, el modelo, el proceso relacionado, si el proceso anfitrión es de confianza, si el agente aprueba automáticamente sus propias acciones y el ID del agente de origen.
- El riesgo muestra el nivel de riesgo, los indicadores de riesgo y las recomendaciones de seguridad que se aplican al agente.
- Los detalles del dispositivo muestran el dispositivo donde se descubrió el agente, incluyendo la plataforma y versión del sistema operativo, el tipo y funciones del dispositivo, y el ID del dispositivo Microsoft Entra.
- Los datos de usuario muestran el ID, nombre y dominio de la cuenta bajo la que opera el agente.
- Los servidores MCP listan los servidores MCP configurados para el agente, con el nombre, tipo y punto final de cada servidor.
- Los servidores MCP locales listan las entradas MCP locales descubiertas en el dispositivo.
Para investigar más a fondo, selecciona Ir a buscar para consultar al agente en caza avanzada, Ver en el mapa para ver al agente en el mapa de la superficie de ataque, o Abrir la página de Agente para abrir la página completa del agente.
Revisa la superficie de ataque y las recomendaciones de un agente
La página del agente tiene una pestaña de Resumen y una pestaña de recomendaciones de seguridad . El mapa de la superficie de ataque en la pestaña Resumen muestra los otros agentes, dispositivos, identidades y recursos asociados al agente.
Para obtener más información sobre el uso del inventario de agentes de inteligencia artificial, consulte Detección de agentes de inteligencia artificial y evaluación de la posición de seguridad mediante Microsoft Defender.
Consultar agentes locales de IA con búsqueda avanzada
Utiliza la caza avanzada para investigar proactivamente la presencia local de agentes de IA, entender cómo están configurados los agentes e identificar a los agentes y usuarios que conllevan el mayor riesgo. Estas consultas te ayudan a inventariar agentes, revisar los servidores MCP a los que se conectan y rastrear el acceso a activos críticos o sensibles.
Entiende las tablas
Tres tablas avanzadas de búsqueda describen los agentes de IA locales. Cada uno responde a una pregunta diferente, y son más útiles juntos.
| Tabla | Qué contiene | Úsalo para responder |
|---|---|---|
| AgentsInfo | Un registro de perfil para cada agente de IA que Microsoft Defender descubra, en todas las plataformas de agentes. Para los agentes de IA locales, el registro incluye el proveedor, la versión, el proceso host, la configuración de confianza y de aprobación automática, los servidores MCP configurados y el dispositivo y la cuenta donde se detectó el agente. | ¿Qué es este agente y cómo está configurado? |
| ExposureGraphNodes | Cada entidad en tu organización como nodo, incluyendo agentes de IA, dispositivos, identidades y recursos en la nube, junto con propiedades como la criticidad de activos y si la entidad posee datos sensibles. | ¿Qué es esta entidad y cuánto importa? |
| ExposureGraphEdges | Las relaciones entre nodos, como el dispositivo en el que se ejecuta un agente, o los recursos a los que puede acceder una identidad. | ¿A qué puede llegar este agente? |
En resumen, AgentsInfo describe qué es un agente, y el gráfico de exposición describe hasta dónde puede llegar un agente.
Ambas fuentes de datos contienen agentes de todas las plataformas, incluidos los agentes en la nube, por lo que cada una necesita su propio filtro.
En AgentsInfo, filtra por la columna Platform:
AgentsInfo
| where Platform == "LocalAgents"
En ExposureGraphNodes, los agentes de IA utilizan la ai-agent etiqueta del nodo. Filtrar por la plataforma indicada en las propiedades del nodo:
ExposureGraphNodes
| where NodeLabel == "ai-agent"
| where tostring(NodeProperties.rawData.aiAgentMetadata.platform) == "LocalAgents"
Importante
La ExposureGraphEdges tabla no incluye una propiedad que identifique a los agentes de IA locales. Filtrar solo por SourceNodeLabel == "ai-agent" devuelve bordes para todos los agentes de IA de tu inquilino, incluidos los agentes en la nube. Obtén siempre primero el conjunto de agentes locales a partir de ExposureGraphNodes y, a continuación, haz una unión con ExposureGraphEdges mediante el ID del nodo, como se muestra en las siguientes consultas.
Combina las tablas
Un agente tiene dos identificadores, y las consultas que combinan las tablas necesitan ambos:
-
AgentIdidentifica el perfil del agente enAgentsInfo. El grafo de exposición almacena el mismo valor en el nodo agente, queNodeProperties.rawData.aiAgentMetadata.id. -
NodeIdidentifica el nodo del agente en el gráfico de exposición. Este es el valor queExposureGraphEdgesse refiere a, enSourceNodeIdyTargetNodeId.
| Partir de | En | Partido en marcha |
|---|---|---|
AgentsInfo |
ExposureGraphNodes |
tostring(AgentId) y tostring(NodeProperties.rawData.aiAgentMetadata.id) |
ExposureGraphNodes |
ExposureGraphEdges |
NodeId y SourceNodeId o TargetNodeId |
Nota:
AgentId es una guid columna en AgentsInfo, pero el gráfico de exposición almacena el mismo valor que una cadena. Conviértelo con tostring() en ambos lados de la unión. Una unión entre columnas de diferentes tipos no coincide con ninguna fila.
Los nodos agentes de IA locales se conectan al resto del grafo de exposición a través de los siguientes bordes:
| Etiqueta de borde | Etiqueta de nodo de destino | Description |
|---|---|---|
runs on |
device, ec2.instance, microsoft.compute/virtualmachines |
El dispositivo donde se descubrió al agente. |
uses |
mcp/server |
Un servidor MCP configurado para el agente. |
used by |
user |
La identidad que usa el agente. |
Los agentes de IA en la nube también utilizan un can authenticate as borde que apunta a una entidad de servicio o a una aplicación OAuth de Microsoft Entra. Los agentes de IA locales no usan ese edge, así que usa used by para resolver la identidad de un agente de IA local.
La criticidad de activos se almacena en ExposureGraphNodes, en NodeProperties.rawData.criticalityLevel.criticalityLevel, donde 0 es el nivel más alto (muy alto) y 3 es el más bajo (bajo). La ruleNames propiedad enumera las reglas de clasificación que hicieron que el activo fuera fundamental.
Trabajar con perfiles locales de agentes de IA
AgentsInfo Añade un registro cada vez que se actualiza el perfil de un agente, por lo que un solo agente suele tener varios registros. Para devolver solo el registro más reciente de cada agente, haz un resumen con arg_max en Timestamp:
AgentsInfo
| where Platform == "LocalAgents"
| summarize arg_max(Timestamp, Name, Version, LifecycleStatus, RawAgentInfo) by AgentId
LifecycleStatus Informa si el agente sigue presente en el dispositivo. Un agente que se ha reinstalado también puede volver a emitirse con un nuevo AgentId, lo que deja marcado el registro anterior como Deleted, así que filtra los registros Deleted y Uninstalled si quieres un inventario actualizado.
Muchas AgentsInfo columnas describen agentes en la nube y están vacías para agentes de IA locales. Las columnas que contienen datos del agente de IA local son AgentId, Name, Version, PublishedStatus, LifecycleStatus, LastUpdatedDateTime, McpServers, DeclaredTools y RawAgentInfo.
La postura local del agente de IA está anidada en la RawAgentInfo columna, bajo localAgentMetadata:
| Propiedad | Description |
|---|---|
vendor |
El publicador del agente, como Anthropic, Google u OpenAI. |
relatedProcess |
El proceso que aloja al agente, como code.exe. |
trustedProcess |
Si el proceso anfitrión es de confianza. Reportado como la cadena "true" o "false". |
autoApprove |
Si el agente actúa sin pedir la aprobación al usuario. Reportado como la cadena "true" o "false". |
deviceName, aadDeviceId |
El dispositivo donde se descubrió al agente. |
accountName, accountDomain, accountSid |
La cuenta bajo la que gestionaba el agente. |
localMcps |
Servidores MCP que se ejecutan localmente en el dispositivo, incluyendo el comando que inicia cada uno. |
Nota:
trustedProcess y autoApprove se reportan como cadenas, no como valores booleanos. Compáralos con "true" o "false" en lugar de usar tobool().
Cada una de las siguientes consultas es autónoma. Las consultas que utilizan el gráfico de exposición comienzan con un conjunto de let sentencias que resuelven agentes de IA locales y los dispositivos en los que se ejecutan.
Haz un inventario de agentes locales de IA
Esta consulta enumera los agentes de IA locales descubiertos en tu organización, junto con el editor, el proceso anfitrión, las versiones en uso y la extensión de cada agente:
AgentsInfo
| where Platform == "LocalAgents"
| summarize arg_max(Timestamp, Name, Version, LifecycleStatus, RawAgentInfo)
by AgentId
| where LifecycleStatus !in~ ("Deleted", "Uninstalled")
| extend AgentMetadata = RawAgentInfo.localAgentMetadata
| extend Vendor = tostring(AgentMetadata.vendor),
Process = tostring(AgentMetadata.relatedProcess),
Device = tostring(AgentMetadata.deviceName),
Account = tostring(AgentMetadata.accountName)
| summarize Installations = count(),
DeviceCount = dcount(Device),
Devices = make_set(Device, 100),
Versions = make_set(Version, 20),
Accounts = make_set_if(Account, isnotempty(Account), 50)
by Agent = Name, Vendor, Process
| sort by DeviceCount desc, Installations desc
Cada uno AgentId representa un perfil de agente, que es un solo agente en un solo dispositivo para una sola cuenta.
Installations cuenta esos perfiles, así que un agente utilizado por dos personas en el mismo dispositivo cuenta dos veces, mientras que DeviceCount solo cuenta el dispositivo una vez.
Revisa los servidores MCP y las herramientas que utilizan los agentes de IA locales
Esta consulta enumera los servidores y herramientas MCP configurados para agentes de IA locales, los agentes y dispositivos que los utilizan, y dónde se ejecuta cada uno:
let localAgentProfiles =
AgentsInfo
| where Platform == "LocalAgents"
| extend AgentMetadata = RawAgentInfo.localAgentMetadata
| project Timestamp,
Agent = Name,
Device = tostring(AgentMetadata.deviceName),
Account = tostring(AgentMetadata.accountName),
McpServers,
DeclaredTools,
LocalServers = AgentMetadata.localMcps;
let remoteMcpServers =
localAgentProfiles
| mv-expand Server = McpServers
| project Timestamp, Agent, Device, Account,
McpServer = tostring(Server.name),
Origin = "Remote MCP server",
Transport = tostring(Server.type),
Location = tostring(Server.endpoint);
let agentDeclaredTools =
localAgentProfiles
| mv-expand Tool = DeclaredTools
| project Timestamp, Agent, Device, Account,
McpServer = tostring(Tool.name),
Origin = "Declared tool",
Transport = tostring(Tool.type),
Location = tostring(Tool.endpoint);
let localMcpServers =
localAgentProfiles
| mv-expand Server = LocalServers
| project Timestamp, Agent, Device, Account,
McpServer = tostring(Server.name),
Origin = "Local MCP server",
Transport = tostring(Server.transportType),
Location = tostring(Server.commandName);
remoteMcpServers
| union agentDeclaredTools, localMcpServers
| where isnotempty(McpServer)
| summarize LastSeen = max(Timestamp),
Agents = make_set(Agent, 20),
Devices = make_set(Device, 20),
Accounts = make_set_if(Account, isnotempty(Account), 20)
by McpServer, Origin, Transport, Location
| sort by McpServer asc, Origin asc
La Origin columna distingue las tres formas en que se informa de un servidor o herramienta:
- Un servidor MCP remoto se accede a través de la red y
Locationcontiene su punto final. - Un servidor MCP local se ejecuta como un proceso en el dispositivo y
Locationmantiene el comando que lo inicia. Los servidores MCP locales solo se reportan enAgentsInfo. - Una herramienta declarada es una herramienta que el agente anuncia. Las herramientas declaradas suelen estar respaldadas por un servidor MCP, pero no siempre reportan un endpoint.
A diferencia de las otras consultas, esta lee todos los registros de perfil de cada agente, de modo que los servidores MCP reportados en cualquier momento están incluidos. La LastSeen columna muestra cuándo se reportó por última vez cada servidor.
Encuentra agentes de IA locales con configuraciones arriesgadas
Esta consulta devuelve agentes de IA locales que actúan sin pedir aprobación al usuario, o que se ejecutan en un proceso host que no es de confianza:
AgentsInfo
| where Platform == "LocalAgents"
| summarize arg_max(Timestamp, Name, Version, LifecycleStatus, RawAgentInfo)
by AgentId
| where LifecycleStatus !in~ ("Deleted", "Uninstalled")
| extend AgentMetadata = RawAgentInfo.localAgentMetadata
| extend AutoApprove = tostring(AgentMetadata.autoApprove),
TrustedProcess = tostring(AgentMetadata.trustedProcess),
Vendor = tostring(AgentMetadata.vendor),
Process = tostring(AgentMetadata.relatedProcess),
Device = tostring(AgentMetadata.deviceName),
Account = tostring(AgentMetadata.accountName)
| where AutoApprove =~ "true" or TrustedProcess =~ "false"
| extend RiskReason = case(
AutoApprove =~ "true" and TrustedProcess =~ "false",
"Acts without approval, and the host process isn't trusted",
AutoApprove =~ "true",
"Acts without approval",
"The host process isn't trusted")
| project Agent = Name, Vendor, Version, Process, Device, Account,
AutoApprove, TrustedProcess, RiskReason, LastSeen = Timestamp
| sort by Device asc, Agent asc
Un agente que aprueba automáticamente sus propias acciones ejecuta herramientas y llega a recursos sin que una persona confirme cada paso, por lo que la cuenta y el dispositivo en el que se ejecuta el agente definen lo que puede hacer sin supervisión.
Encuentra agentes de IA locales arriesgados en dispositivos críticos
Esta consulta combina la configuración de agentes desde AgentsInfo con la criticidad de activos del gráfico de exposición, por lo que puedes empezar con los agentes que actúan sin supervisión y se ejecutan en dispositivos críticos para el negocio:
let deviceLabels = dynamic(["device", "ec2.instance",
"microsoft.compute/virtualmachines"]);
let riskyAgentProfiles =
AgentsInfo
| where Platform == "LocalAgents"
| summarize arg_max(Timestamp, Name, Version, LifecycleStatus, RawAgentInfo)
by AgentId
| where LifecycleStatus !in~ ("Deleted", "Uninstalled")
| extend AgentMetadata = RawAgentInfo.localAgentMetadata
| extend AutoApprove = tostring(AgentMetadata.autoApprove),
TrustedProcess = tostring(AgentMetadata.trustedProcess)
| where AutoApprove =~ "true" or TrustedProcess =~ "false"
| project AgentId = tostring(AgentId),
Agent = Name,
Version,
Vendor = tostring(AgentMetadata.vendor),
Account = tostring(AgentMetadata.accountName),
AutoApprove,
TrustedProcess;
let localAgentNodes =
ExposureGraphNodes
| where NodeLabel == "ai-agent"
| where tostring(NodeProperties.rawData.aiAgentMetadata.platform) == "LocalAgents"
| project AgentNodeId = NodeId,
AgentId = tostring(NodeProperties.rawData.aiAgentMetadata.id);
let agentDeviceEdges =
ExposureGraphEdges
| where SourceNodeLabel == "ai-agent"
| where EdgeLabel =~ "runs on"
| where TargetNodeLabel in (deviceLabels)
| project AgentNodeId = SourceNodeId, DeviceId = TargetNodeId,
Device = TargetNodeName, DeviceType = TargetNodeLabel;
let criticalDevices =
ExposureGraphNodes
| where NodeLabel in (deviceLabels)
| where NodeProperties has "criticalityLevel"
| extend CriticalityLevel =
toint(NodeProperties.rawData.criticalityLevel.criticalityLevel)
| where CriticalityLevel between (0 .. 3)
| extend Criticality = case(
CriticalityLevel == 0, "Very high",
CriticalityLevel == 1, "High",
CriticalityLevel == 2, "Medium",
"Low")
| project DeviceId = NodeId, CriticalityLevel, Criticality,
CriticalityReason =
tostring(NodeProperties.rawData.criticalityLevel.ruleNames);
riskyAgentProfiles
| join kind=inner localAgentNodes on AgentId
| join kind=inner agentDeviceEdges on AgentNodeId
| join kind=inner criticalDevices on DeviceId
| project Device, DeviceType, Criticality, CriticalityReason,
Agent, Vendor, Version, Account, AutoApprove, TrustedProcess,
CriticalityLevel
| sort by CriticalityLevel asc, Device asc, Agent asc
| project-away CriticalityLevel
Para revisar cada agente de IA local en un dispositivo crítico en lugar de solo los más arriesgados, elimina la where AutoApprove =~ "true" or TrustedProcess =~ "false" línea.
Clasifica los usuarios cuyos agentes de IA locales acceden a activos críticos o sensibles
Esta consulta clasifica las identidades que usan agentes de IA locales según la cantidad de recursos críticos o sensibles a los que pueden acceder, para que puedas priorizar las identidades con el mayor alcance potencial. La UserCriticality columna muestra si la identidad se clasifica como un activo crítico, como un Administrador Global:
let deviceLabels = dynamic(["device", "ec2.instance",
"microsoft.compute/virtualmachines"]);
let localAgents =
ExposureGraphNodes
| where NodeLabel == "ai-agent"
| where tostring(NodeProperties.rawData.aiAgentMetadata.platform) == "LocalAgents"
| project AgentNodeId = NodeId, AIAgent = NodeName;
let agentDeviceEdges =
ExposureGraphEdges
| where SourceNodeLabel == "ai-agent"
| where EdgeLabel =~ "runs on"
| where TargetNodeLabel in (deviceLabels)
| project AgentNodeId = SourceNodeId, DeviceId = TargetNodeId,
Device = TargetNodeName;
let agentUserEdges =
ExposureGraphEdges
| where SourceNodeLabel == "ai-agent"
| where EdgeLabel =~ "used by"
| project AgentNodeId = SourceNodeId, UserId = TargetNodeId,
User = TargetNodeName;
let userReach =
ExposureGraphEdges
| where EdgeLabel in~ ("has permissions to", "has role on")
| project UserId = SourceNodeId, AssetId = TargetNodeId
| union (
ExposureGraphNodes
| where NodeLabel == "user"
| project UserId = NodeId, AssetId = NodeId
);
let sensitiveAssets =
ExposureGraphNodes
| where NodeProperties has "criticalityLevel"
or NodeProperties has "containsSensitiveData"
| extend
CriticalityLevel =
toint(NodeProperties.rawData.criticalityLevel.criticalityLevel),
SensitiveDataRaw = tostring(NodeProperties.rawData.containsSensitiveData)
| extend HasSensitiveData =
iff(isnotempty(SensitiveDataRaw) and SensitiveDataRaw !~ "false", "Yes", "No")
| where CriticalityLevel between (0 .. 3) or HasSensitiveData == "Yes"
| extend CriticalityRank =
iff(CriticalityLevel between (0 .. 3), CriticalityLevel, 4)
| project AssetId = NodeId, AssetName = NodeName,
CriticalityRank, HasSensitiveData;
let agentUsers =
localAgents
| join kind=inner agentDeviceEdges on AgentNodeId
| join kind=inner agentUserEdges on AgentNodeId
| project AIAgent, Device, UserId, User;
agentUsers
| join kind=inner userReach on UserId
| join kind=inner sensitiveAssets on AssetId
| summarize AIAgents = make_set(AIAgent, 20),
Devices = make_set(Device, 20),
ReachableAssets = dcountif(AssetId, AssetId != UserId),
SensitiveAssets = dcountif(AssetId,
AssetId != UserId and HasSensitiveData == "Yes"),
Assets = make_set_if(AssetName, AssetId != UserId, 50),
UserRank = minif(CriticalityRank, AssetId == UserId),
AssetRank = minif(CriticalityRank, AssetId != UserId)
by User
| extend UserCriticality = case(
UserRank == 0, "Very high",
UserRank == 1, "High",
UserRank == 2, "Medium",
UserRank == 3, "Low",
"Not classified"),
HighestAssetCriticality = case(
AssetRank == 0, "Very high",
AssetRank == 1, "High",
AssetRank == 2, "Medium",
AssetRank == 3, "Low",
AssetRank == 4, "Sensitive data",
"None")
| extend SortRank = coalesce(AssetRank, 99)
| project User, UserCriticality, ReachableAssets, SensitiveAssets,
HighestAssetCriticality, AIAgents, Devices, Assets, SortRank
| sort by SortRank asc, ReachableAssets desc
| project-away SortRank