Mukautettujen kaavioiden käytön aloittaminen Microsoft Sentinel (esikatselu)

Microsoft Sentinel mukautettujen kaavioiden avulla tietoturvatutkijat ja analyytikot voivat luoda räätälöityjä kaavioesityksiä suojaustiedoistaan. Luomalla mukautettuja kaavioita voit mallintaa tiettyjä hyökkäysmalleja, tutkia uhkia ja suorittaa edistyneitä kaavioalgoritmeja paljastaaksesi piilotetut suhteet digitaalisessa ympäristössäsi. Tässä oppaassa käydään läpi mukautettujen kaavioiden luominen ja hallinta Microsoft Sentinel Visual Studio Code -laajennuksen Jupyter-muistikirjoilla.

Tässä artikkelissa keskitytään mukautettujen kaavioiden manuaaliseen muokkaamiseen koodin avulla. Jos haluat tekoälypohjaisen kokemuksen, katso tekoälyavusteinen mukautettu kaavion tuottaminen Microsoft Sentinel.

Ennakkovaatimukset

Mukautettujen kaavioiden luominen Microsoft Sentinel edellyttää seuraavia:

Ota Microsoft Entra ID-liitin käyttöön, jotta voit käyttää tämän artikkelin mallikoodissa käytettyjä Microsoft Entra kohdetaulukoita. Lisätietoja on Microsoft Sentinel Data Lake -tallennustilan kohdassa Resurssien tietojen käsittely.

Käyttöoikeudet

Jotta voit käsitellä mukautettuja kaavioita, tarvitset seuraavat XDR-käyttöoikeudet Sentinel Data Lakessa. Seuraavassa taulukossa on lueteltu yleisten kaaviotoimintojen käyttöoikeusvaatimukset:

Kaaviotoiminto Tarvittavat käyttöoikeudet
Mallinna ja luo muistikirjakaavio Käytä mukautettua Microsoft Defender XDR yhdistettyä RBAC-roolia tietojen keräämisen tietojen (hallinta) kanssa Microsoft Sentinel tietojen keräämisessä.
Kaavion sisentäminen vuokraajassa Käytä jotakin seuraavista Microsoft Entra ID rooleista:
Suojausoperaattori
Suojauksen järjestelmänvalvoja
Yleinen järjestelmänvalvoja
Kysely pysyvästä kaaviosta Käytä mukautettua Microsoft Defender XDR yhdistettyä RBAC-roolia, jolla on Microsoft Sentinel tietojen keräämisen suojaustietojen perustietojen perusoikeudet (lukuoikeudet).

Tärkeää

Sinulla on oltava oikeudet kaaviossa käytettyjen tietojen lukemiseen. Jos sinulla ei ole käyttöoikeutta tiettyyn tietojoukkoon, näitä tietoja ei sisällytetä kaavioon. Kaavion luomista ei saa rajoittaa Sentinel vaikutusalueella. Alueen käyttäjä ei voi luoda mukautettua kaaviota.

Microsoft Entra ID roolit tarjoavat laajan käyttöoikeuden kaikkiin Data Lake -järjestelmän työtiloihin. Lisätietoja on artikkelissa Microsoft Sentinel roolit ja käyttöoikeudet.

Visual Studio Coden ja Microsoft Sentinel-laajennuksen asentaminen

Luo mukautettuja kaavioita käyttämällä Jupyter-muistikirjoja Microsoft Sentinel Visual Studio Code -laajennuksessa. Lisätietoja on artikkelissa Visual Studio Coden asentaminen ja Microsoft Sentinel -laajennus.

Mukautetun kaavion luominen

Voit luoda ja käsitellä mukautettuja kaavioita suorittamalla seuraavat vaiheet:

  1. Mukautetun kaavion mallintaminen
  2. Mukautetun kaavion sisennys ajoittamalla kaaviotyö
  3. Mukautettujen kaavioiden tarkasteleminen ja hallinta

Mukautetun kaavion mallintaminen

Luo mukautettu kaavio käyttämällä Jupyter-muistikirjaa Microsoft Sentinel Visual Studio Code -laajennuksessa.

Seuraavissa vaiheissa käydään läpi ensimmäisen mukautetun kaavion luominen mallimuistikirjan avulla.

Muistikirjan määrittäminen ja yhteyden muodostaminen Data Lake -tallennustilaan

  1. Valitse Visual Studio Codessa, johon on asennettu Microsoft Sentinel laajennus, Microsoft Sentinel-kuvake vasemmanpuoleisessa valikossa.

  2. Tarkastele kaavioita valitsemalla Kirjaudu sisään

  3. Näyttöön tulee valintaikkuna, jossa on teksti Tunniste "Microsoft Sentinel" haluaa kirjautua sisään Microsoftilla. Valitse Salli sisäänkirjautuminen.

  4. Kirjaudu sisään tunnistetiedoillasi.

  5. Kun olet kirjautunut sisään, valitse + sitten Luo uusi muistikirja.

  6. Nimeä muistikirjatiedosto ja tallenna se sopivaan sijaintiin työtilassasi.

    Näyttökuva Visual Studio Coden kaavioiden kirjautumissivusta.

  7. Valitse valitse ydin muistikirjaikkunan oikeasta yläkulmasta spark-käsittelyvarannon valitsemiseksi.

  8. Valitse Microsoft Sentinel ja valitse sitten jokin käytettävissä olevista spark-altaista.

    Näyttökuva Visual Studio Coden valitse ydin -sivusta.

    Vihje

    Tekoälykehotteiden avulla voit luoda mukautetun kaaviomuistikirjan. Lisätietoja on artikkelissa Tekoälyavusteisen mukautetun kaavion tuottaminen Microsoft Sentinel.

  9. Suorita solu kohteeseen valitsemalla solun vasemmalla puolella oleva suorita solukolmio -kuvake. Kun suoritat solun ensimmäisen kerran, sinua saatetaan kehottaa valitsemaan ydin, jos et jo valinnut sitä.

    Kun suoritat solun ensimmäisen kerran, Spark-istunnon aloittaminen kestää noin viisi minuuttia.

    Näyttökuva, jossa näkyy Visual Studio Coden ensimmäisen solun suorittaminen.

Kaavion luominen

Seuraava malli luo kaavion, joka kulkee Microsoft Entra ryhmän jäsenyyksissä ja ymmärtää sisäkkäiset ryhmäsuhteet. Mallikoodin avulla voit aloittaa yksinkertaisen käyttötapauksen käytön, jotta opit mukautetun kaavioominaisuuden ja hyödynnät kaavion läpiviennin tehoa tutkimuksissasi. Voit luoda kaavion mistä tahansa Sentinel Data Lake -järjestelmässä käytettävissä olevasta taulukosta.

  1. Muodosta yhteys työtilaasi ja lue Entra resurssitaulukoista kaavion luomisen aloittamiseksi.

    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")
    
  2. Kaavion luomiseen tarvittavan solmun ja reunan DataFrames-kehysten valmisteleminen

    # ============================================================
    # 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")))
    )
    
  3. Määritä kaavion rakenne ja sido edellisessä vaiheessa luotuihin DataFrame-kehyksiin

    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()
    
  4. Kaavion rakenteen vahvistaminen

    # Check the schema of the graph spec to ensure it's correct
    entra_group_graph_spec.show_schema()
    
  5. Luo kaavio, mukaan lukien tietojen valmisteleminen ja kaavion julkaiseminen

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

    Huomautus

    Vuorovaikutteisten muistikirjaistuntojen aikana luodut kaaviot poistetaan, kun muistikirjaistunto suljetaan. Jos haluat jatkaa kaavion uudelleenkäyttöä ja jakamista varten, katso Kohta Mukautetun kaavion lisääminen pysyväksi

Olet nyt luonut kaavion muistikirjaan.

Jos haluat näyttää kaavion visuaalisen esityksen, liitä uuteen soluun ja suorita seuraava koodi:

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

Tämä koodi suorittaa GQL (Graph Query Language) -mallikyselyn, joka noutaa kaikki sisäkkäisen ryhmän jäsenyyden enintään 8 tasoa syväksi Tuloksena saatava kaavio visualisoidaan tulosteessa

Näyttökuva, joka näyttää kaavion visualisoinnin Visual Studio Codessa.

Mukautetun kaavion lisääminen pysyväksi

Kun olet luonut kaaviokoodin muistikirjaan, voit suorittaa muistikirjan vuorovaikutteisessa istunnossa tai ajoittaa kaaviotyön. Vuorovaikutteisen muistikirjaistunnon aikana luodut kaaviot ovat väliaikaisia, ja ne ovat käytettävissä vain muistikirjaistunnon kontekstissa. Jos haluat tallentaa kaavion ja jakaa sen tiimillesi, ajoita kaaviotyö, jotta kaaviosi voidaan muodostaa uudelleen usein. Kun kaavio on tallennettu, se on käytettävissä seuraavista: kaaviokokemus Microsoft Defender-portaalissa Sentinel-, Visual Studio Code -muistikirjat- ja Graph-kyselyiden ohjelmointirajapinnat-kohdassa.

  1. Valitse kaaviomuistikirjasta Luo ajoitettu työ ja valitse sitten Luo kaaviotyö.

    Näyttökuva, jossa näkyy Luo ajoitettu työ -painike kaavion muistikirjassa.

  2. Kirjoita Luo kaavio -työlomakkeeseenKaavion nimi ja Kuvaus ja varmista, että Polku sisältää oikean kaavion muistikirjan.

  3. Jos haluat luoda kaavion määrittämättä päivitysaikataulua, valitse Aikataulu-osiosta Pyydettäessä ja luo sitten kaavio valitsemalla Lähetä.

    Huomautus

    Pyydettäessä luodut kaaviot säilyttävät oletuksena 30 päivää, ja ne poistetaan vanhentumisen jälkeen.

  4. Jos haluat luoda kaavion, jossa kaavion tietoja päivitetään säännöllisesti, valitse Aikataulu-osiosta Ajoitettu.

    1. Valitse työn toistotiheys . Voit valita vaihtoehdon Minuutti, Tunneittain, Viikoittain, Päivittäin tai Kuukausittain.

    2. Lisää vaihtoehtoja näytetään aikataulun määrittämiseksi valitsemasi tiheyden mukaan. Esimerkiksi viikonpäivä, kellonaika tai kuukauden päivä.

    3. Valitse Alkamisaika , jotta aikataulun suorittaminen alkaa.

    4. Valitse päättymisaika aikataulun suorittamisen lopettamiseksi. Jos et halua määrittää aikataulun päättymisaikaa, valitse Määritä työ suoritettavaksi loputtomasti. Päivämäärät ja kellonajat ovat aikavyöhykkeelläsi.

    5. Tallenna työn määritykset ja julkaise työ valitsemalla Lähetä . Kaavion muodostamisprosessi alkaa vuokraajassasi. Tarkastele juuri luotua kaaviota ja sen viimeisintä tilaa Sentinel-laajennuksessa.

    Näyttökuva luo kaaviotyö -sivusta.

Mukautettujen kaavioiden tarkasteleminen ja hallinta

Kun olet luonut kaaviotyön, voit tarkastella ja hallita vuokraajan kaaviota Visual Studio Coden Microsoft Sentinel laajennuksesta.

  1. Valitse kaavioluettelosta muodostettu kaavio, jotta näet sen tiedot.

  2. Valitse Työn tiedot -välilehti, jos haluat tarkastella kaaviotyön tilaa, mukaan lukien edellinen suoritusaika, seuraava suoritusaika ja mahdolliset koontiprosessin aikana kohdatut virheet.

  3. Käynnistä kaavion koontiversio manuaalisesti ajoitettujen aikojen ulkopuolella valitsemalla Suorita nyt . Tilaksivaihtuu Jonossa ja sitten "Keskeneräinen" kaaviota luotaessa.

    Näyttökuva, jossa näkyy Visual Studio Coden kaaviotyön tiedot -välilehti.

  4. Kun kaavion koontiversio on valmis, tilaksi päivitetään Valmis. Voit tarkastella kaavion tietoja valitsemalla Kaavion tiedot -välilehden.

    Näyttökuva kaavion tietojen välilehdestä.

  5. Voit nyt kysellä ja visualisoida kaaviota Defender-portaalin Microsoft Sentinel kaaviovisualisoinnista. Lisätietoja on artikkelissa Kaavioiden visualisoiminen Microsoft Sentinel (esikatselu) -kohdassa.