Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
I grafici personalizzati in Microsoft Sentinel consentono a ricercatori e analisti della sicurezza di creare rappresentazioni di grafi personalizzate dei dati di sicurezza. Creando grafici personalizzati, è possibile modellare modelli di attacco specifici, analizzare le minacce ed eseguire algoritmi di grafo avanzati per individuare relazioni nascoste all'interno dell'ambiente digitale. Questa guida illustra i passaggi per creare e gestire grafici personalizzati usando i notebook di Jupyter nell'estensione Microsoft Sentinel Visual Studio Code.
Questo articolo è incentrato sulla creazione manuale di grafici personalizzati usando il codice. Per un'esperienza basata sull'intelligenza artificiale, vedere Creazione di grafici personalizzati assistiti dall'intelligenza artificiale in Microsoft Sentinel.
Prerequisiti
Per creare grafici personalizzati in Microsoft Sentinel, è necessario quanto segue:
- Microsoft Sentinel estensioni per Visual Studio Code. Per altre informazioni, vedere Eseguire notebook nel data lake Microsoft Sentinel.
- Estensione Jupyter per Visual Studio Code.
- Microsoft Sentinel data lake configurato con le autorizzazioni appropriate. Per altre informazioni, vedere Eseguire l'onboarding in Microsoft Sentinel data lake.
Abilitare il connettore Microsoft Entra ID per inserire le tabelle degli asset Microsoft Entra usate nel codice di esempio di questo articolo. Per altre informazioni, vedere Inserimento di dati di asset nel data lake Microsoft Sentinel.
Autorizzazioni
Per interagire con i grafici personalizzati, sono necessarie le autorizzazioni XDR seguenti in Sentinel data lake. Nella tabella seguente sono elencati i requisiti di autorizzazione per le operazioni a grafo comuni:
| Operazione graph | Autorizzazioni necessarie |
|---|---|
| Modellare e compilare un grafico notebook | Usare un ruolo controllo degli accessi in base al ruolo personalizzato Microsoft Defender XDR unificato con autorizzazioni di gestione dei dati per la raccolta di dati Microsoft Sentinel. |
| Rendere persistente un grafico nel tenant | Usare uno dei ruoli di Microsoft Entra ID seguenti: Operatore della sicurezza Amministratore della sicurezza Amministratore globale |
| Eseguire query su un grafico persistente | Usare un ruolo controllo degli accessi in base al ruolo personalizzato Microsoft Defender XDR unificato con autorizzazioni di base dei dati di sicurezza (lettura) sulla raccolta di dati Microsoft Sentinel. |
Importante
È necessario disporre delle autorizzazioni per leggere i dati usati nel grafico. Se non si ha accesso a un set di dati specifico, tali dati non verranno inclusi nel grafico. Per creare un grafico, non è necessario essere limitati da un ambito Sentinel. Un utente con ambito non è in grado di creare un grafico personalizzato.
Microsoft Entra ID ruoli offrono un ampio accesso a tutte le aree di lavoro nel data lake. Per altre informazioni, vedere Ruoli e autorizzazioni in Microsoft Sentinel.
Installare Visual Studio Code e l'estensione Microsoft Sentinel
Creare grafici personalizzati usando i notebook di Jupyter nell'estensione Microsoft Sentinel Visual Studio Code. Per altre informazioni, vedere Installare Visual Studio Code e l'estensione Microsoft Sentinel
Creare un grafico personalizzato
Per creare e usare grafici personalizzati, completare la procedura seguente:
- Modellare un grafico personalizzato
- Rendere persistente il grafico personalizzato pianificando un processo grafico
- Visualizzare e gestire grafici personalizzati
Modellare un grafico personalizzato
Creare un grafico personalizzato usando un notebook di Jupyter nell'estensione Microsoft Sentinel Visual Studio Code.
La procedura seguente illustra come creare il primo grafico personalizzato usando un notebook di esempio.
Configurare il notebook e connettersi al data lake
In Visual Studio Code con l'estensione Microsoft Sentinel installata selezionare l'icona Microsoft Sentinel nel menu a sinistra.
Selezionare Accedi per visualizzare i grafici
Viene visualizzata una finestra di dialogo con il testo L'estensione 'Microsoft Sentinel' vuole accedere usando Microsoft. Selezionare Consenti per accedere.
Accedere con le credenziali.
Dopo aver eseguito l'accesso, selezionare + quindi Crea nuovo notebook.
Assegnare un nome al file notebook e salvarlo in un percorso appropriato nell'area di lavoro.
Selezionare Seleziona kernel in alto a destra nella finestra del notebook per selezionare un pool di calcolo spark.
Selezionare Microsoft Sentinel, quindi selezionare uno dei pool spark disponibili.
Consiglio
È possibile usare le richieste di intelligenza artificiale per creare un notebook grafico personalizzato. Per altre informazioni, vedere Creazione di grafici personalizzati assistiti dall'intelligenza artificiale in Microsoft Sentinel.
Eseguire una cella a selezionando l'icona del triangolo della cella di esecuzione a sinistra della cella. La prima volta che si esegue una cella, potrebbe essere richiesto di selezionare un kernel se non ne è già stata selezionata una.
La prima volta che si esegue una cella, l'avvio della sessione Spark richiede circa cinque minuti.
Creare un grafico
L'esempio seguente crea un grafico per attraversare Microsoft Entra appartenenze ai gruppi e comprendere le relazioni di gruppo annidate. Il codice di esempio consente di iniziare a usare un semplice caso d'uso per apprendere la funzionalità grafo personalizzata e sfruttare la potenza dell'attraversamento del grafo per le indagini. È possibile creare un grafico da qualsiasi tabella disponibile nel data lake Sentinel.
Connettersi all'area di lavoro e leggere Entra tabelle degli asset per iniziare a compilare il grafico.
from pyspark.sql import functions as F from sentinel_lake.providers import MicrosoftSentinelProvider lake_provider = MicrosoftSentinelProvider(spark=spark) # Use the "System tables" workspace which contains the Entra* Assets tables # If you are data is in a different workspace, update this variable accordingly and ensure the tables are present LOG_ANALYTICS_WORKSPACE = "System tables" # Dynamically get the latest snapshot time from EntraUsers 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")) # Load EntraMembers - 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")) ) ) # Load EntraGroups - nodes df_groups = ( lake_provider.read_table("EntraGroups", LOG_ANALYTICS_WORKSPACE) .filter(snapshot_filter) .select("id", "displayName", "mailEnabled") ) # Load EntraUsers - nodes df_users = ( lake_provider.read_table("EntraUsers", LOG_ANALYTICS_WORKSPACE) .filter(snapshot_filter) .select("id", "accountEnabled", "displayName", "department", "lastPasswordChangeDateTime", "userPrincipalName", "usageLocation") ) # Load EntraServicePrincipals - nodes df_service_principals = ( lake_provider.read_table("EntraServicePrincipals", LOG_ANALYTICS_WORKSPACE) .filter(snapshot_filter) .select("accountEnabled", "id", "displayName", "servicePrincipalType", "tenantId", "organizationId") ) # Fix for Spark 3.x Parquet datetime rebase issue. Required when reading Parquet files # written by Spark 2.x which used the Julian calendar, whereas Spark 3.x uses Proleptic # Gregorian. Without these settings, timestamp columns (e.g. lastPasswordChangeDateTime) # may throw errors or return incorrect values. Safe to remove if all data was written by # Spark 3.x (typical for current Fabric/Sentinel environments). spark.conf.set("spark.sql.parquet.datetimeRebaseModeInRead", "CORRECTED") spark.conf.set("spark.sql.parquet.datetimeRebaseModeInWrite", "CORRECTED") spark.conf.set("spark.sql.parquet.int96RebaseModeInRead", "CORRECTED") spark.conf.set("spark.sql.parquet.int96RebaseModeInWrite", "CORRECTED")Preparare il nodo e i dataframe perimetrali necessari per la compilazione del grafico
# ============================================================ # NODE PREPARATION # ============================================================ # EntraUser nodes - keyed by user id user_nodes = ( df_users.df .select( F.col("id"), F.col("displayName"), F.col("accountEnabled"), F.col("department"), F.col("lastPasswordChangeDateTime"), F.col("userPrincipalName"), F.col("usageLocation") ) ) # EntraGroup nodes - keyed by group id group_nodes = ( df_groups.df .select( F.col("id"), F.col("displayName"), F.col("mailEnabled") ) ) # EntraServicePrincipal nodes - keyed by SP id sp_nodes = ( df_service_principals.df .select( F.col("id"), F.col("displayName"), F.col("accountEnabled"), F.col("servicePrincipalType"), F.col("tenantId"), F.col("organizationId") ) ) # ============================================================ # EDGE PREPARATION # ============================================================ # Edge: EntraGroup --Contains--> EntraUser 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: EntraGroup --Contains--> EntraGroup (nested groups) 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"))) ) # Edge: EntraGroup --Contains--> EntraServicePrincipal edge_group_contains_sp = ( df_members.df .filter(F.col("targetType") == "servicePrincipal") .select( F.col("sourceId").alias("SourceGroupId"), F.col("targetId").alias("TargetSPId") ) .distinct() .withColumn("EdgeKey", F.concat_ws("_", F.col("SourceGroupId"), F.col("TargetSPId"))) )Definire lo schema del grafo e associare i dataframe creati nel passaggio precedente
from sentinel_graph import GraphSpecBuilder, Graph # Define the graph schema entra_group_graph_spec = ( GraphSpecBuilder.start() # === NODES === .add_node("EntraUser") .from_dataframe(user_nodes) # Native Spark DataFrame (from .df + .select + .distinct) .with_columns( "id", "displayName", "accountEnabled", "department", "lastPasswordChangeDateTime", "userPrincipalName", "usageLocation", key="id", display="displayName" ) .add_node("EntraGroup") .from_dataframe(group_nodes) # Native Spark DataFrame .with_columns( "id", "displayName", "mailEnabled", key="id", display="displayName" ) .add_node("EntraServicePrincipal") .from_dataframe(sp_nodes) # Native Spark DataFrame .with_columns( "id", "displayName", "accountEnabled", "servicePrincipalType", "tenantId", "organizationId", key="id", display="displayName" ) # === EDGES === # EntraGroup --ContainsUser--> EntraUser .add_edge("ContainsUser") .from_dataframe(edge_group_contains_user) # Native Spark DataFrame .source(id_column="SourceGroupId", node_type="EntraGroup") .target(id_column="TargetUserId", node_type="EntraUser") .with_columns("SourceGroupId", "TargetUserId", "EdgeKey", key="EdgeKey", display="EdgeKey") # EntraGroup --ContainsGroup--> EntraGroup (nested groups) .add_edge("ContainsGroup") .from_dataframe(edge_group_contains_group) # Native Spark DataFrame .source(id_column="SourceGroupId", node_type="EntraGroup") .target(id_column="TargetGroupId", node_type="EntraGroup") .with_columns("SourceGroupId", "TargetGroupId", "EdgeKey", key="EdgeKey", display="EdgeKey") # EntraGroup --ContainsServicePrincipal--> EntraServicePrincipal .add_edge("ContainsServicePrincipal") .from_dataframe(edge_group_contains_sp) # Native Spark DataFrame .source(id_column="SourceGroupId", node_type="EntraGroup") .target(id_column="TargetSPId", node_type="EntraServicePrincipal") .with_columns("SourceGroupId", "TargetSPId", "EdgeKey", key="EdgeKey", display="EdgeKey") ).done()Convalidare lo schema del grafo
# Check the schema of the graph spec to ensure it's correct entra_group_graph_spec.show_schema()Compilare il grafico, inclusa la preparazione dei dati e la pubblicazione del grafico
# Build the graph from the spec - this will validate the spec and prepare it for querying # Alter options is to use Graph.prepare() to prepare the graph nodes and edges in the lake # and then use Graph.publish() to create the graph. You would typically call prepare() and publish() # seperately to understand the cost of Graph API calls that are triggeterd by Graph.publish() # see https://learn.microsoft.com/azure/sentinel/billing?tabs=simplified%2Ccommitment-tiers intra_group_graph = Graph.build(entra_group_graph_spec)Nota
I grafici creati durante le sessioni interattive del notebook vengono rimossi quando la sessione del notebook viene chiusa. Per rendere persistente il grafico per il riutilizzo e la condivisione, vedere Rendere persistente il grafico personalizzato
È stato creato un grafico nel notebook.
Per visualizzare una rappresentazione visiva del grafico, in una nuova cella incollare ed eseguire il codice seguente:
# Query 1: Find nested group relationships nexting 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 *
"""
intra_group_graph.query(query_nested_groups).show()
Questo codice esegue una query GQL (Graph Query Language) di esempio per recuperare tutte le appartenenze a gruppi annidati fino a 8 livelli in profondità Il grafico risultante viene visualizzato nell'output
Rendere persistente il grafico personalizzato
Dopo aver creato il codice del grafo nel notebook, è possibile eseguire il notebook in una sessione interattiva o pianificare un processo a grafo. I grafici creati durante la sessione interattiva del notebook sono temporanei e sono disponibili solo nel contesto della sessione notebook. Per salvare il grafico e condividerlo con il team, pianificare un processo di grafo per ricompilare frequentemente il grafico. Una volta salvato, il grafico è accessibile da: l'esperienza del grafo nel portale di Microsoft Defender in Sentinel, Notebook di Visual Studio Code e API di query Graph.
Nel notebook del grafo selezionare Crea processo pianificato, quindi selezionare Crea un processo grafico.
Nel modulo Crea processo grafico immettere il nome e la descrizione del grafo e verificare che il notebook del grafo corretto sia incluso in Percorso.
Per compilare il grafico senza configurare una pianificazione di aggiornamento, selezionare Su richiesta nella sezione Pianificazione e quindi selezionare Invia per creare il grafico.
Nota
I grafici creati con la pianificazione su richiesta hanno una conservazione predefinita di 30 giorni e vengono eliminati alla scadenza.
Per compilare il grafico in cui i dati del grafo vengono aggiornati regolarmente, selezionare Pianificato nella sezione Pianificazione .
Selezionare una frequenza di ripetizione per il processo. È possibile scegliere tra Minuti, Orari, Settimanali, Giornalieri o Mensili.
Vengono visualizzate altre opzioni per configurare la pianificazione, a seconda della frequenza selezionata. Ad esempio, il giorno della settimana, l'ora del giorno o il giorno del mese.
Selezionare Inizio in tempo per l'avvio dell'esecuzione della pianificazione.
Selezionare fine in tempo per interrompere l'esecuzione della pianificazione. Se non si vuole impostare un'ora di fine per la pianificazione, selezionare Imposta processo per l'esecuzione illimitata. Le date e le ore si trovano nel fuso orario.
Selezionare Invia per salvare la configurazione del processo e pubblicare il processo. Il processo di compilazione del grafico viene avviato nel tenant. Visualizzare il grafico appena creato e il relativo stato più recente nell'estensione Sentinel.
Visualizzare e gestire grafici personalizzati
Dopo aver creato un processo grafico, è possibile visualizzare e gestire il grafico nel tenant dall'estensione Microsoft Sentinel in Visual Studio Code.
Nell'elenco dei grafici selezionare il grafo materializzato per visualizzarne i dettagli.
Selezionare la scheda Dettagli processo per visualizzare lo stato del processo grafico, inclusi l'ultima esecuzione, la fase di esecuzione successiva e gli eventuali errori rilevati durante il processo di compilazione.
Selezionare Esegui ora per attivare manualmente una compilazione a grafo al di fuori degli orari pianificati. Lo stato viene modificato in Accodato, quindi "In corso" durante la compilazione del grafico.
Al termine della compilazione del grafico, lo stato viene aggiornato in Pronto. Selezionare la scheda Dettagli grafico per visualizzare le informazioni sul grafico.
È ora possibile eseguire query e visualizzare il grafico dalla visualizzazione del grafico in Microsoft Sentinel nel portale di Defender. Per altre informazioni, vedere Visualizzare i grafici in Microsoft Sentinel grafico (anteprima).For more information, see Visualize graphs in Microsoft Sentinel graph (preview).
Articoli correlati
- Creazione di grafici personalizzati assistiti dall'intelligenza artificiale in Microsoft Sentinel
- Microsoft Sentinel riferimento alla libreria del provider graph
- Riferimento GQL (Graph Query Language) per Sentinel grafico personalizzato
- Visualizzare i grafici nel grafico Microsoft Sentinel (anteprima)