Notificaciones XMPP con un minimo esfuerzo

"Ditch all those 3rd. party cloudy shining things and join the flow."

lowcodewebhooksxmpp.png

Hay muchas soluciones de low-code por ahí, pero cuando se habla sobre libertad y soberanía sólo uno sobresale y es Node-RED.

Node-RED no es nuevo, es un poco viejo, pero... al contrario de lo que muchos pensarían, es una buena señal. Hecho por IBM hace ya un tiempo, su 1er. release fue en 2013 y luego liberado en el 2016 bajo licencia Apache dejándoselo a la OpendJS Fundation. Node-Red es un entorno de programación low-code orientada a eventos. Hecho en JS, el lado low-code de esta cosa es que terminamos codeando en JavaScript y manipulando objetos JSON todo el tiempo. Pero, para la mayoría de las tareas requeridas para un simple mortal, los nodos de flujo disponibles en la paleta de nodos , es más que suficiente.

forgejo_webhook.png

La cuestión es más que simple y aunque suene descabellado vamos a crear un ecosistema de bots que reaccionen en tiempo real a eventos definidos, integrando tecnologías autoalojables como Forgejo, UptimeKuma, Node-RED y XMPP para que tu sistema de alertas sea robusto y accesible en términos económicos.

Notificaciones usando WebHooks

En la era de la automatización, los webhooks juegan un gran papel en la comunicación entre sistemas. Forgejo, la alternativa descentralizada a GitLab, y UptimeKuma —el monitor de servicios con interfaz minimalista— pueden escribirte mensajes en tiempo real cuando algo se mueve en tus repositorios o tu infraestructura se tambalea. Imagina esto: un push en tu código dispara un mensaje en tu chat de trabajo, o UptimeKuma te avisa por XMPP cuando alguna de las APIs que usas se cae

Resumiendo, muchos sistemas necesitan webhooks para enviar mensajes a otros sistemas, por ejemplo Gitlab e incluso Github pueden enviar mensajes a través de webhooks.

Forgejo push events

Vamos a crear notificaciones webhook para recibir notificaciones sobre eventos push en nuestros proyectos de interes. El flujo es bastante simple de seguir:

forgejo_webhook.png

Los nodos verde son simplemente para obtener feedback de Node-Red mientras ejecuta, en la consola de debug del entorno podremos ver el contendido del mensaje tal y como sale del nodo (Es una herramienta muy útil mientas desarrollamos flujos).

El nodo forgehook es un nodo HTTP input. Define el path en el que se encontrara el webhook, el método HTTP a usar y si debe aceptar archivos.

El segundo nodo, llamado GetJSON transforma el string que se encuentra en el payload del mensaje a un objeto JSON.

Lo sigue el nodo Build Message, aqui tenemos un poco de low-code, ya que queremos contruir un mensaje un poco mas complejo y no queremos mostrar todos los datos que vienen en un evento push.

var msgrt = RED.util.cloneMessage(msg);
msgrt.payload = 'Nuevo push de'.concat(' ',
                  msg.payload.head_commit.author.name,
                  ' con ',
                  msg.payload.total_commits,
                  ' commits en ',
                  msg.payload.repository.full_name,
                  );
msg.payload.commits.forEach(function (obj) { msgrt.payload = msgrt.payload.concat("Mensaje # ",
                                             obj.id, " - ",
                                             obj.message); });
msgrt.payload
return msgrt

Por ultimo, y cerrando el flujo, el envío del mensaje, que en este caso es a un usuario, aunque tranquilamente podría ser una canal, como veremos en el próximo ejemplo. El mensaje en cuestión queda formateado de la siguiente manera:

Nuevo push de TheCoffeMaker con 3 commits en Cyberdelia/Blog
Mensaje # f2a2342374b345a3fe4500bf4fff636a6f8a2c70 - Eventos UptimeKuma
Mensaje # e347d3e754f0a39edd47fea26af614ed5bca80fd - Agregamos imagen placeholder de como configurar forgejo
Mensaje # d63e2ef9778b6451c4b5a5d96385577509acdce8 - Agregamos como quedaria el mensaje

pushalert.png

Por su lado la configuracion del proyecto en Forgejo es bastante trivial:

6cb64b344799ad87a3490ff0c2f7333c.png

y esta muy bien documentado.

Claro esta que lo podemos complejizar tanto como queramos, monitorear otros eventos de Forgejo o añadir autenticación y aumentar las medidas de seguridad, pero dado nuestro caso de uso, donde todo es autoalojado e independiente de redes publicas y/o de terceros, con que las notificaciones viajen dentro de la VLAN asignada es mas que suficiente. No olvidemos el hecho de que estamos procesando toda esta información cruda y enviando solo la información que nosotros necesitamos, sin exponer datos sensibles.

UptimeKuma events

También es muy útil recibir notificaciones cuando estamos fuera de casa y alguno de nuestros hosts falla o algun servicio deja de responder. Por lo que tenemos UptimeKuma monitoreando el estado de los hosts, servicios y el vencimiento de certificados SSL.

En el caso del monitoreo de cyberdelia.com.ar y su certificado tenemos en Node-RED el siguiente flujo que declara el webhook certhook, es decir que recibira cualquier cosa enviada a http:/host.de.nodered:puerto/certhook

36f7816a86f47c5042b4b6b71b0b9b1e.png

Este nodo tiene dos nodos deshabilitados, los cuales no serán ejecutados cuando el flujo procese algún dato. En este caso no enviara el objeto JSON en crudo dentro de un mensaje a dos usuarios XMPP.

Para recibir alertar sobre hosts, tenemos el siguiente flujo:

{static}/img/lowcodewebhooksxmpp/

Este ultimo flujo define el webhook alerthook y recorre un flujo similar, la diferencia principal es como se arma el mensaje en el nodo Build Message

Ambos flujos tienen nodos verdes, que usamos para debugear la salida de los nodos a los que estan conectados.

Certificate Hook/Incoming Alert: A,bos son nodos http input. Define el path en el que se encontrara el webhook, el método HTTP a usar y si debe aceptar archivos. En nuestro caso lo mantenemos simple:

26ee0e41a8d790eaf5795f46c538cc98.png

getJSON: No cambia en nada su finalidad, lo usamos para transformar el string que se encuentra en el payload del mensaje a un objeto JSON

Build Message: En ambos casos la función es similar y bastante menos compleja que el ejemplo de Forgejo. En el caso del mensaje para certificados:

var msgrt = RED.util.cloneMessage(msg);
var alert = JSON.parse(msg.payload);
msgrt.payload = 'Nueva Alerta de Certificado: \n';
msgrt.payload = msgrt.payload.concat(" - ",alert.msg, "\n");
return msgrt

Y para los mensajes de estado de hosts, definimos el mensaje de la siguiente forma:

var msgrt = RED.util.cloneMessage(msg);
var alert = JSON.parse(msg.payload);
msgrt.payload = 'Nueva Alerta en la Infraestructura Galactica: \n';
msgrt.payload = msgrt.payload.concat(" - ",alert.msg, "\n");
return msgrt

Ahora, en UptimeKuma, para monitorear sean hosts o servicios necesitamos agregar un monitor y asignarle una notificación tipo webhook para que este pueda enviar notificaciones ante cualquier cambio de estado en los objetivos monitoreados al endpoint que generamos en Node-RED.

1ro. creamos la notificacion

Para el caso de la notificacion por vencimiento de certificado creamos una notificacion tipo webhook (el request body debe ser application/json)

1b805a87640b3de25b49af1e18649c68.png

De igual manera, repetimos el procedimiento para el otro tipo de notificaciones:

b2062f92a267da280a5ca254e4824cef.png

2do. creamos el monitor

Como vimos en las alertas UtimeKuma, tiene un conjunto variado de servicios a los que podemos monitorear. En particular nosotros vamos a monitorear hosts usando Ping y servicios mediante HTTP

Para el caso de las notificaciones de vencimiento de certificados, creamos un monitor tipo HTTP(s) y le definimos la URL a monitorear.

97729feec52d1005b05df1ab1879b3ec.png

Al final del formulario encontraremos las opciones avanzadas y marcaremos la opcion Certificate Expiry Notification

ccad63300f0f743eb98302c5e2fd72ec.png

En la sección de configuración de las notificaciones (Settings>Notifications) tenemos la opción para controlar las notificaciones por vencimiento de certificados en general:

ae4518a1fc1b78222d17c1cea547c958.png

Algo a tener en cuenta es que podemos elegir la misma alerta para varios  monitores o seleccionar una alerta diferente para cada monitor.

Bien ... ahora vemos el caso del monitoreo de hosts, creamos el monitor tipo Ping, definimos el host al que queremos pinguear cada tanto para ver si responde y el asignamos la notificación Galactic Alert:

b6f885da364443d6c2a9c170deb03d2a.png

Metiendo LLMs en el medio

Ahora metamosle un poco de magia generativa usando nuestro ollama local, el flujo sigue siendo simple:

d61ad6eaad0f79d53d16656277c21b0e.png

Misma lógica que antes, salvo que ahora en vez de construir un mensaje para un usuario en un nodo Build Message, construimos un prompt para un modelo. La función definida en Build Prompt es tan simple como lo que veníamos haciendo con Build Message:

var msgrt = RED.util.cloneMessage(msg);
var alert_msg = "Make a short alert message for the provided message. Message: ".concat(JSON.parse(msg.payload).msg);
alert_msg = alert_msg.concat("**output format**",
"\n",
"[emoji] ALERT: [alert_message].",
"Choose emoji depending on message");
msgrt.payload = {"prompt":alert_msg};
return msgrt

La configuracion del nodo Ollama Generate es también muy simple para este caso: fe193e183927146f44db36c95505572d.png

Y por ultimo, porque Ollama no devuelve simplemente una cadena de texto con la respuesta generada, sino que agrega metadatos ... lo que hacemos en Build Message, es sacar la información relevante contenida en msg.payload.response y enviarla al nodo que finalmente envía la notificación a una sala XMPP.

var msgrt = RED.util.cloneMessage(msg);
msgrt.payload = msg.payload.response;
return msgrt

Y sin mucha más magia, tenemos un bot que procesa alertas de Uptime Kuma y nos escupe algo de su demencia estocástica.

Volver