Desarrollo de soluciones de plataforma de grafos personalizadas

Note

Esta funcionalidad actualmente está en su versión preliminar. Consulte Términos de uso suplementarios para las versiones preliminares de Microsoft Azure.

Una solución de grafo personalizada de Microsoft Sentinel es una solución basada en cuadernos de notas que define nodos y aristas a partir de tablas del lago de datos de Microsoft Sentinel, construye un grafo y permite a los usuarios consultar ese grafo con el lenguaje de consulta de grafos (GQL).

Use esta guía para compilar, probar, materializar, empaquetar y publicar una solución de grafo personalizada como una oferta de SaaS en Microsoft Partner Center para que los clientes puedan detectarla en Seguridad de Microsoft Store.

Prerequisites

Debe estar incorporado al lago de datos para crear soluciones personalizadas de Graph. Para obtener más información, consulte Incorporación al lago de datos de Microsoft Sentinel.

Permissions

En la tabla siguiente se enumeran los permisos necesarios para cada operación o ámbito de esta guía.

Operation Rol obligatorio
Incorporación al lago de datos de Sentinel Microsoft Entra ID: administrador de seguridad o administrador global
Incorporación del área de trabajo de Sentinel al portal de Defender Propietario de la suscripción, o Administrador de acceso de usuario en el ámbito de la suscripción y Colaborador de Microsoft Sentinel en el ámbito de la suscripción o del grupo de recursos
Incorpora el espacio de trabajo de Sentinel al lago de datos Propietario de la suscripción o colaborador de Microsoft Sentinel en el ámbito de la suscripción o del grupo de recursos
Diseñar y crear un grafo de cuaderno Rol RBAC unificado personalizado de Microsoft Defender XDR con el permiso data (manage) sobre la colección de datos de Microsoft Sentinel
Persistencia (materialización) de un gráfico Operador de seguridad, administrador de seguridad o administrador global
Consulta de un gráfico persistente Rol RBAC unificado personalizado de Microsoft Defender XDR con security data basics (read) sobre la colección de datos de Microsoft Sentinel
Publicar una solución personalizada de Graph Cuenta de Publisher de Marketplace en Microsoft Partner Center

Herramientas

Las siguientes herramientas son necesarias para compilar y publicar una solución de grafo personalizada:

Tip

Reutilice un lago de datos existente si su inquilino ya está habilitado para consultas KQL, notebooks o un agente de Security Copilot. Hay un lago de datos por inquilino. En el portal de Defender, vaya aConfiguración> del sistema>Microsoft Sentinel>Lago de datos. Si el estado está aprovisionado, omita la tarea 1.

Crear flujo de trabajo

En el flujo de trabajo siguiente se describen los pasos para compilar y publicar una solución de grafo personalizada.

  1. Cargue datos de ejemplo en las tablas que modela su grafo.
  2. Valide la conectividad con un cuaderno simple.
  3. Cree el gráfico personalizado.
  4. Pruebe el cuaderno de grafos.
  5. Programe una tarea de grafo para materializar el grafo.
  6. Consulte y visualice el gráfico desde el Explorador de Graph.
  7. Empaquetar y publicar la solución de gráfico personalizada.

Ingesta de datos de ejemplo

Esta tarea ingesta las tablas de recursos de Microsoft Entra ID utilizadas por el grafo de ejemplo de esta guía: EntraUsers, EntraGroups, EntraServicePrincipals y EntraMembers.

  1. En el portal de Defender, vaya aConfiguración> del sistema>Microsoft Sentinel>Conectores de datos.
  2. Habilite el conector de Microsoft Entra ID para que las tablas de recursos de Entra se incorporen al lago de datos. Para más información, consulte Datos de activos en el lago de datos de Microsoft Sentinel.
  3. Confirme que estas tablas aparecen en el explorador de Data Lake:
    • EntraUsers
    • EntraGroups
    • EntraServicePrincipals
    • EntraMembers
  4. Estas tablas aparecen en el área de trabajo Tablas del sistema.
  5. Opcional: ingiere otros conectores y reemplaza los nombres de tabla en pasos posteriores si el escenario usa datos diferentes.

Note

Si una tabla no aparece en el explorador de Data Lake, no puede usarla para la creación de grafos y la asistencia de IA no hará referencia a ella.

Validación de la conectividad con un cuaderno sencillo

Cree y ejecute un cuaderno mínimo para comprobar la conectividad del lago de datos antes de la creación de grafos.

  1. Abra Visual Studio Code e inicie sesión en la extensión Microsoft Sentinel con la misma cuenta que tiene acceso al lago de datos.

  2. En Visual Studio Code, en Extensión de Sentinel– Graphs, seleccione Crear nuevo cuaderno. Captura de pantalla que muestra la opción crear nuevo cuaderno en VS Code.

  3. Guarde el cuaderno, por ejemplo hello-world-show-tables.ipynb.

  4. Seleccione Seleccionar kernel, seleccione Microsoft Sentinel y seleccione un grupo de Spark disponible. Captura de pantalla que muestra la opción seleccionar kernel en VS Code.

  5. Agregue las celdas siguientes en orden.

Celda 1 - Markdown:

# Hello World: Show Tables
A minimal connectivity test for the Microsoft Sentinel data lake.
If every cell below runs without error, your environment is ready
to author custom graphs.
Steps:
1. Connect to the data lake with the Microsoft Sentinel provider
2. Point at your workspace
3. Read a table and show a few rows

Celda 2: código (conéctese y establezca el área de trabajo):

from sentinel_lake.providers import MicrosoftSentinelProvider
# The provider gives the notebook access to data lake tables.
lake_provider = MicrosoftSentinelProvider(spark=spark)
# >>> ADD YOUR WORKSPACE HERE <<<
# Replace with the Log Analytics workspace that holds your tables.
# Entra asset tables (EntraUsers, EntraGroups, ...) live in "System tables".
LOG_ANALYTICS_WORKSPACE = "System tables"
print(f"Using workspace: {LOG_ANALYTICS_WORKSPACE}")

Celda 3 - Markdown:

## Read a table and show rows
Reading a known table is the fastest way to confirm the extension
can reach the lake with your permissions. Swap EntraGroups for any
table that exists in your workspace.

Celda 4 - Código (leer una tabla y mostrar filas):

# Read a table from the data lake into a Spark DataFrame.
df_groups = lake_provider.read_table("EntraGroups", LOG_ANALYTICS_WORKSPACE)
# Show a sample. .df exposes the underlying Spark DataFrame.
df_groups.df.select("id", "displayName", "mailEnabled").show(20, truncate=False)

Celda 5 - Código (recuentos opcionales de integridad):

# Confirm the read returned data and inspect the schema.
print("Row count:", df_groups.df.count())
df_groups.df.printSchema()
  1. Ejecute todas las celdas de arriba abajo.
  2. Confirme que todas las celdas se completan sin una devolución de seguimiento roja, aparecen los datos de vista previa de la tabla y el recuento de filas no es cero.

Note

Si las lecturas fallan o no devuelven ninguna fila, confirme que el conector de la sección Ingerir datos de ejemplo ha completado su primera captura instantánea, LOG_ANALYTICS_WORKSPACE coincide con un área de trabajo real y su cuenta tiene acceso de lectura. Compruebe el contenido de la tabla con KQL en el portal de Defender para confirmar que los datos están presentes. Para obtener más información, consulte Ejecución de consultas KQL en el lago de datos de Microsoft Sentinel.

Creación del grafo personalizado

Cree de una de estas formas:

  • Creación de grafos asistidos por IA.
  • Crear manualmente.

Creación de grafos asistidos por IA

Para crear un grafo con asistencia de IA, siga estos pasos:

  1. En Visual Studio Code, abre el chat de GitHub Copilot.

  2. Empiece su prompt con el asistente @sentinel /graph-authoring para crear grafos y describa su grafo en lenguaje natural:

    @sentinel /graph-authoring Create a graph that maps Entra groups to
    their member users, groups, and service principals using EntraGroups,
    EntraUsers, EntraServicePrincipals, and EntraMembers from the
    "System tables" workspace.
    

    Captura de pantalla que muestra la creación de grafos asistidos por IA en VS Code.

    Copilot genera las celdas siguientes para el ciclo de vida de creación de grafos:

    Fase del ciclo de vida Salida generada
    Configuración del entorno Comprueba los paquetes necesarios y la información de conexión
    Carga de datos Lee tablas nombradas del lago de datos de Sentinel
    Transformación de datos Prepara datos de nodos y aristas
    Esquema de grafo Define nodos y bordes
    Validación del esquema Valida la definición del grafo.
    Compilación de grafos Materializa el grafo de la sesión.
    Consulta de grafos Ejecuta una consulta GQL de ejemplo y visualiza el resultado
  3. Continúe refinando el cuaderno con avisos como estos:

    Objetivo Prompt
    Agregar una relación @sentinel Add an edge from User to IPAddress
    Filtrar los datos @sentinel Filter the data to show only failed sign-ins
    Cambiar intervalo de tiempo @sentinel Change the time range to the last 7 days
    Corrección del error de compilación @sentinel Fix the error in the graph build step
    Descripción del código @sentinel Explain how edge keys are defined
    Búsqueda de una API sin edición What parameters does build_graph_with_data() accept? #Sentinel

Tip

Use @sentinel /graph-authoring para crear o modificar celdas del cuaderno. Si necesita explicaciones sobre la API o consultas de ejemplo, pregunte a Copilot e incluya #Sentinel para obtener respuestas específicas de Sentinel.

Crear manualmente

Para crear un grafo manualmente, siga estos pasos:

  1. Conexión y lectura de tablas de recursos.

    from pyspark.sql import functions as F
    from sentinel_lake.providers import MicrosoftSentinelProvider
    lake_provider = MicrosoftSentinelProvider(spark=spark)
    # Entra asset tables live in the "System tables" workspace.
    # If your data is elsewhere, update this and ensure the tables exist.
    LOG_ANALYTICS_WORKSPACE = "System tables"
    # Use the latest snapshot of EntraUsers as the point-in-time for all tables.
    snapshot_time = (
        lake_provider.read_table("EntraUsers", LOG_ANALYTICS_WORKSPACE)
        .df.agg(F.max("_SnapshotTime").alias("max_snapshot"))
        .collect()[0]["max_snapshot"]
        .strftime("%Y-%m-%dT%H:%M:%SZ")
    )
    print(f"Using snapshot_time: {snapshot_time}")
    snapshot_filter = (F.col("_SnapshotTime") == F.lit(snapshot_time).cast("timestamp"))
    # Edges: group contains user / group / servicePrincipal
    df_members = (
        lake_provider.read_table("EntraMembers", LOG_ANALYTICS_WORKSPACE)
        .filter(
            snapshot_filter
            & (F.col("sourceType") == "group")
            & (F.col("targetType").isin("user", "group", "servicePrincipal"))
        )
    )
    # Nodes
    df_groups = (
        lake_provider.read_table("EntraGroups", LOG_ANALYTICS_WORKSPACE)
        .filter(snapshot_filter)
        .select("id", "displayName", "mailEnabled")
    )
    df_users = (
        lake_provider.read_table("EntraUsers", LOG_ANALYTICS_WORKSPACE)
        .filter(snapshot_filter)
        .select("id", "accountEnabled", "displayName", "department",
                "userPrincipalName", "usageLocation")
    )
    
  2. Prepare los DataFrames de nodos y aristas.

    # NODES
    user_nodes = df_users.df.select(
        "id", "displayName", "accountEnabled", "department",
        "userPrincipalName", "usageLocation")
    group_nodes = df_groups.df.select("id", "displayName", "mailEnabled")
    # EDGES
    edge_group_contains_user = (
        df_members.df.filter(F.col("targetType") == "user")
        .select(F.col("sourceId").alias("SourceGroupId"),
                F.col("targetId").alias("TargetUserId"))
        .distinct()
        .withColumn("EdgeKey", F.concat_ws("_", F.col("SourceGroupId"), F.col("TargetUserId")))
    )
    edge_group_contains_group = (
        df_members.df.filter(F.col("targetType") == "group")
        .select(F.col("sourceId").alias("SourceGroupId"),
                F.col("targetId").alias("TargetGroupId"))
        .distinct()
        .withColumn("EdgeKey", F.concat_ws("_", F.col("SourceGroupId"), F.col("TargetGroupId")))
    )
    
  3. Defina el esquema del grafo y vincule DataFrames.

    from sentinel_graph import GraphSpecBuilder, Graph
    entra_group_graph_spec = (
        GraphSpecBuilder.start()
        # === NODES ===
        .add_node("EntraUser").from_dataframe(user_nodes)
        .with_columns("id", "displayName", "accountEnabled", "department",
                      "userPrincipalName", "usageLocation",
                      key="id", display="displayName")
        .add_node("EntraGroup").from_dataframe(group_nodes)
        .with_columns("id", "displayName", "mailEnabled",
                      key="id", display="displayName")
        # === EDGES ===
        .add_edge("ContainsUser").from_dataframe(edge_group_contains_user)
        .source(id_column="SourceGroupId", node_type="EntraGroup")
        .target(id_column="TargetUserId", node_type="EntraUser")
        .with_columns("SourceGroupId", "TargetUserId", "EdgeKey",
                      key="EdgeKey", display="EdgeKey")
        .add_edge("ContainsGroup").from_dataframe(edge_group_contains_group)
        .source(id_column="SourceGroupId", node_type="EntraGroup")
        .target(id_column="TargetGroupId", node_type="EntraGroup")
        .with_columns("SourceGroupId", "TargetGroupId", "EdgeKey",
                      key="EdgeKey", display="EdgeKey")
    ).done()
    # Validate the schema before building.
    entra_group_graph_spec.show_schema()
    
  4. Compile el grafo.

    # Build = prepare data + publish for the session.
    entra_group_graph = Graph.build(entra_group_graph_spec)
    print(entra_group_graph.build_status.status)   # "published" or "prepared"
    

    Note

    Graph.build() prepara los datos y publica en una sola llamada. Para inspeccionar los nodos y bordes preparados antes de publicar, llame a Graph.prepare(spec), revise graph.nodes y graph.edges, a continuación, llame a graph.publish().

  5. Ejecute una consulta GQL.

    # Find nested group relationships up to 8 levels deep. 
    # Update the Entra Group name that you want to traverse from 
    
    query_nested_groups = """ 
    MATCH p=(g1:EntraGroup)-[cg]->{1,8}(g2) 
    WHERE g1.displayName = 'tmplevel3' 
    RETURN * 
    """ 
    entra_group_graph.query(query_nested_groups).show()
    

Prueba del cuaderno de grafos

Pruebe el cuaderno para asegurarse de que genera la salida esperada del grafo:

  1. Reinicie el kernel y ejecute todas las celdas de arriba abajo. Captura de pantalla que muestra el botón reiniciar kernel.

  2. Confirme que cada celda se completa correctamente.

  3. Si las celdas de transformación tardan más de 5 minutos en ejecutarse en un grupo pequeño, ajuste los filtros de instantáneas y la proyección de columnas antes de ampliar la capacidad.

  4. Confirme que show_schema() devuelve los nodos y bordes esperados.

  5. Ejecute una consulta GQL de ejemplo y compruebe la visualización y la salida tabular.

  6. Validar casos perimetrales:

    • Entrada vacía.
    • Desfase de esquema.
    • Falta acceso a la tabla.

Tip

Agregue celdas markdown encima de cada sección de código para documentar el propósito, las entradas, las salidas y los nodos o bordes generados.

Programar una tarea de grafo para materializar el grafo

Los gráficos creados en una sesión interactiva son efímeros. Programe un trabajo de grafo para conservar y actualizar el grafo. Para obtener más información, consulte Programar y administrar trabajos de gráfico de Microsoft Sentinel.

  1. En el cuaderno de grafos, seleccione Crear trabajo> programadoCrear un trabajo de grafo. Captura de pantalla que muestra el botón para crear un trabajo de grafo.

  2. Escriba el nombre y la descripción del grafo y compruebe la ruta de acceso del cuaderno.

  3. Seleccione una programación:

    • A petición: se compila una vez, con una retención predeterminada de 30 días.
    • Programado: seleccione cadencia de repetición y horas de inicio y finalización.
  4. Seleccione Enviar.

  5. Abra el gráfico en la extensión de Sentinel y supervise los detalles del trabajo.

  6. Use Ejecutar ahora para ejecutar fuera de la programación según sea necesario.

  7. Confirme la progresión de estado de Queued a In Progress a Ready.

Importante

Los trabajos enviados se desacoplan del bloc de notas local. Editar el/la .ipynb local no actualiza la tarea programada. Para actualizar un cuaderno del trabajo, descárguelo desde el panel Gráficos, edítelo y, a continuación, use Editar trabajo>Enviar.

Consulta y visualización desde el Explorador de Graph

Después de que el estado del trabajo del grafo sea Ready, consulte y visualice en el portal de Defender, cuadernos y API REST.

  1. En el portal de Defender en Microsoft Sentinel, abra la experiencia del grafo y seleccione el grafo materializado.
  2. Ejecute consultas GQL, inspeccione el esquema, cambie las salidas visuales y tabulares y recorra el próximo salto.
  3. Use esta referencia rápida de GQL:
Patrón o cláusula Ejemplo
Nodo con etiqueta (g:EntraGroup)
Arista dirigida con tipo -[c:ContainsUser]->
Ruta de acceso de longitud variable (de 1 a 8 saltos) (a)-[e]->{1,8}(b)
Filter WHERE g.displayName = 'Finance Admins'
Proyectar, ordenar, limitar RETURN g.displayName ORDER BY g.displayName LIMIT 10
Expresiones de etiqueta (:EntraUser \| EntraServicePrincipal)

Note

Cada consulta de GQL comienza con MATCH. El motor funciona en UTC. Use ZONED_DATETIME(...) para literales de fecha y hora. No se admiten INSERT ni CREATE. Los gráficos son de solo lectura.

  1. Consulta desde un cuaderno.

    from sentinel_graph import Graph
    # Attach to an already-materialized graph by name.
    graph = Graph.get("entra_group_membership")
    graph.query("MATCH (g:EntraGroup)-[c:ContainsUser]->(u:EntraUser) RETURN g, c, u").show()
    # Purpose-built security algorithms are available too:
    graph.blast_radius(source_property_value="Finance Admins", min_hop_count=1).show()
    
  2. Realiza consultas mediante las API REST de Graph.

    GET https://api.securityplatform.microsoft.com/graphs/graph-instances?graphTypes=Custom
    Authorization: Bearer <access_token>
    
    POST https://api.securityplatform.microsoft.com/graphs/graph-instances/{graphName}/query
    Authorization: Bearer <access_token>
    Content-Type: application/json
    {
      "query": "MATCH (g:EntraGroup)-[c:ContainsUser]->(u) RETURN g, c, u LIMIT 100",
      "responseFormats": ["Table", "Graph"],
      "queryLanguage": "GQL"
    }
    

responseFormats controla la forma de salida. "Table" devuelve filas, "Graph" devuelve nodos y bordes, y ["Table", "Graph"] devuelve ambos.

Para más información, consulte Graph REST APIs for custom graphs (API rest de Graph para gráficos personalizados).

Empaqueta y publica tu solución de grafos

Una vez probado y materializado el grafo, empaquetelo para la implementación a los clientes. Para obtener instrucciones detalladas de empaquetado, consulte Empaquetar y publicar soluciones de grafos y cuadernos de Microsoft Sentinel.

Troubleshooting

Use las tablas siguientes para diagnosticar problemas comunes por síntoma.

Creación de grafos

Síntoma Causa y corrección probables
MicrosoftSentinelProvider o sentinel_graph no se encuentra Vuelva a iniciar sesión en la extensión y confirme que se ha seleccionado un kernel Microsoft Sentinel.
La celda se queda bloqueada en Iniciando sesión de Spark El primer inicio puede tardar entre 3 y 5 minutos. Si supera los 6 minutos, compruebe la capacidad del grupo y vuelva a intentarlo.
show_schema() está vacío o Graph.build() produce un error Confirme que existen columnas clave y visualización y que no son NULL, y los valores de origen y destino node_type coinciden con alias de nodo.
La consulta GQL no devuelve ninguna fila Confirme que existen valores de filtro en la instantánea seleccionada y compruebe el filtrado de instantáneas.
publish() falla por permiso denegado Confirme que tiene el rol Operador de seguridad, Administrador de seguridad o Administrador global.

Redacción asistida por IA

Síntoma Causa y corrección probables
@sentinel /graph-authoring no hace nada Confirme que las extensiones GitHub Copilot y Jupyter están instaladas y activas, y tiene un plan de Copilot Empresa o Enterprise.
El código generado hace referencia a una tabla que falta Confirme la configuración del conector y compruebe que la tabla aparece en el explorador de Data Lake.

Programación de trabajos

Síntoma Causa y corrección probables
Las ediciones de cuadernos locales no se reflejan en el trabajo Descargue el notebook del trabajo desde el panel Gráficos, edítelo y, a continuación, use Edit job>Submit.
El grafo materializado ha desaparecido Los gráficos a petición tienen retención de 30 días. Programar una tarea periódica o ejecutar una nueva compilación.