first commit
This commit is contained in:
@@ -0,0 +1,163 @@
|
||||
# Configuración para Zabbix - Cisco MAC Monitor LLD
|
||||
# ================================================
|
||||
|
||||
## CONFIGURACIÓN DEL JAVASCRIPT EN ZABBIX
|
||||
|
||||
### 1. Crear el Script JavaScript en Zabbix
|
||||
|
||||
**Administración > Scripts > Crear Script**
|
||||
- Nombre: `Cisco MAC LLD`
|
||||
- Tipo: `Script`
|
||||
- Ejecutar en: `Zabbix server`
|
||||
- Comandos: [Copiar contenido de zabbix_lld_script.js]
|
||||
|
||||
### 2. Configurar Discovery Rule
|
||||
|
||||
**Configuración > Hosts > [Tu Host Cisco] > Discovery > Crear regla de descubrimiento**
|
||||
|
||||
- Nombre: `Cisco MAC Address Discovery`
|
||||
- Tipo: `Script`
|
||||
- Clave: `cisco.mac.discovery`
|
||||
- Script: `Cisco MAC LLD`
|
||||
- Intervalo: `1h` (o según necesites)
|
||||
- Periodo de conservación de elementos perdidos: `7d`
|
||||
|
||||
### 3. Configurar Macros del Host
|
||||
|
||||
**Configuración > Hosts > [Tu Host Cisco] > Macros**
|
||||
|
||||
Crear las siguientes macros:
|
||||
|
||||
```
|
||||
{$CISCO_SERVICE_URL} = https://tu-servidor:8443
|
||||
{$CISCO_HOST} = {HOST.CONN} # O la IP específica
|
||||
{$CISCO_USERNAME} = tu_usuario_ssh
|
||||
{$CISCO_PASSWORD} = tu_contraseña_ssh
|
||||
{$CISCO_TIMEOUT} = 60
|
||||
```
|
||||
|
||||
### 4. Configurar Item Prototypes
|
||||
|
||||
Una vez creada la Discovery Rule, crear los siguientes Item Prototypes:
|
||||
|
||||
#### Item 1: Contador de MACs por Puerto
|
||||
- Nombre: `Port {#PORT_NAME} - MAC Count`
|
||||
- Tipo: `Dependent item`
|
||||
- Clave: `cisco.port.mac.count[{#PORT_NAME}]`
|
||||
- Master item: `cisco.mac.discovery`
|
||||
- Preprocessing:
|
||||
- JSONPath: `$.data[?(@['{#PORT_NAME}'] == '{#PORT_NAME}')]['{#MAC_COUNT}'].first()`
|
||||
|
||||
#### Item 2: Lista de MACs por Puerto
|
||||
- Nombre: `Port {#PORT_NAME} - MAC Addresses`
|
||||
- Tipo: `Dependent item`
|
||||
- Clave: `cisco.port.mac.addresses[{#PORT_NAME}]`
|
||||
- Tipo de información: `Text`
|
||||
- Master item: `cisco.mac.discovery`
|
||||
- Preprocessing:
|
||||
- JSONPath: `$.data[?(@['{#PORT_NAME}'] == '{#PORT_NAME}')]['{#MAC_ADDRESSES}'].first()`
|
||||
|
||||
#### Item 3: VLANs por Puerto
|
||||
- Nombre: `Port {#PORT_NAME} - VLANs`
|
||||
- Tipo: `Dependent item`
|
||||
- Clave: `cisco.port.vlans[{#PORT_NAME}]`
|
||||
- Tipo de información: `Text`
|
||||
- Master item: `cisco.mac.discovery`
|
||||
- Preprocessing:
|
||||
- JSONPath: `$.data[?(@['{#PORT_NAME}'] == '{#PORT_NAME}')]['{#VLANS}'].first()`
|
||||
|
||||
### 5. Configurar Triggers (Opcional)
|
||||
|
||||
#### Trigger 1: Puerto con muchas MACs
|
||||
- Nombre: `Port {#PORT_NAME} has too many MAC addresses`
|
||||
- Expresión: `last(/Template/cisco.port.mac.count[{#PORT_NAME}])>50`
|
||||
- Severidad: `Warning`
|
||||
|
||||
#### Trigger 2: Cambio en número de MACs
|
||||
- Nombre: `MAC count changed on port {#PORT_NAME}`
|
||||
- Expresión: `change(/Template/cisco.port.mac.count[{#PORT_NAME}])<>0`
|
||||
- Severidad: `Information`
|
||||
|
||||
## CONFIGURACIÓN DEL SERVICIO HTTPS
|
||||
|
||||
### Variables de entorno necesarias:
|
||||
```bash
|
||||
CISCO_SERVICE_PORT=8443
|
||||
SSL_CERT_PATH=/path/to/certificate.pem
|
||||
SSL_KEY_PATH=/path/to/private.key
|
||||
```
|
||||
|
||||
### Comando para generar certificado autofirmado:
|
||||
```bash
|
||||
openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365 -nodes \
|
||||
-subj "/C=ES/ST=Madrid/L=Madrid/O=Organization/CN=cisco-monitor"
|
||||
```
|
||||
|
||||
## ESTRUCTURA ESPERADA DE RESPUESTA JSON
|
||||
|
||||
```json
|
||||
{
|
||||
"data": [
|
||||
{
|
||||
"port": "Gi1/0/1",
|
||||
"data": {
|
||||
"count": 2,
|
||||
"vlans": "600,601",
|
||||
"addresses": "F0:8E:DB:2E:4D:86 600\nF0:8E:DB:2E:4D:86 601",
|
||||
"timestamp": 1763048672
|
||||
}
|
||||
},
|
||||
{
|
||||
"port": "Gi1/0/10",
|
||||
"data": {
|
||||
"count": 1,
|
||||
"vlans": "151",
|
||||
"addresses": "00:50:56:A6:91:69 151",
|
||||
"timestamp": 1763048672
|
||||
}
|
||||
},
|
||||
{
|
||||
"port": "Gi1/0/11",
|
||||
"data": {
|
||||
"count": 0,
|
||||
"vlans": "",
|
||||
"addresses": "",
|
||||
"timestamp": 1763048672
|
||||
}
|
||||
}
|
||||
],
|
||||
"timestamp": "2024-11-13T10:30:00",
|
||||
"unix_timestamp": 1700000000,
|
||||
"device_hostname": "cisco-switch",
|
||||
"total_ports": 24,
|
||||
"total_macs": 45,
|
||||
"ports_with_macs": 12,
|
||||
"ports_without_macs": 12
|
||||
}
|
||||
```
|
||||
|
||||
## TROUBLESHOOTING
|
||||
|
||||
### 1. Verificar logs de Zabbix
|
||||
```bash
|
||||
tail -f /var/log/zabbix/zabbix_server.log | grep "Cisco"
|
||||
```
|
||||
|
||||
### 2. Probar el servicio manualmente
|
||||
```bash
|
||||
curl -k -X POST https://tu-servidor:8443/mac-monitor \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"host": "192.168.1.10",
|
||||
"username": "admin",
|
||||
"password": "password"
|
||||
}'
|
||||
```
|
||||
|
||||
### 3. Verificar conectividad HTTPS desde Zabbix
|
||||
Usar "Administration > Scripts > Test" en Zabbix con un script simple:
|
||||
```javascript
|
||||
var req = new HttpRequest();
|
||||
var response = req.get("https://tu-servidor:8443/health");
|
||||
return response;
|
||||
```
|
||||
@@ -0,0 +1,60 @@
|
||||
/**
|
||||
* Zabbix JavaScript para consulta de datos MAC por puerto
|
||||
* Compatible con versiones antiguas - Funciona con Zabbix 4.x, 5.x y 6.x
|
||||
* Formato de respuesta estructurado por puertos
|
||||
*/
|
||||
|
||||
// Configuración mediante macros
|
||||
var serviceUrl = "{$CISCO_SERVICE_URL}";
|
||||
var ciscoHost = "{$CISCO_HOST}";
|
||||
var ciscoUsername = "{$CISCO_USERNAME}";
|
||||
var ciscoPassword = "{$CISCO_PASSWORD}";
|
||||
|
||||
// Validar parámetros requeridos
|
||||
if (!serviceUrl || !ciscoHost || !ciscoUsername || !ciscoPassword) {
|
||||
throw "Faltan parámetros: CISCO_SERVICE_URL, CISCO_HOST, CISCO_USERNAME, CISCO_PASSWORD";
|
||||
}
|
||||
|
||||
// Log de inicio
|
||||
Zabbix.Log(4, "[Cisco MAC] Host: " + ciscoHost);
|
||||
|
||||
// Preparar datos para POST
|
||||
var postData = JSON.stringify({
|
||||
"host": ciscoHost,
|
||||
"username": ciscoUsername,
|
||||
"password": ciscoPassword,
|
||||
"port": 22,
|
||||
"timeout": 30
|
||||
});
|
||||
|
||||
// Crear request HTTP (método básico compatible)
|
||||
var req = new HttpRequest();
|
||||
req.addHeader('Content-Type: application/json');
|
||||
|
||||
try {
|
||||
// Hacer consulta POST
|
||||
var response = req.post(serviceUrl , postData);
|
||||
|
||||
// Verificar status
|
||||
if (req.getStatus() !== 200) {
|
||||
throw "HTTP Error " + req.getStatus();
|
||||
}
|
||||
|
||||
// Parsear respuesta
|
||||
var jsonData = JSON.parse(response);
|
||||
|
||||
// Validar estructura
|
||||
if (!jsonData.data) {
|
||||
throw "Invalid response structure";
|
||||
}
|
||||
|
||||
// Log de éxito
|
||||
Zabbix.Log(4, "[Cisco MAC] Success: " + jsonData.data.length + " ports");
|
||||
|
||||
// Retornar datos estructurados por puertos
|
||||
return JSON.stringify(jsonData);
|
||||
|
||||
} catch (error) {
|
||||
Zabbix.Log(2, "[Cisco MAC] ERROR: " + error);
|
||||
throw "Cisco MAC query failed: " + error;
|
||||
}
|
||||
@@ -0,0 +1,140 @@
|
||||
/**
|
||||
* Zabbix JavaScript para Low Level Discovery (LLD)
|
||||
* Consulta HTTPS al servicio de monitorización de MACs Cisco
|
||||
*
|
||||
* Parámetros esperados:
|
||||
* - {$CISCO_SERVICE_URL}: URL del servicio HTTPS (ej: https://cisco-monitor:8443)
|
||||
* - {$CISCO_HOST}: IP o hostname del dispositivo Cisco
|
||||
* - {$CISCO_USERNAME}: Usuario SSH
|
||||
* - {$CISCO_PASSWORD}: Contraseña SSH
|
||||
* - {$CISCO_TIMEOUT}: Timeout en segundos (opcional, default: 60)
|
||||
*
|
||||
* Uso en Zabbix:
|
||||
* - Crear un item tipo "Script"
|
||||
* - Configurar parámetros como macros del host
|
||||
* - Usar este script en el discovery rule
|
||||
*/
|
||||
|
||||
// Configuración
|
||||
var serviceUrl = "{$CISCO_SERVICE_URL}";
|
||||
var ciscoHost = "{$CISCO_HOST}";
|
||||
var ciscoUsername = "{$CISCO_USERNAME}";
|
||||
var ciscoPassword = "{$CISCO_PASSWORD}";
|
||||
var timeout = parseInt("{$CISCO_TIMEOUT}") || 60;
|
||||
|
||||
// Validar parámetros requeridos
|
||||
if (!serviceUrl || !ciscoHost || !ciscoUsername || !ciscoPassword) {
|
||||
throw new Error("Faltan parámetros requeridos: CISCO_SERVICE_URL, CISCO_HOST, CISCO_USERNAME, CISCO_PASSWORD");
|
||||
}
|
||||
|
||||
// Log de inicio
|
||||
Zabbix.Log(4, "[Cisco MAC LLD] Iniciando consulta para host: " + ciscoHost);
|
||||
Zabbix.Log(4, "[Cisco MAC LLD] Service URL: " + serviceUrl);
|
||||
|
||||
try {
|
||||
// Preparar datos para POST
|
||||
var postData = JSON.stringify({
|
||||
"host": ciscoHost,
|
||||
"username": ciscoUsername,
|
||||
"password": ciscoPassword,
|
||||
"port": 22,
|
||||
"timeout": timeout
|
||||
});
|
||||
|
||||
// Configurar request HTTP
|
||||
var req = new HttpRequest();
|
||||
|
||||
// Configurar headers
|
||||
req.addHeader('Content-Type: application/json');
|
||||
req.addHeader('Accept: application/json');
|
||||
req.addHeader('User-Agent: Zabbix-LLD-Script/1.0');
|
||||
|
||||
// Configurar timeout (método compatible con versiones anteriores de Zabbix)
|
||||
if (typeof req.setTimeout === 'function') {
|
||||
req.setTimeout(timeout * 1000);
|
||||
} else if (typeof req.setConnectTimeout === 'function') {
|
||||
req.setConnectTimeout(timeout);
|
||||
req.setTimeout(timeout);
|
||||
}
|
||||
|
||||
// Log de request
|
||||
Zabbix.Log(4, "[Cisco MAC LLD] Enviando POST a: " + serviceUrl + "/cisco-mac-monitor");
|
||||
Zabbix.Log(4, "[Cisco MAC LLD] POST data: " + postData);
|
||||
|
||||
// Hacer la consulta HTTPS POST
|
||||
var response = req.post(serviceUrl + "/cisco-mac-monitor", postData);
|
||||
|
||||
// Log de response
|
||||
Zabbix.Log(4, "[Cisco MAC LLD] Response status: " + req.getStatus());
|
||||
Zabbix.Log(4, "[Cisco MAC LLD] Response length: " + response.length);
|
||||
|
||||
// Verificar código de estado HTTP
|
||||
if (req.getStatus() !== 200) {
|
||||
throw new Error("HTTP Error " + req.getStatus() + ": " + response);
|
||||
}
|
||||
|
||||
// Validar que la respuesta no esté vacía
|
||||
if (!response || response.trim().length === 0) {
|
||||
throw new Error("Respuesta vacía del servicio");
|
||||
}
|
||||
|
||||
// Intentar parsear JSON
|
||||
var jsonResponse;
|
||||
try {
|
||||
jsonResponse = JSON.parse(response);
|
||||
} catch (parseError) {
|
||||
Zabbix.Log(3, "[Cisco MAC LLD] Error parsing JSON: " + parseError.message);
|
||||
Zabbix.Log(3, "[Cisco MAC LLD] Raw response: " + response.substring(0, 500) + "...");
|
||||
throw new Error("Error parsing JSON response: " + parseError.message);
|
||||
}
|
||||
|
||||
// Validar estructura de respuesta
|
||||
if (!jsonResponse.data || !Array.isArray(jsonResponse.data)) {
|
||||
throw new Error("Respuesta JSON inválida: falta campo 'data' o no es array");
|
||||
}
|
||||
|
||||
// Log de éxito
|
||||
Zabbix.Log(4, "[Cisco MAC LLD] Éxito: " + jsonResponse.data.length + " elementos descubiertos");
|
||||
Zabbix.Log(4, "[Cisco MAC LLD] Device: " + (jsonResponse.device_hostname || "unknown"));
|
||||
Zabbix.Log(4, "[Cisco MAC LLD] Total ports: " + (jsonResponse.total_ports || 0));
|
||||
Zabbix.Log(4, "[Cisco MAC LLD] Total MACs: " + (jsonResponse.total_macs || 0));
|
||||
|
||||
// Preparar respuesta para LLD
|
||||
var lldResponse = {
|
||||
"data": jsonResponse.data
|
||||
};
|
||||
|
||||
// Log de algunos elementos de ejemplo para debug
|
||||
if (jsonResponse.data.length > 0) {
|
||||
Zabbix.Log(4, "[Cisco MAC LLD] Primer elemento: " + JSON.stringify(jsonResponse.data[0]));
|
||||
|
||||
if (jsonResponse.data.length > 1) {
|
||||
Zabbix.Log(4, "[Cisco MAC LLD] Segundo elemento: " + JSON.stringify(jsonResponse.data[1]));
|
||||
}
|
||||
}
|
||||
|
||||
// Retornar JSON para LLD
|
||||
return JSON.stringify(lldResponse);
|
||||
|
||||
} catch (error) {
|
||||
// Log de error detallado
|
||||
Zabbix.Log(2, "[Cisco MAC LLD] ERROR: " + error.message);
|
||||
Zabbix.Log(2, "[Cisco MAC LLD] Host: " + ciscoHost);
|
||||
Zabbix.Log(2, "[Cisco MAC LLD] Service URL: " + serviceUrl);
|
||||
|
||||
// En caso de error, retornar estructura vacía para evitar fallos en LLD
|
||||
// Esto permite que Zabbix no falle completamente si hay problemas temporales
|
||||
var errorResponse = {
|
||||
"data": [],
|
||||
"error": error.message,
|
||||
"timestamp": new Date().toISOString(),
|
||||
"host": ciscoHost
|
||||
};
|
||||
|
||||
// Opcionalmente, lanzar error para que Zabbix lo registre
|
||||
// Comentar la siguiente línea si prefieres que LLD retorne estructura vacía en caso de error
|
||||
throw new Error("Cisco MAC LLD failed for " + ciscoHost + ": " + error.message);
|
||||
|
||||
// Retornar respuesta de error (solo se ejecuta si se comenta el throw anterior)
|
||||
// return JSON.stringify(errorResponse);
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/**
|
||||
* Zabbix JavaScript Simplificado para Cisco MAC LLD
|
||||
* Versión minimalista para pruebas rápidas
|
||||
*/
|
||||
|
||||
// Parámetros (configurar según tu entorno)
|
||||
var serviceUrl = value; // Pasado como parámetro en Zabbix
|
||||
var ciscoHost = "{HOST.CONN}"; // IP del host de Zabbix
|
||||
var username = "{$CISCO_USER}";
|
||||
var password = "{$CISCO_PASS}";
|
||||
|
||||
Zabbix.Log(4, "Cisco LLD: Consultando " + ciscoHost);
|
||||
|
||||
var req = new HttpRequest();
|
||||
req.addHeader('Content-Type: application/json');
|
||||
|
||||
var postData = JSON.stringify({
|
||||
"host": ciscoHost,
|
||||
"username": username,
|
||||
"password": password,
|
||||
"timeout": 30
|
||||
});
|
||||
|
||||
try {
|
||||
var response = req.post(serviceUrl + "/mac-monitor", postData);
|
||||
|
||||
if (req.getStatus() !== 200) {
|
||||
throw "HTTP " + req.getStatus() + ": " + response;
|
||||
}
|
||||
|
||||
var data = JSON.parse(response);
|
||||
|
||||
return JSON.stringify({"data": data.data});
|
||||
|
||||
} catch (error) {
|
||||
Zabbix.Log(2, "Cisco LLD Error: " + error);
|
||||
throw error;
|
||||
}
|
||||
Reference in New Issue
Block a user