Desenvolva soluções personalizadas para plataformas de grafos

Note

Este recurso está atualmente em versão prévia. Consulte Termos de Uso Complementares para Visualizações do Microsoft Azure.

Uma solução de grafo personalizado do Microsoft Sentinel é uma solução baseada em notebook que define nós e arestas a partir das tabelas do data lake do Microsoft Sentinel, cria um grafo e permite aos usuários consultar esse grafo com a Linguagem de Consulta de Grafos (GQL).

Use este guia para compilar, testar, materializar, empacotar e publicar uma solução de grafo personalizado como uma oferta de SaaS no Microsoft Partner Center para que os clientes possam descobri-la no Segurança da Microsoft Store.

Pré-requisitos

Você deve ter acesso ao data lake para criar soluções de grafos personalizados. Para obter mais informações, consulte Como integrar-se ao data lake do Microsoft Sentinel.

Permissions

A tabela a seguir lista as permissões necessárias para cada operação ou escopo neste guia.

Operação Função necessária
Integração ao data lake do Sentinel Microsoft Entra ID – Administrador de Segurança ou Administrador Global
Integrar o espaço de trabalho do Sentinel ao portal Defender Proprietário da Assinatura ou Administrador de Acesso do Usuário no escopo da assinatura, e Colaborador do Microsoft Sentinel no escopo da assinatura ou do grupo de recursos
Integrar o espaço de trabalho do Sentinel ao data lake Proprietário da Assinatura ou Colaborador do Microsoft Sentinel no escopo da assinatura ou do grupo de recursos
Modelar e construir grafos em notebooks Função RBAC unificada do Microsoft Defender XDR personalizada com a permissão data (manage) sobre a coleta de dados do Microsoft Sentinel
Persistir (materializar) um grafo Operador de segurança, administrador de segurança ou administrador global
Consultar um gráfico persistente Função RBAC unificada do Microsoft Defender XDR personalizada com security data basics (read) sobre a coleta de dados do Microsoft Sentinel
Publicação de solução personalizada do Graph Conta de Publisher do Marketplace no Microsoft Partner Center

Tools

As seguintes ferramentas são necessárias para criar e publicar uma solução de grafo personalizada:

Tip

Reutilize um data lake existente se o locatário já estiver integrado para consultas KQL, notebooks ou um agente do Security Copilot. Existe um lago de dados para cada locatário. No portal do Defender, vá para Sistema>Configurações>Microsoft Sentinel>Data lake. Se o status for Provisionado, ignore a tarefa 1.

Criar fluxo de trabalho

O fluxo de trabalho a seguir descreve as etapas para criar e publicar uma solução de grafo personalizado.

  1. Ingerir dados de exemplo nas tabelas modeladas pelo grafo.
  2. Validar a conectividade com um notebook simples.
  3. Crie o grafo personalizado.
  4. Teste o notebook de grafo.
  5. Agende uma tarefa de grafo para materializar o grafo.
  6. Consulte e visualize o grafo no Explorador do Graph.
  7. Empacote e publique a solução de grafo personalizado.

Ingerir dados de exemplo

Essa tarefa ingere tabelas de ativos do Microsoft Entra ID usadas pelo grafo de exemplo neste guia: EntraUsers, EntraGroups, EntraServicePrincipals e EntraMembers.

  1. No portal do Defender, vá para Sistema>Configurações>Microsoft Sentinel>Conectores de dados.
  2. Habilite o conector do Microsoft Entra ID para que as tabelas de ativos do Entra sejam incluídas no data lake. Para mais informações, veja Dados de ativos no lago de dados Microsoft Sentinel.
  3. Confirme se essas tabelas aparecem no data lake explorer:
    • EntraUsers
    • EntraGroups
    • EntraServicePrincipals
    • EntraMembers
  4. Essas tabelas são exibidas no espaço de trabalho Tabelas do sistema.
  5. Opcional: ingerir outros conectores e substituir nomes de tabela em etapas posteriores se o cenário usar dados diferentes.

Note

Se uma tabela não aparecer no data lake explorer, você não poderá usá-la para criação de grafo e a assistência de IA não a fará referência.

Validar a conectividade com um notebook simples

Crie e execute um notebook mínimo para verificar a conectividade do data lake antes da criação do grafo.

  1. Abra Visual Studio Code e entre na extensão Microsoft Sentinel com a mesma conta que tenha acesso ao data lake.

  2. Em Visual Studio Code, em Extensão do Sentinel – Grafos, selecione Criar novo bloco de anotações. Uma captura de tela mostrando a opção criar novo bloco de anotações no VS Code.

  3. Salve o bloco de anotações, por exemplo hello-world-show-tables.ipynb.

  4. Selecione Selecionar kernel, selecione Microsoft Sentinel e selecione um pool do Spark disponível. Uma captura de tela mostrando a opção selecionar kernel no VS Code.

  5. Adicione as células a seguir em ordem.

Célula 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

Célula 2 – Código (conecte-se e defina seu workspace):

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}")

Célula 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.

Célula 4 - Código (ler uma tabela e mostrar linhas):

# 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)

Célula 5 – Código (contagens opcionais de sanidade):

# Confirm the read returned data and inspect the schema.
print("Row count:", df_groups.df.count())
df_groups.df.printSchema()
  1. Execute todas as células de cima para baixo.
  2. Confirme se cada célula é concluída sem um rastreamento vermelho, os dados de visualização da tabela são exibidos e a contagem de linhas não é zero.

Note

Se as leituras falharem ou não retornarem nenhuma linha, confirme se o conector da seção Ingerir dados de exemplo concluiu seu primeiro instantâneo, se LOG_ANALYTICS_WORKSPACE corresponde a um workspace real e se a conta tem acesso de leitura. Verifique o conteúdo da tabela com o KQL no portal Defender para confirmar se os dados estão presentes. Para obter mais informações, consulte Executar consultas KQL no data lake Microsoft Sentinel.

Criar o grafo personalizado

Crie de uma das seguintes maneiras:

  • Criação de grafo assistida por IA.
  • Criar à mão.

Criação de grafo assistida por IA

Para criar um grafo com assistência de IA, siga estas etapas:

  1. Em Visual Studio Code, abra o GitHub Copilot Chat.

  2. Inicie seu prompt com o auxiliar @sentinel /graph-authoring de criação de grafo e descreva o grafo em linguagem simples:

    @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.
    

    Uma captura de tela mostrando a criação de grafo assistido por IA no VS Code.

    Copilot gera as seguintes células para o ciclo de vida de criação de grafos:

    Estágio do ciclo de vida Saída gerada
    Configuração do ambiente Verifica os pacotes necessários e as informações de conexão
    Carregamento de dados Lê tabelas nomeadas do data lake do Sentinel
    Transformação de dados Prepara dados de nó e aresta
    Esquema de grafo Define nós e bordas
    Validação do esquema Valida a definição do grafo
    Compilação do grafo Materializa o grafo da sessão
    Consulta de grafos Executa uma consulta GQL de exemplo e visualiza o resultado
  3. Continue ajustando o notebook com prompts como estes:

    Objetivo Prompt
    Adicionar um relacionamento @sentinel Add an edge from User to IPAddress
    Filtrar dados @sentinel Filter the data to show only failed sign-ins
    Alterar intervalo de tempo @sentinel Change the time range to the last 7 days
    Corrigir erro de build @sentinel Fix the error in the graph build step
    Entender o código @sentinel Explain how edge keys are defined
    Pesquisar uma API sem edição What parameters does build_graph_with_data() accept? #Sentinel

Tip

Use @sentinel /graph-authoring para criar ou modificar células de notebook. Se você precisar de explicações sobre API ou exemplos de consultas, pergunte ao Copilot e inclua #Sentinel para respostas específicas do Sentinel.

Criar à mão

Para criar um grafo manualmente, siga estas etapas:

  1. Conectar e ler tabelas de ativos.

    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 os DataFrames de bordas e nós.

    # 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 o esquema de grafo e associe 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. Crie o 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 dados e publica em uma chamada. Para inspecionar nós e bordas preparados antes da publicação, chame Graph.prepare(spec), examine graph.nodes e graph.edges, em seguida, chame graph.publish().

  5. Execute uma 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()
    

Teste o notebook de gráficos

Teste o notebook para garantir que ele produza a saída de grafo esperada:

  1. Reinicie o kernel e execute todas as células de cima para baixo. Uma captura de tela mostrando o botão reiniciar kernel.

  2. Confirme se cada célula é concluída com êxito.

  3. Se as células de transformação levarem mais de 5 minutos para serem executadas em um pool pequeno, aperte os filtros de instantâneo e a projeção de coluna antes de aumentar a escala.

  4. Confirme se show_schema() retorna os nós e bordas esperados.

  5. Execute uma consulta GQL de exemplo e verifique a visualização e a saída tabular.

  6. Validar casos extremos:

    • Entrada vazia.
    • Descompasso de esquema.
    • Acesso à tabela não encontrado.

Tip

Adicione células de Markdown acima de cada seção de código para documentar a finalidade, as entradas, as saídas e os nós ou arestas produzidos.

Agendar um trabalho de grafo para materializar o grafo

Os grafos criados em uma sessão interativa são efêmeros. Agende um trabalho de grafo para persistir e atualizar o grafo. Para obter mais informações, consulte Agendar e gerenciar trabalhos de grafo Microsoft Sentinel.

  1. No notebook de grafo, selecione Criar trabalho agendado>Criar um trabalho de grafo. Uma captura de tela com o botão para criar um trabalho de grafo.

  2. Insira o Nome e a Descrição do grafo e verifique o caminho do notebook.

  3. Selecione uma agenda:

    • Sob demanda: compila uma vez, com uma retenção padrão de 30 dias.
    • Agendado: selecione a frequência de repetição e os horários de início e término.
  4. Selecione Enviar.

  5. Abra o gráfico na extensão Sentinel e monitore Detalhes da tarefa.

  6. Use Run Now para executar fora do agendamento, conforme necessário.

  7. Confirmar a progressão de status de Queued para In ProgressReady.

Importante

Os trabalhos enviados são desvinculados do seu notebook local. A edição da configuração local .ipynb não atualiza a tarefa agendada. Para atualizar um notebook do trabalho, baixe-o no painel Gráficos, edite-o e, em seguida, use Editar trabalho>Enviar.

Consultar e visualizar no Graph Explorer

Depois que o status do trabalho do grafo for Ready, consulte e visualize no portal do Defender, em notebooks e em APIs REST.

  1. No portal do Defender, em Microsoft Sentinel, abra a experiência de grafo e selecione o grafo materializado.
  2. Execute consultas GQL, inspecione o esquema, alterne entre as saídas visual e tabular e navegue até o próximo salto.
  3. Consulte esta referência rápida da GQL:
Padrão ou cláusula Example
Nó com rótulo (g:EntraGroup)
Borda tipada e direcionada -[c:ContainsUser]->
Caminho de comprimento variável (1 a 8 saltos) (a)-[e]->{1,8}(b)
Filter WHERE g.displayName = 'Finance Admins'
Projetar, classificar, limitar RETURN g.displayName ORDER BY g.displayName LIMIT 10
Expressões de etiqueta (:EntraUser \| EntraServicePrincipal)

Note

Cada consulta GQL começa com MATCH. O mecanismo opera em UTC. Use ZONED_DATETIME(...) para literais datetime. INSERT e CREATE não são suportados. Os gráficos são somente para leitura.

  1. Consulta de um bloco de anotações.

    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. Consultar por meio das APIs REST do 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 a forma de saída. "Table" retorna linhas, "Graph" retorna nós e bordas e ["Table", "Graph"] retorna ambas.

Para obter mais informações, consulte APIs REST do Graph para gráficos personalizados.

Empacote e publique sua solução de grafo

Depois que o grafo for testado e materializado, empacote-o para implantação aos clientes. Para obter instruções de empacotamento detalhadas, consulte Empacotar e publicar soluções de notebook e do Microsoft Sentinel Graph.

Solução de problemas

Use as tabelas a seguir para diagnosticar problemas comuns por sintoma.

Criação de gráficos

Sintoma Causa e correção prováveis
MicrosoftSentinelProvider ou sentinel_graph não encontrado Entre novamente na extensão e confirme se um kernel Microsoft Sentinel está selecionado.
A célula trava em "Iniciando a sessão do Spark" A primeira inicialização pode levar de 3 a 5 minutos. Se exceder 6 minutos, verifique a capacidade do pool e tente novamente.
show_schema() está vazio ou Graph.build() falha Confirme se as colunas de chave e exibição existem e não são nulas, e os valores de origem e de destino node_type correspondem a aliases de nó.
A consulta GQL não retorna linhas Confirme se há valores de filtro no snapshot selecionado e verifique a filtragem do snapshot.
publish() falha com permissão negada Confirme se você tem a função Operador de Segurança, Administrador de Segurança ou Administrador Global.

Autoría assistida por Inteligência Artificial

Sintoma Causa e correção prováveis
@sentinel /graph-authoring não faz nada Confirme se as extensões GitHub Copilot e Jupyter estão instaladas e ativas e se você tem um plano Copilot Business ou Enterprise.
O código gerado faz referência a uma tabela ausente Confirme a instalação do conector e verifique se a tabela aparece no data lake explorer.

Agendamento de trabalho

Sintoma Causa e correção prováveis
As edições no notebook local não se refletem na tarefa Baixe o notebook do trabalho no painel Graphs, edite-o e depois use Editar trabalho>Enviar.
Grafo materializado desapareceu Os grafos sob demanda têm retenção de 30 dias. Agende um trabalho recorrente ou execute um novo build.