Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Замечание
Сейчас эта функция доступна в предварительной версии. См. дополнительные условия использования предварительных версий Microsoft Azure.
Пользовательское графовое решение Microsoft Sentinel — это решение на основе записных книжек, которое определяет узлы и рёбра на основе таблиц озера данных Microsoft Sentinel, строит граф и позволяет пользователям выполнять запросы к этому графу с помощью языка запросов к графам (GQL).
Используйте это руководство, чтобы создать, протестировать, подготовить к развертыванию, упаковать и опубликовать настраиваемое графовое решение как предложение SaaS в Microsoft Partner Center, чтобы клиенты могли найти его в Microsoft Security Store.
Необходимые условия
Чтобы создать пользовательские решения Graph, необходимо подключиться к озеру данных. Дополнительные сведения см. в разделе "Подключение к озеру данных Microsoft Sentinel".
Permissions
В следующей таблице перечислены необходимые разрешения для каждой операции или области в этом руководстве.
| Операция | Требуемая роль |
|---|---|
| Подключение к озеру данных Sentinel | Microsoft Entra ID — администратор безопасности или глобальный администратор |
| Подключите рабочую область Sentinel к порталу Defender | Владелец подписки или администратор доступа пользователей на уровне подписки, а также участник Microsoft Sentinel на уровне подписки или группы ресурсов |
| Подключить рабочую область Sentinel к озеру данных | Владелец подписки или участник Microsoft Sentinel на уровне подписки или группы ресурсов |
| Моделирование и создание графа записной книжки | Пользовательская унифицированная роль RBAC Microsoft Defender XDR с разрешением data (manage) для сбора данных в Microsoft Sentinel |
| Сохранение (материализация) графа | Оператор безопасности, администратор безопасности или глобальный администратор |
| Запрос сохраняемого графа | Настраиваемая унифицированная роль RBAC Microsoft Defender XDR с security data basics (read) управлением сбором данных Microsoft Sentinel |
| Публикация настраиваемого решения Graph | Учетная запись Publisher Marketplace в Microsoft Partner Center |
Инструменты
Для создания и публикации пользовательского решения графа требуются следующие средства:
- Visual Studio Code.
- расширение Microsoft Sentinel для Visual Studio Code. Для получения дополнительной информации см. разделы Install Visual Studio Code и расширение Microsoft Sentinel.
- Расширение Jupyter для Visual Studio Code.
- расширение GitHub Copilot и тарифный план GitHub Copilot Business или Enterprise.
- Python 3.10 или более поздней версии на локальном компьютере.
Tip
Используйте повторно существующее озеро данных, если ваш арендатор уже подключён к запросам KQL, записным книжкам или агенту Security Copilot. Существует одно озеро данных для каждого клиента. На портале Defender перейдите в раздел Система>Параметры>Microsoft Sentinel>Озеро данных. Если статус — Provisioned, пропустите шаг 1.
Рабочий процесс сборки
Ниже описан процесс создания и публикации настраиваемого графового решения.
- Загрузите образцы данных в таблицы, которые моделирует ваш граф.
- Проверьте подключение с помощью простой записной книжки.
- Создание настраиваемого графа.
- Проверьте графический блокнот.
- Запланируйте задание на построение графа, чтобы материализовать граф.
- Запрос и визуализация графа из обозревателя Graph.
- Упакуйте и опубликуйте настраиваемое решение для графа.
Загрузка образцов данных
Эта задача загружает таблицы ресурсов Microsoft Entra ID, которые используются в примере графа в этом руководстве: EntraUsers, EntraGroups, EntraServicePrincipals и EntraMembers.
- На портале Defender перейдите в System>Settings>Microsoft Sentinel>Соединители данных.
- Включите коннектор Microsoft Entra ID, чтобы таблицы ресурсов Entra загружались в озеро данных. Для получения дополнительной информации см. раздел «Данные об активах» в data lake Microsoft Sentinel.
- Убедитесь, что в обозревателе озера данных отображаются следующие таблицы:
EntraUsersEntraGroupsEntraServicePrincipalsEntraMembers
- Эти таблицы попадают в рабочее пространство Системные таблицы.
- Необязательно. Добавьте данные из других коннекторов и замените имена таблиц на последующих шагах, если в вашем сценарии используются другие данные.
Замечание
Если таблица не отображается в обозревателе озера данных, ее нельзя использовать для создания графов, и ИИ-помощник не будет ее учитывать.
Проверка подключения с помощью простой записной книжки
Создайте и запустите минимальный блокнот, чтобы проверить подключение к озеру данных перед разработкой графа.
Откройте Visual Studio Code и войдите в расширение Microsoft Sentinel с той же учетной записью, которая имеет доступ к озеру данных.
В Visual Studio Code в разделе Sentinel Extension — Graphs выберите Создать новый блокнот.
Сохраните записную книжку, например
hello-world-show-tables.ipynb.Выберите Выбрать ядро, затем выберите Microsoft Sentinel и доступный пул Spark.
Добавьте следующие ячейки в порядок.
Ячейка 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
Ячейка 2. Код (подключение и настройка рабочей области):
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}")
Ячейка 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.
Ячейка 4 . Код (чтение таблицы и отображение строк):
# 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)
Ячейка 5 — код (необязательные проверочные подсчёты):
# Confirm the read returned data and inspect the schema.
print("Row count:", df_groups.df.count())
df_groups.df.printSchema()
- Запустите все ячейки сверху вниз.
- Убедитесь, что каждая ячейка завершается без красной трассировки, отображаются данные предварительного просмотра таблицы, а число строк не равно нулю.
Замечание
Если чтение завершается с ошибкой или не возвращает ни одной строки, убедитесь, что соединитель из раздела Загрузка образцов данных завершил свой начальный снимок, LOG_ANALYTICS_WORKSPACE указывает на существующую рабочую область и у вашей учетной записи есть права на чтение. Проверьте оглавление с помощью KQL на портале Defender, чтобы подтвердить наличие данных. Дополнительные сведения см. в разделе Запуск запросов KQL в озере данных Microsoft Sentinel.
Создайте пользовательский граф
Создайте одним из следующих способов:
- Разработка графов с поддержкой искусственного интеллекта.
- Автор вручную.
Разработка графов с поддержкой искусственного интеллекта
Чтобы создать граф с помощью ИИ, выполните следующие действия.
В Visual Studio Code откройте Copilot Chat GitHub.
Начните запрос со вспомогательного средства для создания графов
@sentinel /graph-authoringи опишите свой граф простым языком:@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.Copilot создает следующие ячейки для жизненного цикла разработки графа:
Стадия жизненного цикла Сгенерированные выходные данные Настройка среды Проверяет необходимые пакеты и сведения о подключении Загрузка данных Считывает именованные таблицы из озера данных Sentinel Преобразование данных Подготавливает данные узлов и рёбер Схема графа Определяет узлы и края Проверка схемы Проверяет определение графа Построение графа Материализует граф для сеанса Графовый запрос Выполняет пример запроса GQL и визуализирует результат Продолжайте дорабатывать блокнот с помощью таких запросов:
Goal Prompt Добавьте связь @sentinel Add an edge from User to IPAddressФильтрация данных @sentinel Filter the data to show only failed sign-insИзменение диапазона времени @sentinel Change the time range to the last 7 daysИсправлена ошибка сборки @sentinel Fix the error in the graph build stepПонимание кода @sentinel Explain how edge keys are definedНайти API без возможности редактирования What parameters does build_graph_with_data() accept? #Sentinel
Tip
Используется @sentinel /graph-authoring для создания или изменения ячеек записной книжки. Если вам нужны пояснения по API или примеры запросов, спросите Copilot и укажите #Sentinel, чтобы получить ответы по Sentinel.
Автор вручную
Чтобы создать граф вручную, выполните следующие действия.
Подключитесь и прочитайте таблицы активов.
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") )Подготовьте DataFrame для узлов и рёбер.
# 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"))) )Определите схему графа и привяжите объекты DataFrame.
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()Создайте граф.
# 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"Замечание
Graph.build()подготавливает данные и публикует их за один вызов. Чтобы проверить подготовленные узлы и рёбра перед публикацией, вызовитеGraph.prepare(spec), проверьтеgraph.nodesиgraph.edges, затем вызовитеgraph.publish().Запустите 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()
Протестируйте блокнот графов
Проверьте блокнот, чтобы убедиться, что он выводит ожидаемый график:
Подтвердите успешное завершение каждой ячейки.
Если ячейки преобразования выполняются дольше 5 минут в небольшом пуле, ужесточите фильтры моментальных снимков и проекцию столбцов перед увеличением масштаба.
Убедитесь, что
show_schema()возвращает ожидаемые узлы и рёбра.Запустите пример запроса GQL и проверьте визуализацию и табличные выходные данные.
Проверьте граничные случаи:
- Пустые входные данные.
- Изменение схемы.
- Отсутствует доступ к таблице.
Tip
Добавьте ячейки Markdown над каждым разделом кода с описанием назначения, входных данных, выходных данных, а также создаваемых узлов или рёбер.
Планирование задания графа для материализации графа
Графы, созданные в интерактивном сеансе, являются временными. Запланируйте задачу для сохранения и обновления графа. Дополнительные сведения см. в статье Планирование заданий графа Microsoft Sentinel и управление ими.
В блокноте графа выберите Создать задание по расписанию>Создать задание графа.
Введите имя и описание графа и проверьте путь к записной книжке.
Выберите расписание:
- По запросу: выполняет сборку один раз с 30-дневным хранением по умолчанию.
- Запланировано: выберите повторяемую периодичность и время начала и окончания.
Нажмите кнопку "Отправить".
Откройте граф в расширении Sentinel и отслеживайте сведения о задании.
Используйте Запустить сейчас, чтобы при необходимости выполнить запуск вне расписания.
Подтвердите последовательность изменения статуса от
QueuedдоIn ProgressдоReady.
Important
Отправленные задания не зависят от вашего локального блокнота. Редактирование локального .ipynb не обновляет запланированную задачу. Чтобы обновить блокнот задания, скачайте его с панели Graphs, внесите изменения, затем выберите Изменить задание>Отправить.
Запрос и визуализация из обозревателя Graph
После того как статус задания графа станет Ready, можно выполнять запросы и визуализировать данные на портале Defender, в записных книжках и через REST API.
- На портале Defender в разделе Microsoft Sentinel откройте представление графа и выберите свой материализованный граф.
- Выполняйте запросы GQL, просматривайте схему, переключайтесь между визуальным и табличным представлением результатов и переходите к следующему узлу.
- Используйте этот краткий справочник по GQL:
| Шаблон или предложение | Пример |
|---|---|
| Узел с меткой | (g:EntraGroup) |
| Типизированный, направленный край | -[c:ContainsUser]-> |
| Путь переменной длины (от 1 до 8 прыжков) | (a)-[e]->{1,8}(b) |
| Filter | WHERE g.displayName = 'Finance Admins' |
| Проекция, сортировка, ограничение | RETURN g.displayName ORDER BY g.displayName LIMIT 10 |
| Выражения для меток | (:EntraUser \| EntraServicePrincipal) |
Замечание
Каждый запрос GQL начинается с MATCH. Движок работает по времени UTC. Используется ZONED_DATETIME(...) для литералы datetime.
INSERT и CREATE не поддерживаются. Графы доступны только для чтения.
Запрос из блокнота.
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()Запрос с помощью REST API 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 управляет формой выходных данных.
"Table" возвращает строки, "Graph" возвращает узлы и края и ["Table", "Graph"] возвращает оба.
Дополнительные сведения см. в разделе REST API Graph для настраиваемых графов.
Упакуйте и опубликуйте решение графа
После тестирования и материализации графа упаковайте его для развертывания клиентам. Подробные инструкции по упаковке см. в статье Упаковка и публикация решений Microsoft Sentinel с графами и записными книжками.
Troubleshooting
Используйте следующие таблицы для диагностики распространенных проблем по симптомам.
Разработка графов
| Симптом | Вероятно, причина и исправление |
|---|---|
MicrosoftSentinelProvider или sentinel_graph не найдено |
Снова войдите в расширение и убедитесь, что выбрано ядро Microsoft Sentinel. |
| Ячейка зависает на этапе «Запуск сессии Spark» | Первый запуск может занять от 3 до 5 минут. Если значение превышает 6 минут, проверьте емкость пула и повторите попытку. |
show_schema() пуст или Graph.build() дает сбой |
Убедитесь, что ключевые и отображаемые столбцы существуют и не являются null, а исходные и целевые node_type значения соответствуют псевдонимам узлов. |
| Запрос GQL не возвращает строк | Убедитесь, что значения фильтров присутствуют в выбранном снимке, и проверьте фильтрацию по снимкам. |
publish() завершается с ошибкой: доступ запрещён |
Убедитесь, что у вас есть роль оператора безопасности, администратора безопасности или глобального администратора. |
Создание с использованием искусственного интеллекта
| Симптом | Вероятно, причина и исправление |
|---|---|
@sentinel /graph-authoring ничего не делает |
Убедитесь, что расширения GitHub Copilot и Jupyter установлены и включены, и у вас оформлен тарифный план Copilot Business или Copilot Enterprise. |
| Созданный код ссылается на недостающую таблицу | Подтвердите настройку соединителя и убедитесь, что таблица отображается в обозревателе озера данных. |
Планирование заданий
| Симптом | Вероятно, причина и исправление |
|---|---|
| Изменения локальной записной книжки не отражаются в задании | Скачайте блокнот задания на панели «Graphs», измените его, затем нажмите Изменить задание>Отправить. |
| Материализованный граф исчез | Графики по запросу имеют 30-дневный срок хранения. Запланируйте повторяющееся задание или запустите новую сборку. |
Связанные материалы
- Обзор настраиваемых диаграмм в Microsoft Sentinel
- Начало работы с пользовательскими графиками
- Создание пользовательских графов с поддержкой искусственного интеллекта
- Справочник по поставщику графов Microsoft Sentinel
- Справочник по GQL для пользовательского графа Sentinel
- REST API Graph для настраиваемых графов
- Подключиться к озеру данных Microsoft Sentinel
- Запуск записных книжек в озере данных Microsoft Sentinel
- Опубликуйте агент Security Copilot или аналитическое решение в Security Store
- Microsoft Partner Center