Перейти к основному содержимому

Слушатель вебхуков Microsoft Graph

Платформа шлюза msgraph_webhook представляет собой входящий обработчик событий. Через неё VibeOS получает уведомления об изменениях от Microsoft Graph — «встреча Teams завершена», «в чате появилось новое сообщение», «событие календаря обновлено». В отличие от платформы teams (бота, с которым общаются пользователи), этот механизм предназначен для того, чтобы M365 сообщала VibeOS о произошедших событиях, а не для общения с людьми.

Сейчас основным потребителем является конвейер обработки сводок встреч Teams: Graph уведомляет, когда для встречи появляется стенограмма, конвейер загружает её, и VibeOS публикует сводку обратно в Teams. Другие ресурсы Graph (/chats/.../messages, /users/.../events) используют тот же слушатель — конвейеры-потребители появятся с собственными PR.

Предварительные требования​

  • Учётные данные приложения Microsoft Graph — Зарегистрируйте приложение Microsoft Graph
  • Публичный HTTPS-URL, доступный Microsoft Graph (Graph не вызывает частные конечные точки). Для тестирования подходит туннель разработчика; для продакшена нужен реальный домен с валидным сертификатом.
  • Надёжный общий секрет для использования в качестве значения clientState. Сгенерируйте с помощью openssl rand -hex 32 и поместите в ~/.vibeos/.env как MSGRAPH_WEBHOOK_CLIENT_STATE.

Быстрый старт​

Минимальный ~/.vibeos/config.yaml:

platforms:
msgraph_webhook:
enabled: true
extra:
host: 127.0.0.1
port: 8646
client_state: "замените-на-надёжный-секрет"
accepted_resources:
- "communications/onlineMeetings"

Или через переменные окружения в ~/.vibeos/.env (автоматически объединяются при запуске):

MSGRAPH_WEBHOOK_ENABLED=true
MSGRAPH_WEBHOOK_PORT=8646
MSGRAPH_WEBHOOK_CLIENT_STATE=<сгенерируйте-с-openssl-rand-hex-32>
MSGRAPH_WEBHOOK_ACCEPTED_RESOURCES=communications/onlineMeetings

Примечание: хост привязки считывается из extra.host в config.yaml (см. пример выше); переменной окружения MSGRAPH_WEBHOOK_HOST не существует.

Запустите шлюз: vibeos gateway run. Слушатель предоставляет:

  • POST /msgraph/webhook — уведомления об изменениях от Graph
  • GET /msgraph/webhook?validationToken=... — проверка подписки Graph (квитирование)
  • GET /health — проверка готовности со счётчиками принятых/дублированных уведомлений

Опубликуйте слушатель публично (обратный прокси, туннель разработчика, ingress). Ваш URL для уведомлений в подписках Graph — это ваш публичный HTTPS-источник, за которым следует /msgraph/webhook:

https://ops.example.com/msgraph/webhook

Конфигурация​

Все настройки находятся в platforms.msgraph_webhook.extra:

ПараметрПо умолчаниюОписание
host0.0.0.0Адрес привязки HTTP-слушателя. Привязка не к loopback требует allowed_source_cidrs; loopback (127.0.0.1 / ::1) — самый простой вариант для туннеля разработчика / обратного прокси.
port8646Порт привязки.
webhook_path/msgraph/webhookПуть URL, на который Graph отправляет POST-запросы.
health_path/healthКонечная точка готовности.
client_state—Общий секрет, который Graph повторяет в каждом уведомлении. Сравнивается с помощью hmac.compare_digest — сгенерируйте с openssl rand -hex 32.
accepted_resources[] (принимать все)Белый список путей/шаблонов ресурсов Graph. Замыкающий * означает совпадение по префиксу. Начальный / допускается. Пример: ["communications/onlineMeetings", "chats/*/messages"].
max_seen_receipts5000Размер кэша дедупликации для ID уведомлений. Самые старые записи удаляются при достижении лимита.
allowed_source_cidrs[]Обязательно для привязки не к loopback. Оставляйте пустым только если слушатель привязан к loopback и находится за локальным туннелем / обратным прокси.

Большинство параметров также имеют эквивалентную переменную окружения (MSGRAPH_WEBHOOK_*), которая объединяется с конфигурацией при запуске шлюза (исключение — host, он доступен только в конфиге — см. примечание выше) — смотрите справочник по переменным окружения.

Усиление безопасности​

clientState — основная проверка подлинности​

Каждое уведомление Graph включает строку clientState, с которой была зарегистрирована ваша подписка. Слушатель отклоняет любое уведомление, чей clientState не совпадает, используя безопасное по времени сравнение. Это документированный механизм Microsoft — относитесь к этому значению как к надёжному общему секрету.

Если client_state не задан, слушатель отказывается запускаться.

Белый список IP-адресов источников (продакшен-развёртывания)​

В продакшене ограничьте слушатель опубликованными Microsoft диапазонами IP-адресов источников вебхуков Graph. Microsoft документирует диапазоны исходящего трафика в веб-сервисе IP-адресов и URL Office 365. Настройте их так:

platforms:
msgraph_webhook:
enabled: true
extra:
host: 0.0.0.0
client_state: "..."
allowed_source_cidrs:
- "52.96.0.0/14"
- "52.104.0.0/14"
# ...добавьте текущие диапазоны исходящего трафика категорий "Common" + "Teams" Microsoft 365

Или как переменную окружения:

MSGRAPH_WEBHOOK_ALLOWED_SOURCE_CIDRS="52.96.0.0/14,52.104.0.0/14"

Привязка к не-loopback хосту, такому как 0.0.0.0, :: или LAN-IP, без allowed_source_cidrs будет отклонена при запуске. Если вы используете туннель разработчика или обратный прокси на той же машине, привяжите VibeOS к 127.0.0.1 или ::1 и оставьте белый список пустым. Некорректные строки CIDR логируют предупреждение и игнорируются. Пересматривайте список IP-адресов Microsoft ежеквартально — он меняется.

Терминация HTTPS​

Слушатель работает по обычному HTTP. Завершайте TLS на вашем обратном прокси (Caddy, Nginx, Cloudflare Tunnel, AWS ALB) и проксируйте трафик к слушателю по локальной сети. Graph отказывается доставлять уведомления на конечные точки, не использующие HTTPS, поэтому незашифрованный трафик от самого Graph до вас не дойдёт.

Гигиена ответов​

При успехе слушатель возвращает 202 Accepted с пустым телом — внутренние счётчики не попадают в ответ по сети. Операторы могут наблюдать счётчики через /health, который защищён теми же правилами IP-адресов, что и путь вебхука.

Таблица кодов состояния:

РезультатСтатус
Уведомление(я) приняты или дедуплицированы202
Проверка подписки (GET с validationToken)200 (возвращает токен)
Все элементы в пакете не прошли проверку clientState403
Некорректный JSON / отсутствует массив value / неизвестный ресурс400
IP-адрес источника не в белом списке403
Простой GET без validationToken400

Устранение неполадок​

ПроблемаЧто проверить
Не удаётся проверить подписку GraphПубличный URL доступен, путь /msgraph/webhook совпадает, GET с validationToken возвращает токен дословно как text/plain в течение 10 секунд.
Уведомления POST-ятся, но ничего не обрабатываетсяclient_state совпадает с тем, что было указано при регистрации подписки. Заново выполните openssl rand -hex 32 и создайте новую подписку, если значение изменилось. Проверьте, что accepted_resources включает путь ресурса, который отправляет Graph.
Каждое уведомление возвращает 403Несовпадение clientState (подделка или подписка зарегистрирована с другим значением). Пересоздайте подписку с помощью vibeos teams-pipeline subscribe --client-state "$MSGRAPH_WEBHOOK_CLIENT_STATE" ... (поставляется с PR для конвейера времени выполнения).
Слушатель отказывается запускаться на 0.0.0.0Установите allowed_source_cidrs на текущие диапазоны исходящего трафика вебхуков Microsoft или привяжите VibeOS к 127.0.0.1 / ::1 за туннелем или обратным прокси.
Слушатель запускается, но curl http://localhost:8646/health зависаетКонфликт привязки порта. Проверьте ss -tlnp | grep 8646 и измените port: при необходимости.
Реальные запросы Graph от Microsoft получают 403Белый список IP-адресов источников слишком узок. Расширьте список, включив текущие диапазоны исходящего трафика Microsoft. Если вы всё ещё тестируете путь через туннель, привяжите VibeOS к loopback и позвольте туннелю обрабатывать публичный доступ.

Связанные документы​