Pular para o conteúdo principal

Webhooks

Dois fluxos distintos:

  1. Webhooks de saída — o RuleForge envia eventos para uma URL sua quando algo acontece (validação termina, versão publica, etc.). Endpoints /platform/organizations/{id}/webhooks/*.
  2. Webhooks de entrada — provedores Git (GitHub, GitLab, Gitea) enviam push events para o RuleForge, que dispara o auto-import de bindings. Endpoints /webhooks/git/*.

Outbound — tabela de endpoints

MétodoCaminhoPermissão
POST/platform/organizations/{organization_id}/webhooksintegration:manage
GET/platform/organizations/{organization_id}/webhooksSessão
GET/platform/organizations/{organization_id}/webhooks/{webhook_id}Sessão
PATCH/platform/organizations/{organization_id}/webhooks/{webhook_id}integration:manage
DELETE/platform/organizations/{organization_id}/webhooks/{webhook_id}integration:manage
GET/platform/organizations/{organization_id}/webhooks/{webhook_id}/deliveriesSessão
POST/platform/organizations/{organization_id}/webhooks/{webhook_id}/testintegration:manage

Inbound — tabela de endpoints

MétodoCaminhoAuth
POST/webhooks/git/githubHMAC SHA-256
POST/webhooks/git/gitlabToken secreto
POST/webhooks/git/giteaHMAC SHA-256

Outbound

POST /.../webhooks

Registra um webhook de saída.

Request body (WebhookCreateRequest):

{
"url": "https://webhooks.acme.com/ruleforge",
"events": [
"validation.completed",
"regression.failed",
"version.published"
],
"secret": "a-secret-string-with-16-plus-chars",
"description": "Canal do time de SOC"
}
  • url — 8–2048 chars, deve ser http:// ou https://. Por padrão IPs privados/loopback são bloqueados (controlado pelo operador via NATIVE_WAZUH_WEBHOOK_BLOCK_PRIVATE_NETWORKS).
  • events[] — pelo menos 1 evento, todos devem ser valores válidos. Ver eventos disponíveis.
  • secret — 16–256 chars. Usado para assinar o payload com HMAC SHA-256 no header X-RuleForge-Signature.

Response 201 (WebhookRecord).

Eventos suportados

validation.completed
logtest.completed
regression.completed
regression.passed
regression.failed
review.created
review.approved
review.changes_requested
review.rejected
version.created
version.published
publish.failed
feedback.created
api_key.created
api_key.revoked
api.quota.warning

Descrição detalhada em Eventos de webhook.

Formato do payload enviado

Cada entrega é um POST ao seu endpoint:

POST /ruleforge HTTP/1.1
Host: webhooks.acme.com
Content-Type: application/json
X-RuleForge-Event: validation.completed
X-RuleForge-Delivery: 8e1f2c3a…
X-RuleForge-Signature: sha256=abc123…
User-Agent: RuleForge-Webhooks/1.0

{
"event": "validation.completed",
"delivery_id": "8e1f2c3a…",
"organization_id": "org_...",
"resource_type": "analysis",
"resource_id": null,
"payload": {
"ok": true,
"diagnostic_count": 0,
"total_rules": 8621,
"total_decoders": 623
},
"occurred_at": "2026-04-24T15:30:00Z"
}

Verificação da assinatura (exemplo Python):

import hmac, hashlib

def verify(body: bytes, signature: str, secret: str) -> bool:
expected = "sha256=" + hmac.new(secret.encode(), body, hashlib.sha256).hexdigest()
return hmac.compare_digest(expected, signature)

Expectativa de resposta

  • Seu endpoint deve responder 2xx em até 10 s (NATIVE_WAZUH_WEBHOOK_TIMEOUT_SECONDS, padrão 10).
  • Qualquer 4xx/5xx é considerado falha → RuleForge faz retry com backoff exponencial.
  • Se seu serviço cair, failure_count sobe; após várias falhas seguidas o webhook pode ser marcado como is_active=false pelo operador.

GET /.../webhooks

Lista webhooks.

Response 200: array de WebhookRecord:

{
"id": "wh_...",
"organization_id": "org_...",
"url": "https://webhooks.acme.com/ruleforge",
"target_host": "webhooks.acme.com",
"destination_type": "custom",
"events": ["validation.completed"],
"description": "Canal do SOC",
"is_active": true,
"delivery_count": 1423,
"failure_count": 12,
"last_delivery_at": "2026-04-24T15:30:00Z",
"secret_masked": "abc***xyz",
"created_at": "...",
"updated_at": "..."
}

PATCH /.../webhooks/{id}

Atualização parcial. Para trocar o secret, envie secret no body; sem envio preserva o atual.

DELETE /.../webhooks/{id}

Remove o webhook. Response 204.

GET /.../webhooks/{id}/deliveries

Histórico de entregas (últimas N).

Response 200 (WebhookDeliveryRecord[]):

[
{
"id": "del_...",
"webhook_id": "wh_...",
"event_type": "validation.completed",
"status": "delivered",
"response_status": 200,
"duration_ms": 412.3,
"response_snippet": "{\"ok\":true}",
"error_message": null,
"attempt_count": 1,
"next_retry_at": null,
"delivered_at": "2026-04-24T15:30:01Z",
"created_at": "2026-04-24T15:30:00Z"
},
{
"id": "del_...",
"webhook_id": "wh_...",
"event_type": "version.published",
"status": "failed",
"response_status": 502,
"duration_ms": 8932.1,
"error_message": "Bad Gateway",
"attempt_count": 3,
"next_retry_at": "2026-04-24T15:40:00Z",
"created_at": "2026-04-24T15:20:00Z"
}
]

POST /.../webhooks/{id}/test

Dispara um delivery de teste com payload sintético. Útil para validar que seu endpoint está certo sem esperar um evento real.

Request body (opcional): { "event_type": "validation.completed" }. Default é validation.completed.

Response 200:

{
"delivered": true,
"response_status": 200,
"duration_ms": 412.3
}

Inbound (Git)

Endpoints que recebem push events dos provedores Git. Dispara auto-import de todos os bindings que apontam para repository@branch.

Não chame estes endpoints manualmente — configure como webhook nas plataformas Git correspondentes.

POST /webhooks/git/github

Headers esperados:

Content-Type: application/json
X-GitHub-Event: push
X-GitHub-Delivery: <uuid>
X-Hub-Signature-256: sha256=<hmac>

Payload: formato nativo do GitHub Push Event. Campos lidos:

  • ref (precisa começar com refs/heads/).
  • repository.full_name.
  • after (commit SHA).
  • pusher.name.

Verificação: HMAC SHA-256 do body com secret configurado na integração. O secret é gerado na UI quando o webhook é criado no GitHub.

Response 200:

{ "status": "ok", "bindings_triggered": 2 }

Response 401: assinatura inválida.

POST /webhooks/git/gitlab

Headers esperados:

Content-Type: application/json
X-Gitlab-Event: Push Hook
X-Gitlab-Token: <secret>

Payload: Push Hook do GitLab. Campos lidos: ref, project.path_with_namespace, checkout_sha.

Verificação: comparação de X-Gitlab-Token com o secret configurado.

POST /webhooks/git/gitea

Headers: similar ao GitHub (X-Gitea-Event, X-Gitea-Signature).

Verificação: HMAC SHA-256 do body.

Como o RuleForge usa os webhooks de entrada

  1. Recebe o push event.
  2. Verifica assinatura/token.
  3. Extrai (provider, repository, branch, commit_sha).
  4. Busca todos os bindings ativos com sync_on_webhook=true que batem.
  5. Enfileira um git_sync job para cada binding.
  6. Retorna 200 ao provedor (o processamento é assíncrono).

O status dos syncs disparados fica disponível em GET /.../git-bindings/{id}/runs.

Estruturas compartilhadas

WebhookRecord

Já mostrado acima.

WebhookDeliveryRecord

Já mostrado acima. statusfailed.