Webhooks
Configure destinos de webhook para receber alertas de segurança do cside via requisições HTTP POST com verificação de assinatura HMAC.
Como os webhooks funcionam
Os webhooks permitem que você receba notificações do cside como requisições HTTP POST para uma URL que você especificar. Quando um trigger dispara, o cside envia um payload JSON para o seu endpoint de webhook contendo detalhes sobre o evento.
Você pode configurar webhooks em três formatos:
- JSON - payload JSON padrão para integrações personalizadas
- Slack - pré-formatado para canais Slack
- Discord - pré-formatado para canais Discord
Adicionando um destino de webhook
Para adicionar um webhook como destino em uma notification config:
- Abra o painel e navegue até Team Settings > Notifications
- Crie uma nova notification config ou edite uma existente
- Em Send To, clique em Add destination e selecione Webhook
- No painel de Configuration, preencha:
- Endpoint URL: a URL onde você deseja receber as notificações de webhook (ex.:
https://example.com/cside/notify) - Secret: uma chave secreta usada para assinar as requisições de webhook (usada para verificação HMAC)
- Format: escolha JSON, Slack ou Discord
- Endpoint URL: a URL onde você deseja receber as notificações de webhook (ex.:
- Clique em Save ou Save & Test
O payload do webhook
Toda requisição de webhook contém um payload JSON estruturado com os seguintes campos:
event"alert.created"
sent_atstring
dataAlertCreatedObject
domain_idstring
destination_idstring
Events
Abaixo estão os IDs de eventos e seus payloads enviados com os webhooks.
Event IDs
| ID | Nome | Objeto data |
|---|---|---|
| alert.created | Alert Created | Alert Object |
Objetos de evento
type"URL"|"HASH"|"IP"|"DOMAIN"|"HOSTNAME"
domainstring
targetstring
action"alert"
Verificação HMAC
Toda requisição de webhook inclui um header x-cside-signature contendo um hash HMAC SHA256 do corpo da requisição, assinado com o secret que você forneceu ao criar o destino de webhook.
Você deve sempre verificar essa assinatura para confirmar que a requisição veio do cside e prevenir ataques de replay.
Como verificar a assinatura
Se você está usando JavaScript, use nosso pacote JavaScript para verificação integrada.
Para outras linguagens, calcule o hash HMAC SHA256 do corpo bruto da requisição usando seu secret de webhook e compare-o com o valor do header x-cside-signature.
async function verifyHmac(body: string, signature: string, secret: string) {
const encoder = new TextEncoder();
const encodedBody = encoder.encode(body);
const key = await crypto.subtle.importKey(
"raw",
encoder.encode(secret),
{ name: "HMAC", hash: "SHA-256" },
false,
["sign"]
);
const signatureBuffer = await crypto.subtle.sign("HMAC", key, encodedBody);
const finalSig = Array.from(new Uint8Array(signatureBuffer))
.map((byte) => byte.toString(16).padStart(2, "0"))
.join("");
return signature.toLowerCase() === finalSig;
}fn verify_hmac(body: &str, signature: &str, secret: &str) -> Result<(), &'static str> {
let mut mac = HmacSha256::new_from_slice(secret.as_bytes()).map_err(|_| "Invalid secret")?;
mac.update(body.as_bytes());
let result = mac.finalize();
let code_bytes = result.into_bytes();
let final_sig = hex::encode(code_bytes);
if signature.to_lowercase() == final_sig {
Ok(())
} else {
Err("Invalid signature")
}
}
// Add to Cargo.toml:
// [dependencies]
// hmac = "0.12"
// sha2 = "0.10"
// hex = "0.4"package main
import (
"crypto/hmac"
"crypto/sha256"
"encoding/hex"
"strings"
)
func verifyHmac(body, signature, secret string) bool {
h := hmac.New(sha256.New, []byte(secret))
h.Write([]byte(body))
finalSig := hex.EncodeToString(h.Sum(nil))
return strings.ToLower(signature) == finalSig
}defmodule HmacVerifier do
def verify_hmac(body, signature, secret) do
final_sig =
:crypto.mac(:hmac, :sha256, secret, body)
|> Base.encode16(case: :lower)
String.downcase(signature) == final_sig
end
endimport hmac
import hashlib
import secrets
def verify_hmac(body: str, signature: str, secret: str) -> bool:
final_sig = hmac.new(
secret.encode('utf-8'),
body.encode('utf-8'),
hashlib.sha256
).hexdigest()
return signature.lower() == final_sigThanks for your feedback!