CreaRack-SL

API SNMP endpoints — test, interfaces, poll con autorización

Descripción

Endpoints Ninja en monitoring/api/snmp.py que permiten sondear dispositivos SNMP desde el servidor CreaRack. En sesión 107 se añadieron gates de autorización y guard de red privada.

Endpoints

POST /api/monitoring/targets/{target_id}/snmp/test

Prueba conectividad SNMP a un dispositivo.

Autorización: Requiere observatory:edit (aplicado sesión 107).

Respuesta exitosa (admin, dispositivo público):

{
  "success": true,
  "response_time_ms": 123.45
}

Respuesta — dispositivo privado (admin, pero IP privada):

{
  "success": false,
  "skipped": true,
  "reason": "private_ip"
}

Respuesta — usuario readonly (no admin):

403 Forbidden

Implementación (sesión 107):

require_perm(request, "observatory", "edit")
org, target = get_target_or_404(request, target_id)
if is_private_ip(target.ip_address):
    return {"success": False, "skipped": True, "reason": "private_ip"}
# ... SNMP test ...

GET /api/monitoring/targets/{target_id}/snmp/interfaces

Obtiene todas las interfaces SNMP de un dispositivo.

Autorización: Requiere observatory:edit (aplicado sesión 107).

Respuesta exitosa (admin, dispositivo público):

{
  "target_id": 42,
  "interfaces": [
    {"index": 1, "name": "eth0", "type": "ethernetCsmacd", "speed": 1000000000, ...},
    {"index": 2, "name": "eth1", "type": "ethernetCsmacd", "speed": 10000000000, ...}
  ]
}

Respuesta — dispositivo privado (admin, pero IP privada):

{
  "target_id": 42,
  "interfaces": [],
  "skipped": true,
  "reason": "private_ip"
}

Respuesta — usuario readonly (no admin):

403 Forbidden

POST /api/monitoring/targets/{target_id}/snmp/poll

Sondea métricas SNMP de ancho de banda en un dispositivo.

Autorización: Requiere observatory:edit (ya existía, reforzado sesión 107).

Respuesta exitosa (métricas obtenidas):

{
  "status": "up",
  "interface_count": 2,
  "samples_created": 4,
  "response_time_ms": 45.67
}

Respuesta — fallo SNMP (no alcanza):

{
  "status": "down",
  "error": "Failed to get SNMP data"
}

Nota sesión 107: Antes devolvía {"status": "error"} (valor fuera de STATUS_CHOICES). Ahora "down" es válido.


Cambios sesión 107

1. Gate de autorización (require_perm)

Los 3 endpoints ahora requieren require_perm(request, "observatory", "edit"):

from core.utils import require_perm

def test_snmp_connection(request, target_id: int):
    require_perm(request, "observatory", "edit")
    # ...

Si el usuario no tiene permiso → 403 Forbidden.

2. Guard de red privada (is_private_ip)

snmp/test e snmp/interfaces no tenían el guard is_private_ip(target.ip_address) que sí usa snmp/poll. Lo añadido:

if is_private_ip(target.ip_address):
    return {"success": False, "skipped": True, "reason": "private_ip"}

Cierra el vector de escaneo de red interna. Dispositivos privados se monitorean vía Local Agent.

3. Status inválido en snmp/poll

Antes: {"status": "error", "error": "Failed..."} Después: {"status": "down", "error": "Failed..."}

El estado "down" está en el modelo MonitoringTarget.STATUS_CHOICES.

Fuentes de datos

Cada endpoint construye una instancia SNMPService a partir de target.config (credenciales SNMP, versión, etc.) y target.ip_address.

  • Modelo: monitoring.models.MonitoringTarget
  • Servicio: monitoring.services.snmp_service.SNMPService
  • Escritura de muestras: monitoring.services.MetricsWriter

Errores y logging

Sesión 107: Los errores SNMP ahora se loguean (antes mudos):

except Exception as e:
    logger.warning("SNMP test_connection failed for %s: %s", self.host, e)
    return {"success": False, "error": "SNMP connection failed"}

El mensaje devuelto al cliente es genérico (no str(exc)), pero el log interno registra la excepción para debugging.

Testing

Tests en tests/api/test_monitoring.py:

  • TestSnmpProbeAuthorization.test_snmp_test_unauthenticated() → 401/403
  • TestSnmpProbeAuthorization.test_readonly_cannot_snmp_test() → 403
  • TestSnmpProbeAuthorization.test_readonly_cannot_snmp_interfaces() → 403
  • TestSnmpProbeAuthorization.test_admin_snmp_test_skips_private() → 200 + reason=private_ip
  • TestSnmpProbeAuthorization.test_admin_snmp_interfaces_skips_private() → 200 + empty interfaces

Véase también

  • [[entity—monitoring—service—snmp-service]]
  • [[feature—monitoring—sesion-107-auditoria-suprema-sub-area-2]]
  • [[concept—saas—multi-tenancy]]
  • [[concept—saas—authorization]]