Pular para o conteúdo principal

Documentação oficial desta página · v0.20.6

Webhook do Microsoft Graph

A plataforma de gateway msgraph_webhook é um ouvinte de eventos de entrada. É por ela que o Hermes recebe notificações de mudança do Microsoft Graph — "uma reunião do Teams terminou", "chegou uma mensagem nova neste chat", "este evento de calendário foi atualizado". É diferente da plataforma teams (que é um bot de chat para as pessoas conversarem): aqui é o M365 avisando o Hermes que algo aconteceu, não uma pessoa.

Hoje o consumidor principal é o pipeline de resumo de reuniões do Teams: o Graph avisa quando uma reunião gera uma transcrição, o pipeline busca essa transcrição e o Hermes publica um resumo de volta no Teams. Outros recursos do Graph (/chats/.../messages, /users/.../events) usam o mesmo ouvinte — os consumidores do pipeline chegam em PRs próprios.

Pré-requisitos​

  • Credenciais de aplicativo do Microsoft Graph — Registrar um aplicativo do Microsoft Graph
  • Uma URL HTTPS pública que o Microsoft Graph consiga alcançar (o Graph não chama endpoints privados). Um túnel de desenvolvimento serve para testes; em produção você precisa de um domínio real com certificado válido.
  • Um segredo compartilhado forte para usar como valor de clientState. Gere com openssl rand -hex 32 e coloque em ~/.hermes/.env como MSGRAPH_WEBHOOK_CLIENT_STATE.

Início rápido​

~/.hermes/config.yaml mínimo:

platforms:
msgraph_webhook:
enabled: true
extra:
host: 127.0.0.1
port: 8646
client_state: "troque-por-um-segredo-forte"
accepted_resources:
- "communications/onlineMeetings"

Ou por variáveis de ambiente em ~/.hermes/.env (mescladas automaticamente na inicialização):

MSGRAPH_WEBHOOK_ENABLED=true
MSGRAPH_WEBHOOK_PORT=8646
MSGRAPH_WEBHOOK_CLIENT_STATE=<gere-com-openssl-rand-hex-32>
MSGRAPH_WEBHOOK_ACCEPTED_RESOURCES=communications/onlineMeetings

Atenção: o host de bind é lido de extra.host no config.yaml (veja o exemplo acima); não existe variável de ambiente MSGRAPH_WEBHOOK_HOST para sobrescrever.

Inicie o gateway: hermes gateway run. O ouvinte expõe:

  • POST /msgraph/webhook — notificações de mudança vindas do Graph
  • GET /msgraph/webhook?validationToken=... — handshake de validação da assinatura do Graph
  • GET /health — sonda de prontidão com contadores de aceitos/duplicados

Exponha o ouvinte publicamente (proxy reverso, túnel de desenvolvimento, ingress). A URL de notificação para as assinaturas do Graph é a sua origem HTTPS pública seguida de /msgraph/webhook:

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

Configuração​

Todos os ajustes ficam sob platforms.msgraph_webhook.extra:

AjustePadrãoDescrição
hostnão definido (pilha dupla: todas as interfaces, IPv4+IPv6)Endereço de bind do ouvinte HTTP. Binds fora de loopback exigem allowed_source_cidrs; loopback (127.0.0.1 / ::1) é a configuração mais fácil com túnel de desenvolvimento / proxy reverso.
port8646Porta de bind.
webhook_path/msgraph/webhookCaminho de URL para onde o Graph faz POST.
health_path/healthEndpoint de prontidão.
client_state—Segredo compartilhado que o Graph devolve em toda notificação. Comparado com hmac.compare_digest — gere com openssl rand -hex 32.
accepted_resources[] (aceita tudo)Lista de permissão de caminhos/padrões de recurso do Graph. Um * no fim funciona como casamento de prefixo. Uma / no início é tolerada. Exemplo: ["communications/onlineMeetings", "chats/*/messages"].
max_seen_receipts5000Tamanho do cache de deduplicação dos IDs de notificação. As entradas mais antigas são descartadas quando o limite é atingido.
allowed_source_cidrs[]Obrigatório para binds fora de loopback. Deixe vazio só quando o ouvinte estiver ligado ao loopback e atrás de um túnel local / proxy reverso.

Quase todos os ajustes também têm uma variável de ambiente equivalente (MSGRAPH_WEBHOOK_*) que é mesclada na configuração na inicialização do gateway (a exceção é host, que só existe na configuração — veja a observação acima) — consulte a referência de variáveis de ambiente.

Reforço de segurança​

O clientState é a verificação de autenticação principal​

Toda notificação do Graph inclui a string clientState registrada com a sua assinatura. O ouvinte rejeita qualquer notificação cujo clientState não bata, usando comparação de tempo constante. Esse é o mecanismo documentado pela Microsoft — trate o valor como um segredo compartilhado forte.

Se client_state não estiver definido, o ouvinte se recusa a iniciar.

Lista de permissão de IP de origem (implantações em produção)​

Em produção, restrinja o ouvinte às faixas de IP de origem dos webhooks do Graph publicadas pela Microsoft. A Microsoft documenta as faixas de saída no serviço web de endereços IP e URLs do Office 365. Configure assim:

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"
# ...acrescente as faixas de saída atuais das categorias "Common" + "Teams" do Microsoft 365

Ou como variável de ambiente:

MSGRAPH_WEBHOOK_ALLOWED_SOURCE_CIDRS="52.96.0.0/14,52.104.0.0/14"

Ligar a um host fora de loopback, como 0.0.0.0, :: ou um IP de rede local, sem allowed_source_cidrs é recusado na inicialização. Se você usa um túnel de desenvolvimento ou proxy reverso na mesma máquina, ligue o Hermes a 127.0.0.1 ou ::1 e deixe a lista de permissão vazia. Strings de CIDR inválidas geram um aviso no log e são ignoradas. Revise a lista de IPs da Microsoft a cada trimestre — ela muda.

Terminação HTTPS​

O ouvinte fala HTTP puro. Faça a terminação TLS no seu proxy reverso (Caddy, Nginx, Cloudflare Tunnel, AWS ALB) e encaminhe para o ouvinte pela rede local. O Graph se recusa a entregar em endpoints que não sejam HTTPS, então não há caminho para tráfego sem criptografia chegar até você vindo do próprio Graph.

Higiene das respostas​

Em caso de sucesso, o ouvinte retorna 202 Accepted com corpo vazio — os contadores internos ficam fora da resposta. Os operadores acompanham as contagens pelo /health, protegido pelas mesmas regras de IP de origem do caminho do webhook.

Tabela de códigos de status:

ResultadoStatus
Notificação(ões) aceita(s) ou deduplicada(s)202
Handshake de validação (GET com validationToken)200 (devolve o token)
Todos os itens do lote falharam no clientState403
JSON malformado / array value ausente / recurso desconhecido400
IP de origem fora da lista de permissão403
GET simples, sem validationToken400

Solução de problemas​

ProblemaO que verificar
A validação da assinatura do Graph falhaA URL pública está acessível, o caminho /msgraph/webhook bate e o GET com validationToken devolve o token literalmente como text/plain em até 10 segundos.
As notificações chegam via POST, mas nada é ingeridoO client_state bate com o que você registrou na assinatura. Rode openssl rand -hex 32 de novo e crie uma assinatura nova se o valor divergiu. Confira se accepted_resources inclui o caminho de recurso que o Graph está enviando.
Toda notificação retorna 403clientState divergente (forjado, ou assinatura registrada com outro valor). Recrie a assinatura com hermes teams-pipeline subscribe --client-state "$MSGRAPH_WEBHOOK_CLIENT_STATE" ... (vem com o PR do runtime do pipeline).
O ouvinte se recusa a iniciar em 0.0.0.0Defina allowed_source_cidrs com as faixas de saída de webhook atuais da Microsoft, ou ligue o Hermes a 127.0.0.1 / ::1 atrás do seu túnel ou proxy reverso.
O ouvinte inicia, mas curl http://localhost:8646/health travaConflito de porta. Verifique com ss -tlnp | grep 8646 e mude o port: se precisar.
Requisições reais do Graph vindas da Microsoft levam 403A lista de permissão de IP de origem está estreita demais. Amplie-a para incluir as faixas de saída atuais da Microsoft. Se você ainda está validando o caminho do túnel, ligue o Hermes ao loopback e deixe o túnel cuidar da exposição pública.