Una alerta que solo llega al correo es un incidente sin responsable. La integración entre Zabbix y GLPI existe para convertir cada problema detectado en un ticket rastreable - con número, responsable, categoría, prioridad y SLA - y para cerrarlo solo cuando Zabbix confirma la recuperación. El truco no está en "crear el ticket": está en no crear cuarenta.
Qué debe entregar la integración
Un puente Zabbix a GLPI que aguante producción necesita cuatro garantías, no solo "publicar un ticket":
- Idempotencia: un problema abre un ticket, no uno por cada paso de escalado.
- Correlación problema/recuperación: el evento de recovery debe encontrar y cerrar exactamente el ticket que abrió.
- Mapeo de severidad: la severidad de Zabbix se traduce a prioridad de GLPI de forma consistente, no a criterio de cada analista.
- Contexto suficiente: host, IP, trigger, hora y mensaje en el cuerpo, para que el analista actúe sin abrir Zabbix.
Arquitectura: dónde el webhook se vuelve ticket
Zabbix dispara con una Action; la Action ejecuta una operación de medio de tipo Webhook; el Webhook es un script JavaScript nativo de Zabbix que hace un POST a un endpoint del lado de GLPI. Del lado de GLPI usamos el receiver del módulo Automatizaciones, que valida la firma HMAC, aplica el mapa de campos y crea (o cierra) el ticket. Evitamos llamar a la API REST de GLPI directamente desde Zabbix porque cada llamada exigiría el par app-token/user-token y un par initSession/killSession - bajo una tormenta de alertas eso golpea la API y agota sesiones.
Artefacto: el Media Type webhook de Zabbix
Los parámetros mapean macros del evento; el script arma el payload y trata el código HTTP. Problema y recuperación usan el mismo Media Type - el campo event_value los distingue (1 = problema, 0 = recuperación):
// Zabbix -> Media type -> Webhook -> Parametros
// endpoint = https://glpi.cliente.com/plugins/nextool/automations/webhook/zabbix
// event_id = {EVENT.ID} // estable en el par problema/recovery
// event_value = {EVENT.VALUE} // 1 = problema, 0 = recuperacion
// host_name = {HOST.NAME}
// host_ip = {HOST.IP}
// trigger_name = {TRIGGER.NAME}
// severity = {TRIGGER.SEVERITY}
// occurred = {EVENT.DATE} {EVENT.TIME}
// message = {ALERT.MESSAGE}
// hmac = {$NEXTOOL_HMAC} // macro secreta, nunca en el cuerpo de la alerta
var p = JSON.parse(value);
var req = new HttpRequest();
req.addHeader('Content-Type: application/json');
req.addHeader('X-Nextool-Signature: ' + p.hmac);
var payload = JSON.stringify({
event_id: p.event_id,
recovery: p.event_value === '0',
host: p.host_name,
host_ip: p.host_ip,
trigger: p.trigger_name,
severity: p.severity,
occurred: p.occurred,
message: p.message
});
var resp = req.post(p.endpoint, payload);
var code = req.getStatus();
if (code < 200 || code >= 300) {
Zabbix.log(3, '[nextool] fallo HTTP ' + code + ': ' + resp);
throw 'Envio a GLPI fallo: HTTP ' + code;
}
return resp;
Mapa de severidad Zabbix a prioridad GLPI
Zabbix tiene seis severidades; GLPI, cinco prioridades. Fijamos el mapa en el receiver para no dejarlo a criterio de cada analista:
| Severidad Zabbix | Prioridad GLPI | Abre ticket? |
|---|---|---|
| Not classified / Information | - | No (solo registro) |
| Warning | Baja | Sí |
| Average | Media | Sí |
| High | Alta | Sí |
| Disaster | Muy alta | Sí + notifica a guardia |
Deduplicación y cierre automático
Este es el punto que separa una integración de juguete de una que sobrevive en producción. Al abrir el ticket, el receiver guarda el tickets_id de GLPI como tag del evento en Zabbix (o en una tabla de correlación indexada por event_id). Cuando Zabbix envía el recovery con el mismo event_id, el receiver localiza ese ticket y añade un seguimiento de recuperación - o lo cierra, según la política del cliente. Sin esa clave, el recovery no sabe qué ticket cerrar y acumulas tickets abiertos de problemas ya resueltos.
Errores comunes que corregimos en soporte
En el soporte diario, el incidente más común no es la alerta que nunca se vuelve ticket - es la alerta que se vuelve cuarenta. Una interfaz en flapping a las 3 de la mañana abrió decenas de tickets idénticos porque la Action disparaba en cada paso de escalado y el receiver no deduplicaba. La corrección tiene dos lados: en Zabbix, dependencia de trigger, histéresis en la expresión de recovery y operación de medio solo en el primer paso; en GLPI, idempotencia por event_id. Otros dos errores recurrentes: enviar la categoría del ticket como texto libre (GLPI espera un itilcategories_id numérico - un texto nuevo no coincide y el ticket queda sin categoría) y poner el secreto HMAC en el cuerpo de la alerta en vez de en una macro protegida como {$NEXTOOL_HMAC}.
Métodos de integración comparados
| Método | Sin código? | Dedup/recovery | Cuándo usar |
|---|---|---|---|
| Módulo Automatizaciones (receiver) | Sí (mapa por JSONPath) | Nativo por event_id | Estándar para la mayoría de clientes |
| API REST de GLPI directa | No | Lo implementas tú | Sin el módulo; pocos hosts |
| Script externo (Python/Bash) | No | Lo implementas y mantienes | Reglas de negocio fuera del estándar |
Si tu operación ya corre Zabbix pero las alertas mueren en un buzón que nadie lee, NexTool implementa este puente con el módulo Automatizaciones y mantiene las reglas afinadas en soporte - triggers, mapa de severidad y política de cierre. Conoce el módulo Automatizaciones.
Este contenido se produjo con ayuda de inteligencia artificial y fue revisado por el equipo de Nextool Solutions.