Desenvolver soluções personalizadas para plataformas de grafos

Note

Esta funcionalidade está atualmente em pré-visualização. Consulte Termos Suplementares de Utilização para Versões Prévias do Microsoft Azure.

Uma solução personalizada de grafos Microsoft Sentinel é uma solução baseada em cadernos que define nós e arestas a partir de tabelas de data lake do Microsoft Sentinel, constrói um grafo e permite aos utilizadores consultar esse grafo com a Linguagem de Consulta de Grafos (GQL).

Use este guia para construir, testar, materializar, empacotar e publicar uma solução de grafos personalizada como uma oferta SaaS no Centro de Parceiros Microsoft, para que os clientes possam descobri-la na Microsoft Security Store.

Pré-requisitos

Tens de estar integrado no data lake para criar soluções Custom Graph. Para mais informações, veja Como integrar o data lake Microsoft Sentinel.

Permissions

A tabela seguinte lista as permissões necessárias para cada operação ou âmbito neste guia.

Operation Função necessária
Adesão ao data lake do Sentinel Microsoft Entra ID - Administrador de Segurança ou Administrador Global
Integrar a área de trabalho do Sentinel no portal Defender Proprietário da Subscrição ou Administrador de Acesso do Utilizador ao nível da subscrição e Contribuidor do Microsoft Sentinel ao nível da subscrição ou do grupo de recursos
Integrar o espaço de trabalho do Sentinel no data lake Proprietário da subscrição ou Contribuidor do Microsoft Sentinel ao nível da subscrição ou do grupo de recursos
Modelar e criar um gráfico de bloco de notas Função RBAC unificada personalizada do Microsoft Defender XDR com a permissão data (manage) para a recolha de dados do Microsoft Sentinel
Guardar de forma persistente (materializar) um grafo Operador de Segurança, Administrador de Segurança ou Administrador Global
Consultar um gráfico persistente Função unificada de RBAC personalizada do Microsoft Defender XDR com security data basics (read) controlo sobre a recolha de dados do Microsoft Sentinel
Publicação da solução Custom Graph Conta do Marketplace Publisher no Centro de Parceiros Microsoft

Tools

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

Sugestão

Reutilize um data lake existente se o seu inquilino já estiver integrado para consultas KQL, notebooks ou um Security agente do Copilot. Há um lago de dados por locatário. No portal do Defender, aceda a Sistema>Definições>Microsoft Sentinel>Data lake. Se o estado estiver Provisionado, salta a tarefa 1.

Fluxo de compilação

O fluxo de trabalho seguinte descreve os passos para construir e publicar uma solução de grafos personalizada.

  1. Ingere dados de amostra nas tabelas que o seu gráfico modela.
  2. Valide a conectividade com um notebook básico.
  3. Criar o gráfico personalizado.
  4. Testa o caderno de gráficos.
  5. Agende um trabalho de gráfico para materializar o gráfico.
  6. Consulta e visualiza o grafo a partir do explorador de grafos.
  7. Empacote e publique a solução de gráfico personalizada.

Importar dados de exemplo

Esta tarefa ingere tabelas de ativos do Microsoft Entra ID usadas pelo gráfico de exemplo neste guia: EntraUsers, EntraGroups, EntraServicePrincipals, e EntraMembers.

  1. No portal do Defender, aceda a Sistema>Definições>Microsoft Sentinel>Conectores de dados.
  2. Ative o conector Microsoft Entra ID para que as tabelas de ativos do Entra sejam importadas para o data lake. Para mais informações, consulte Dados de ativos no Microsoft Sentinel data lake.
  3. Confirme que estas tabelas aparecem no explorador do lago de dados:
    • EntraUsers
    • EntraGroups
    • EntraServicePrincipals
    • EntraMembers
  4. Estas tabelas são colocadas no espaço de trabalho Tabelas do sistema.
  5. Opcional: importar outros conectores e substituir nomes de tabelas nos passos seguintes se o seu cenário utilizar dados diferentes.

Note

Se uma tabela não aparecer no explorador de lagos de dados, não pode usá-la para criação de grafos, e a assistência de IA não a referencia.

Validar a conectividade com um notebook simples

Crie e execute um bloco de notas mínimo para verificar a conectividade do data lake antes de criar grafos.

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

  2. No Visual Studio Code, em Sentinel Extension–Graphs, selecione Criar novo caderno. Uma captura de ecrã a mostrar a opção de criar novo caderno no VS Code.

  3. Guarde o caderno, por hello-world-show-tables.ipynbexemplo.

  4. Selecione Select kernel, selecione Microsoft Sentinel e selecione um pool de spark disponível. Uma captura de ecrã que mostra a opção select kernel no VS Code.

  5. Adicione as células seguintes por 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 (liga e define o teu espaço de trabalho):

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 (leia uma tabela e mostre as 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. Analise todas as células de cima a baixo.
  2. Confirme que todas as células estão concluídas sem um rastreamento vermelho, os dados de pré-visualização da tabela aparecem e a contagem de linhas é diferente de zero.

Note

Se as leituras falharem ou não devolverem linhas, confirme que o conector da secção Ingerir dados de exemplo concluiu o seu primeiro instantâneo, que LOG_ANALYTICS_WORKSPACE corresponde a uma área de trabalho real e que a sua conta tem acesso de leitura. Verifique o conteúdo da tabela com KQL no portal Defender para confirmar a presença de dados. Para mais informações, consulte Executar consultas KQL no data lake Microsoft Sentinel.

Criar gráfico personalizado

Autor de uma destas formas:

  • Criação de grafos assistida por IA.
  • Autor à mão.

Autoria de grafos assistida por IA

Para criar um gráfico com assistência de IA, siga estes passos:

  1. No Visual Studio Code, abra o Chat do GitHub Copilot.

  2. Comece o prompt com o assistente de criação de grafos @sentinel /graph-authoring e descreva o seu 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 ecrã que mostra a autoria de grafos assistida por IA no VS Code.

    O Copilot gera as seguintes células para o ciclo de criação do grafo:

    Fase do ciclo de vida Produção gerada
    Configuração do ambiente Verifica os pacotes necessários e as informações de ligação
    Carregamento de dados Lê tabelas nomeadas do lago de dados Sentinel
    Transformação de dados Prepara dados de nós e arestas
    Esquema de grafo Define os nós e as arestas
    Validação de esquemas Valida a definição do grafo
    Construção de grafos Materializa o gráfico da sessão
    Consulta de grafos Executa uma consulta GQL de exemplo e visualiza o resultado
  3. Continue a aperfeiçoar o bloco de notas com pedidos como estes:

    Goal Prompt
    Adicionar uma relação @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 compilação @sentinel Fix the error in the graph build step
    Compreender o código @sentinel Explain how edge keys are defined
    Procure uma API sem editar What parameters does build_graph_with_data() accept? #Sentinel

Sugestão

Use @sentinel /graph-authoring para criar ou modificar células de caderno. Se precisares de explicações sobre a API ou de consultas de exemplo, pergunta ao Copilot e inclui #Sentinel para obter respostas específicas do Sentinel.

Escrever manualmente

Para criar um gráfico manualmente, siga estes passos:

  1. Ligue-se a e leia tabelas 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 os DataFrames de nós e arestas.

    # 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 do 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. Constrói o gráfico.

    # 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 numa só chamada. Para inspecionar os nós e as arestas preparados antes da publicação, chame Graph.prepare(spec), reveja graph.nodes e graph.edges e, em seguida, chame graph.publish().

  5. Executa 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 caderno de grafos

Teste o caderno para garantir que produz a saída esperada do gráfico:

  1. Reinicia o kernel e executa todas as células de alto a baixo. Uma captura de ecrã a mostrar o botão de reiniciar kernel.

  2. Confirme que cada célula está concluída com sucesso.

  3. Se as células de transformação demorarem mais de 5 minutos num pool pequeno, restrinja os filtros de snapshot e a projeção de colunas antes de aumentar a escala.

  4. Confirme que show_schema() devolve os nós e arestas esperados.

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

  6. Validar casos limite:

    • Entrada vazia.
    • Desvio do esquema.
    • Falta acesso à mesa.

Sugestão

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

Agende uma tarefa de grafo para materializar o grafo

Os grafos criados numa sessão interativa são efémeros. Agende um trabalho de grafo para persistir e atualizar o gráfico. Para mais informações, consulte Agendar e gerir trabalhos de grafos Microsoft Sentinel.

  1. No seu notebook de grafos, selecione Criar Tarefa Agendada>Criar uma tarefa de grafo. Uma captura de ecrã que mostra o botão para criar uma tarefa de gráfico.

  2. Introduza o Nome e Descrição do grafo e verifique o caminho do caderno.

  3. Selecione um horário:

    • A pedido: compila uma vez, com um período de retenção predefinido de 30 dias.
    • Programado: selecionar a frequência de repetição e as horas de início e de fim.
  4. Selecione Enviar.

  5. Abre o gráfico na extensão Sentinel e monitoriza os Detalhes da tarefa.

  6. Utilize Run Now para executar fora da programação quando necessário.

  7. Confirme a progressão do estado de Queued para In Progress para Ready.

Importante

Os trabalhos submetidos são independentes do seu notebook local. Editar o local .ipynb não atualiza o trabalho agendado. Para atualizar um caderno de trabalhos, descarrega-o do painel Graphs, edita-o e depois usa Editar Enviar trabalho>.

Consultar e visualizar a partir do explorador de grafos

Quando o estado da tarefa do gráfico for Ready, consulte e visualize dados no portal do Defender, em notebooks e em APIs REST.

  1. No portal do Defender, em Microsoft Sentinel, abra a experiência de grafos e selecione o grafo materializado.
  2. Executar consultas GQL, inspecionar o esquema, trocar as saídas visuais e tabulares, e percorrer o próximo salto.
  3. Usa esta referência rápida do GQL:
Padrão ou cláusula Exemplo
Nó com rótulo (g:EntraGroup)
Aresta tipada e dirigida -[c:ContainsUser]->
Caminho de comprimento variável (1 a 8 saltos) (a)-[e]->{1,8}(b)
Filter WHERE g.displayName = 'Finance Admins'
Projetar, ordenar, limitar RETURN g.displayName ORDER BY g.displayName LIMIT 10
Expressões de etiqueta (:EntraUser \| EntraServicePrincipal)

Note

Toda consulta GQL começa com MATCH. O motor funciona em UTC. Use ZONED_DATETIME(...) para literais de data e hora. INSERT e CREATE não são suportados. Os gráficos são apenas de leitura.

  1. Consulta a partir de um notebook.

    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. Consulta usando APIs Graph REST.

    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 da saída. "Table" devolve linhas, "Graph" devolve nós e arestas, e ["Table", "Graph"] devolve ambos.

Para mais informações, consulte Graph REST APIs para grafos personalizados.

Empacote e publique a sua solução de grafos

Depois de o seu gráfico ser testado e materializado, empacote-o para implementação nos clientes. Para instruções detalhadas de embalagem, consulte Empacotar e publicar soluções para grafos e cadernos Microsoft Sentinel.

Troubleshooting

Use as tabelas seguintes para diagnosticar problemas comuns por sintoma.

Autoria de grafos

Symptom Causa provável e solução
MicrosoftSentinelProvider ou sentinel_graph não encontrado Inicie sessão novamente na extensão e confirme que um kernel Microsoft Sentinel foi selecionado.
A célula fica bloqueada na "Sessão de início do Spark" O primeiro arranque pode demorar entre 3 a 5 minutos. Se ultrapassar os 6 minutos, verifica a capacidade da piscina e tenta novamente.
show_schema() é vazio ou Graph.build() falha Confirme que as colunas de chave e de apresentação existem e não são nulas, e que os valores de origem e de destino node_type correspondem aos aliases dos nós.
A consulta GQL não retorna linhas Confirme que os valores do filtro existem no instantâneo selecionado e verifique a filtragem do instantâneo.
publish() falha devido a permissão negada Confirme que tem funções de Operador de Segurança, Administrador de Segurança ou Administrador Global.

Autoria assistida por IA

Symptom Causa provável e solução
@sentinel /graph-authoring Não faz nada Confirma que as extensões GitHub Copilot e Jupyter estão instaladas e ativas, e tens um plano Copilot Business ou Enterprise.
Código gerado faz referência a uma tabela em falta Confirme a configuração do conector e verifique se a tabela aparece no explorador do lago de dados.

Agendamento de tarefas

Symptom Causa provável e solução
As edições locais do notebook não são refletidas na tarefa Descarrega o caderno de tarefas a partir do painel de Gráficos, edita-o e depois usa Editar Enviar trabalho>.
O grafo materializado desapareceu Os gráficos on-demand têm retenção de 30 dias. Agende uma tarefa recorrente ou execute uma nova compilação.