Слушатель Webhook Microsoft Graph
Платформа gateway msgraph_webhook — это входящий слушатель событий. Так Hermes получает уведомления об изменениях от Microsoft Graph — «собрание Teams завершилось», «новое сообщение поступило в этот чат», «это событие календаря было обновлено». Отличается от платформы teams (которая является чат-ботом, которому пользователи пишут) — здесь M365 сообщает Hermes о произошедшем, а не человек.
Сейчас основным потребителем является конвейер саммари собраний: Graph уведомляет, когда собрание создаёт транскрипт, конвейер получает его, и Hermes публикует саммари обратно в Teams. Другие ресурсы Graph (/chats/.../messages, /users/.../events) используют тот же слушатель — потребители конвейера поступают с собственными PR.
Предварительные требования
-
Учётные данные приложения Microsoft Graph — Зарегистрируйте приложение Microsoft Graph
-
Публичный HTTPS-URL, который может достичь Microsoft Graph (Graph не вызывает приватные конечные точки). Для тестирования подходит dev-туннель; для продакшена нужен реальный домен с действительным сертификатом.
-
Надёжный общий секрет для использования в качестве значения
clientState. Сгенерируйте с помощьюopenssl rand -hex 32и поместите его в~/.hermes/.envкакMSGRAPH_WEBHOOK_CLIENT_STATE.
Быстрый старт
Минимальный ~/.hermes/config.yaml:
platforms:
msgraph_webhook:
enabled: true
extra:
port: 8646
client_state: "replace-with-a-strong-secret"
accepted_resources:
- "communications/onlineMeetings"
Или через переменные окружения в ~/.hermes/.env (автоматически объединяются при запуске):
MSGRAPH_WEBHOOK_ENABLED=true
MSGRAPH_WEBHOOK_PORT=8646
MSGRAPH_WEBHOOK_CLIENT_STATE=<generate-with-openssl-rand-hex-32>
MSGRAPH_WEBHOOK_ACCEPTED_RESOURCES=communications/onlineMeetings
Запустите gateway: hermes gateway run. Слушатель предоставляет:
-
POST /msgraph/webhook— уведомления об изменениях от Graph -
GET /msgraph/webhook?validationToken=...— подтверждение подписки Graph -
GET /health— проба готовности с счётчиками принятых/дубликатов
Откройте слушатель публично (обратный прокси, dev-туннель, ingress). Ваш URL уведомлений для подписок Graph — это ваш публичный HTTPS-источник, за которым следует /msgraph/webhook:
https://ops.example.com/msgraph/webhook
Настройка
Все настройки размещаются в platforms.msgraph_webhook.extra:
| Параметр | По умолчанию | Описание |
|---|---|---|
host |
0.0.0.0 |
Адрес привязки для HTTP-слушателя. |
port |
8646 |
Порт привязки. |
webhook_path |
/msgraph/webhook |
URL-путь, на который Graph отправляет POST. |
health_path |
/health |
Конечная точка готовности. |
client_state |
— | Общий секрет, который Graph возвращает в каждом уведомлении. Сравнивается с помощью hmac.compare_digest — сгенерируйте с помощью openssl rand -hex 32. |
accepted_resources |
[] (accept all) |
Белый список путей/шаблонов ресурсов Graph. Завершающий * действует как префиксное совпадение. Начальный / допускается. Пример: ["communications/onlineMeetings", "chats/*/messages"]. |
max_seen_receipts |
5000 |
Размер кэша дедупликации для ID уведомлений. Самые старые записи вытесняются при достижении лимита. |
allowed_source_cidrs |
[] (allow all) |
Необязательный белый список IP-источников. См. ниже. |
Каждый параметр также имеет эквивалентную переменную окружения (MSGRAPH_WEBHOOK_*), которая объединяется с конфигурацией при запуске gateway — см. справочник переменных окружения.
Усиление безопасности
clientState — основная проверка аутентификации
Каждое уведомление Graph включает строку clientState, с которой была зарегистрирована ваша подписка. Слушатель отклоняет любое уведомление, чей clientState не совпадает, используя безопасное по времени сравнение. Это задокументированный механизм Microsoft — рассматривайте значение как надёжный общий секрет.
Если client_state не задан, слушатель принимает каждый правильно сформированный POST. Не запускайте без него в продакшене.
Белый список IP-источников (продакшн-развёртывания)
Для продакшена ограничьте слушатель опубликованными Microsoft диапазонами IP-источников вебхуков Graph. Microsoft документирует диапазоны исходящих адресов в веб-сервисе IP-адресов и URL Office 365. Настройте их как:
platforms:
msgraph_webhook:
enabled: true
extra:
client_state: "..."
allowed_source_cidrs:
- "52.96.0.0/14"
- "52.104.0.0/14"
# ...add the current Microsoft 365 "Common" + "Teams" category egress ranges
Или как переменную окружения:
MSGRAPH_WEBHOOK_ALLOWED_SOURCE_CIDRS="52.96.0.0/14,52.104.0.0/14"
Пустой белый список = принимать отовсюду (по умолчанию; сохраняет рабочие процессы dev-туннеля). Недопустимые строки CIDR логируют предупреждение и игнорируются. Проверяйте список IP Microsoft ежеквартально — он меняется.
Завершение HTTPS
Слушатель использует обычный HTTP. Завершайте TLS на вашем обратном прокси (Caddy, Nginx, Cloudflare Tunnel, AWS ALB) и проксируйте к слушателю через локальную сеть. Graph отказывается доставлять на не-HTTPS конечные точки, поэтому нет пути для незашифрованного трафика достичь вас от самого Graph.
Гигиена ответов
При успехе слушатель возвращает 202 Accepted с пустым телом — внутренние счётчики не попадают в ответ. Операторы могут наблюдать счётчики через /health.
Таблица кодов состояния:
| Результат | Статус |
|---|---|
| Уведомление(я) приняты или дублированы | 202 |
Подтверждение связи (GET с validationToken) |
200 (echoes the token) |
| Все элементы в пакете не прошли проверку clientState | 403 |
Неправильный JSON / отсутствует массив value / неизвестный ресурс |
400 |
| IP-источник не в белом списке | 403 |
Пустой GET без validationToken |
400 |
Диагностика проблем
| Проблема | Что проверить |
|---|---|
| Ошибка подтверждения подписки Graph | Публичный URL доступен, путь /msgraph/webhook совпадает, GET с validationToken возвращает токен дословно как text/plain в течение 10 секунд. |
| Уведомления POST, но ничего не принимается | client_state совпадает с тем, что вы зарегистрировали при подписке. Запустите заново openssl rand -hex 32 и создайте новую подписку, если значение изменилось. Проверьте, что accepted_resources включает путь ресурса, который отправляет Graph. |
| Каждое уведомление получает 403 | Несоответствие clientState (подделка или подписка зарегистрирована с другим значением). Пересоздайте подписку с помощью hermes teams-pipeline subscribe --client-state "$MSGRAPH_WEBHOOK_CLIENT_STATE" ... (поставляется с PR конвейера). |
Слушатель запускается, но curl http://localhost:8646/health зависает |
Конфликт привязки порта. Проверьте ss -tlnp \| grep 8646 и измените port:, если необходимо. |
| Реальные запросы Graph от Microsoft получают 403 | Белый список IP-источников слишком узкий. Временно удалите allowed_source_cidrs, подтвердите прохождение трафика, затем расширьте список, включив текущие диапазоны исходящих адресов Microsoft. |
Связанные документы
-
Регистрация приложения Microsoft Graph — предварительное требование регистрации приложения Azure
-
Переменные окружения → Microsoft Graph — полный список переменных окружения
-
Настройка бота Microsoft Teams — другая платформа, которая позволяет пользователям общаться с Hermes в Teams