Слушатель вебхуков Microsoft Graph
Платформа шлюза msgraph_webhook — это предстоящий слушатель событий. Таким образом Hermes получает уведомления об изменениях от Microsoft Graph — «встреча Teams завершилась», «в этот чат пришло новое сообщение», «календарь этого события был обновлено». В отличие от платформы «команды» (которая является чат-ботом, мои пользователи пишут), этот слушатель — M365 сообщает Гермесу о том, что произошло, а не человек.
Сейчас основным потребителем является конвейерный конвейер встреч Teams: Graph уведомляет, когда встреча создает стенограмму, конвейер загружает ее, и Hermes публикует краткое содержание обратно в Teams. Другие ресурсы Graph (/chats/.../messages, /users/.../events) используют тот же слушатель — пользователь конвейера появляется со своими собственными PR.
Предварительные требования
- Учётные данные приложения Microsoft Graph — Зарегистрируйте приложение Microsoft Graph
- Публичный URL-адрес HTTPS, доступный Microsoft Graph (график не содержит частных конечных точек). Туннель для разработки подойдёт для тестирования; для продакшена нужен реальный домен с действительным сертификатом.
- Сильный общий секрет для использования в качестве значения clientState. Сгенерируйте с помощью
openssl rand -hex 32и поместите в~/.hermes/.envкакMSGRAPH_WEBHOOK_CLIENT_STATE.
Быстрый старт
Минимальный ~/.hermes/config.yaml:
platforms:
msgraph_webhook:
enabled: true
extra:
port: 8646
client_state: "замените-на-сильный-секрет"
accepted_resources:
- "communications/onlineMeetings"
Или через переменные окружения в ~/.hermes/.env (автоматически объединяются при запуске):
MSGRAPH_WEBHOOK_ENABLED=true
MSGRAPH_WEBHOOK_PORT=8646
MSGRAPH_WEBHOOK_CLIENT_STATE=<сгенерируйте-с-openssl-rand-hex-32>
MSGRAPH_WEBHOOK_ACCEPTED_RESOURCES=communications/onlineMeetings
Запустите шлюз: «Запуск шлюза Гермеса». Слушатель обеспечивает:
POST /msgraph/webhook— уведомления об изменениях от GraphGET /msgraph/webhook?validationToken=...— рукопожатие проверки подписки GraphGET /health— проверка помощи со счётчиками привлеченных/дублирующих протоколов.
Откройте слушатель публично (обратный прокси, туннель для разработки, вход). Ваш URL-адрес для подписки на Graph — это ваш публичный HTTPS-источник, за которым следует /msgraph/webhook:
https://ops.example.com/msgraph/webhook
Конфигурация
Все настройки находятся в platforms.msgraph_webhook.extra:
| Настройка | По умолчанию | Описание |
|---|---|---|
хозяин |
0.0.0.0 |
Адрес привязки HTTP-слушателя. |
порт |
8646 |
Порт привязки. |
webhook_path |
/msgraph/webhook |
URL-путь, по этому графику отправляются POST-запросы. |
путь_здоровья |
/здоровье |
Конечная точка помощи. |
client_state |
— | Общий секрет, который график повторяется в каждом уведомлении. Сравнивается с помощью hmac.compare_digest — сгенерируйте с помощью openssl rand -hex 32. |
accepted_resources |
[] (принимать все) |
Белый список путей/шаблонов ресурсов График. Завершающий * действует как префиксное совпадение. Начальный / лампы. Пример: ["communication/onlineMeetings", "chats/*/messages"]. |
max_seen_receipts |
5000 |
Размер кэша дедупликации для идентификатора идентификатора. Самые старые записи удаляются при использовании лимита. |
allowed_source_cidrs |
[] (разрешить все) |
Опциональный белый список исходных IP. См. ниже. |
Каждая настройка также имеет эквивалентную переменную окружность (MSGRAPH_WEBHOOK_*), которая занимается конфигурацией при запуске шлюза — см. справочник заключения окружения.
Усиление безопасности
clientState — базовая проверка аутентификации
График включает код clientState, который зарегистрировала вашу подписку. Слушатель отклоняет любое)., чей clientState не соответствует, используя безопасное сравнение по времени. Этот задокументированный механизм Microsoft — относится к последствиям как к сильному общему секрету.
Если client_state не задан, слушатель принимает любой корректно сформированный POST. Не запускайте без него в продакшене.
Белый список исходных IP (продакшен-развёртывания)
Для продакшена ограничьте слушателя опубликованными диапазонами IP-адресов источников вебхуков График от Microsoft. Microsoft документирует диапазон исходящего трафика в веб-сервисе [IP-адрес и URL-адрес Office 365] (https://learn.microsoft.com/en-us/microsoft-365/enterprise/urls-and-ip-address-ranges). Настроить их как:
platforms:
msgraph_webhook:
enabled: true
extra:
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"
Пустой белый список = принять откуда угодно (по умолчанию; сохранить рабочие стенки туннелей для разработки). Неверные строки CIDR записывают предупреждения в регистрацию и отключаются. Проверяйте список IP Microsoft ежеквартально — он меняется.
Завершение HTTPS
Слушатель использует обычный HTTP. Завершите TLS на своем обратном прокси (Caddy, Nginx, Cloudflare Tunnel, AWS ALB) и проксируйте слушателя в локальной сети. Граф отказывается предоставлять данные на конечные точки, не использующие HTTPS, поэтому нет пути, по которому незашифрованный трафик от Графа мог бы вас препятствовать.
Гигиена атаки
При успехе слушатель получает 202 Accepted с пустым голосом — внутренние счётчики остаются вне ответа по проводу. Операторы могут наблюдать счётчики через /health.
Таблица кодов статусов:
| Результат | Статус |
|---|---|
| Уведомление(я) осуществлено или дедуплицировано | 202 |
Рукопожатие проверок (GET с validationToken) |
200 (возвращает токен) |
| Каждый элемент в пакете не прошёл clientState | 403 |
Некорректный JSON / отсутствует массив value / неизвестный ресурс |
400 |
| Исходный IP не в белом списке | 403 |
Простой GET без validationToken |
400 |
Устранение неполадок
| Проблема | Что проверить |
|---|---|
| График проверки подписки не удаётся | Публичный URL-адрес доступен, путь /msgraph/webhook соответствует, GET с validationToken возвращает токен дословно как text/plain в течение 10 секунд. |
| ПОСТ-уведомления приходят, но ничего не обрабатывается | client_state соответствует тем, которые вы зарегистрировали в подписке. Запустите заново openssl rand -hex 32 и создайте новую подписку, если значение изменилось. Проверьте, что accepted_resources включает путь ресурса, который отправляет Graph. |
| выдает 403 | Несовпадение clientState (подделка или подписка зарегистрирована с другим значением). Пересоздайте подписку с помощью hermes groups-pipeline subscribe --client-state "$MSGRAPH_WEBHOOK_CLIENT_STATE"... (поставляется с PR-окружением выполнения конвейера). |
Слушатель включен, но curl http://localhost:8646/health зависит |
Конфликт привязки порта. Проверьте ss -tlnp \| grep 8646 и при необходимости замените port:. |
| Реальные запросы График от Microsoft получают 403 | Белый список исходных IP слишком узок. Временно удалите allowed_source_cidrs, убедитесь, что трафик проходит, затем расширьте список, включая текущий диапазон исходящего трафика Microsoft. |
Связанные документы
- Зарегистрируйте приложение Microsoft Graph — предварительное требование регистрации приложения Azure.
- Переменные окружения → Microsoft Graph — полный список окружения
- Настройка бота Microsoft Teams — другая платформа, авторизованная пользовательская связь с Hermes в Teams.