Ir al contenido

Receptores de webhooks

Construye un endpoint que reciba los webhooks de Rhombus de forma segura: verifica las firmas sobre el cuerpo sin procesar, responde rápido y encola el trabajo, llega a sistemas de una red privada sin abrirla a internet y prueba en local.

En esta página

Un receptor de webhooks es el endpoint HTTPS al que Rhombus envía los eventos. Esta guía construye uno que verifica cada solicitud, responde dentro de los límites de tiempo de Rhombus y entrega el trabajo al resto de tus sistemas, incluidos los de una red privada que no puede aceptar conexiones desde internet.

Antes de empezar, lee Webhooks para conocer los dos tipos de webhook (la acción de webhook de una regla y los webhooks de Actividad y Diagnóstico de la organización), sus cargas útiles y sus reglas de entrega.

Qué debe hacer el receptor

  1. Aceptar HTTPS en una dirección pública con un certificado de una autoridad de certificación pública.
  2. Verificar la firma sobre el cuerpo sin procesar antes de confiar en su contenido.
  3. Responder 200 en pocos segundos. Rhombus da 2 segundos para conectar en los webhooks de reglas y hace un solo intento; el trabajo lento va después de la respuesta.
  4. Encolar el evento para tus trabajadores, y dejar que eliminen duplicados por los IDs de la carga útil.

Un receptor en Node.js y Python

Ambos ejemplos verifican x-rhombus-signature-sha256, el HMAC-SHA256 en hexadecimal en minúsculas del cuerpo sin procesar, con el secreto del webhook como clave. Las acciones de webhook de reglas y los webhooks de la organización lo envían, así que el mismo receptor sirve para ambos tipos; los webhooks de la organización también envían x-rhombus-signature-sha1, que no necesitas. La firma cubre exactamente los bytes que envió Rhombus, así que lee el cuerpo sin procesar: un analizador JSON que se ejecute antes (como express.json()) lo modifica, y la verificación falla.

javascript
import crypto from "node:crypto";
import express from "express";

const SECRET = process.env.RHOMBUS_WEBHOOK_SECRET; // the webhook's secret
const app = express();

// express.raw keeps the body as bytes so the signature can be checked.
app.post("/rhombus/webhook", express.raw({ type: "*/*", limit: "1mb" }), (req, res) => {
  const sent = Buffer.from(req.get("x-rhombus-signature-sha256") ?? "");
  const expected = Buffer.from(crypto.createHmac("sha256", SECRET).update(req.body).digest("hex"));
  if (sent.length !== expected.length || !crypto.timingSafeEqual(sent, expected)) { // constant time
    return res.sendStatus(401);
  }
  res.sendStatus(200); // answer first
  queue.push(JSON.parse(req.body.toString("utf8"))); // then hand off: SQS, Pub/Sub, Kafka, a table
});

app.listen(8080);

El cuerpo de un webhook de regla describe la regla que se activó y los eventos que coincidieron:

javascript
const { ruleUuid, triggeredTimestampMs, deviceEvents = [] } = event;
for (const deviceEvent of deviceEvents) {
  console.log(ruleUuid, deviceEvent.deviceUuid, deviceEvent.activities, deviceEvent.timestampMs);
}

Webhooks muestra ambas cargas útiles completas.

Dónde ejecutarlo

SituaciónEjecuta el receptorNotas
Tus sistemas están en la nubeUn contenedor o una función detrás de tu balanceador de carga o tu API gatewayLa opción más simple
Tus sistemas están en una red privadaUn pequeño relé público (una función serverless y una cola) que verifica y encola; los trabajadores privados toman los eventos de la colaNinguna conexión entrante a la red privada
Estás desarrollando en localTu equipo, detrás de un túnel temporal de un servicio de túnelesSolo para pruebas; cierra el túnel al terminar

Redes privadas: relé a través de una cola

Los sistemas que no aceptan conexiones desde internet sí pueden salir. Pon solo el receptor en internet y deja que tus sistemas privados recojan los eventos:

Cargando el diagrama…
  • El receptor solo tiene el secreto del webhook, nunca una clave de API.
  • Los trabajadores necesitan acceso saliente a la cola y nada entrante.
  • Si la cola o los trabajadores no están disponibles, los eventos esperan en la cola; si el receptor no está disponible, Rhombus no reenvía, así que concilia con la API.

Evita reenviar webhooks a la red privada mediante un túnel SSH o una redirección de puertos: expone una vía de entrada a un host interno, y el túnel se convierte en una credencial y un punto único de fallo que mantener.

Pruebas locales

Para probar un receptor en tu equipo, expón su puerto a través de un servicio de túneles, agrega la URL HTTPS del túnel como URL del webhook y activa la regla. Elimina el webhook de Rhombus y cierra el túnel al terminar.

Configura Rhombus

  1. Agrega el webhook

    Para la acción de webhook de una regla, abre la regla en la consola, agrega una acción de webhook con la URL HTTPS de tu receptor y guarda. Para un webhook de organización, ve a Configuración → Integraciones y recursos para desarrolladores → Webhooks, agrega la URL y elige Actividad o Diagnóstico.

  2. Guarda el secreto

    Copia el secreto del webhook en la configuración de tu receptor, desde un gestor de secretos y no desde el código fuente. Encuentra tu secreto muestra dónde lo guarda cada tipo.

  3. Activa un evento de prueba

    Provoca un evento que cubra la regla o el webhook y confirma que el receptor registra una solicitud verificada y devuelve 200.

Ponlo en producción

  • Monitorea el receptor: alerta sobre respuestas que no sean 2xx, fallos de firma y respuestas lentas. Una entrega fallida de un webhook de regla también aparece en Rhombus como un evento de diagnóstico EXTERNAL_WEBHOOK_FAILURE.
  • Rechaza las solicitudes sin firma. Una solicitud sin una firma válida no vino de Rhombus.
  • Mantén las cargas útiles fuera de los registros compartidos. Nombran personas, lugares y dispositivos; registra solo los IDs que necesites.
  • Reemplaza un secreto filtrado: elimina el webhook y créalo de nuevo, lo que le da un secreto nuevo, y después actualiza el receptor.