Webhooks
Dois fluxos distintos:
- 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/*. - 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étodo | Caminho | Permissão |
|---|---|---|
| POST | /platform/organizations/{organization_id}/webhooks | integration:manage |
| GET | /platform/organizations/{organization_id}/webhooks | Sessã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}/deliveries | Sessão |
| POST | /platform/organizations/{organization_id}/webhooks/{webhook_id}/test | integration:manage |
Inbound — tabela de endpoints
| Método | Caminho | Auth |
|---|---|---|
| POST | /webhooks/git/github | HMAC SHA-256 |
| POST | /webhooks/git/gitlab | Token secreto |
| POST | /webhooks/git/gitea | HMAC 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 serhttp://ouhttps://. Por padrão IPs privados/loopback são bloqueados (controlado pelo operador viaNATIVE_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 headerX-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
2xxem 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_countsobe; após várias falhas seguidas o webhook pode ser marcado comois_active=falsepelo 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 comrefs/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
- Recebe o push event.
- Verifica assinatura/token.
- Extrai
(provider, repository, branch, commit_sha). - Busca todos os bindings ativos com
sync_on_webhook=trueque batem. - Enfileira um
git_syncjob para cada binding. - Retorna
200ao 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. status ∈ failed.
Links relacionados
- Eventos de webhook — lista completa com descrições.
- Webhooks — guia operacional
- Git e pipelines
- Endpoints de organização — git bindings.