ADR: Eliminar python-nmap (abandonada) → subprocess + xml.etree stdlib
ADR: Eliminar python-nmap (abandonada) → subprocess + xml.etree stdlib
Contexto
discover_nmap en network/services/device_discovery/service.py es el método de la Stage 1.5 del pipeline de Auto-Provision que realiza OS detection y service detection mediante el binario nmap. Hasta esta sesión dependía del wrapper Python python-nmap 0.7.1.
En la sesión 30 del Supercontexto (2026-04-26), durante el cierre del Cluster J2 de Fase B post-audit, se detectó que python-nmap llevaba 4 años sin releases (último: 0.7.1, octubre 2021) y fue clasificada como deuda técnica activa. Se evaluaron 3 alternativas antes de decidir.
Alternativas evaluadas
| Alternativa | Licencia | Estado | Decisión |
|---|---|---|---|
python-nmap 0.7.1 (actual) | GPL-3.0 | Abandonada — sin releases desde oct 2021 | ❌ Eliminar |
python3-nmap (nmap3) | GPL-3.0 | Sin releases > 1 año | ❌ Descartada — no mejora ni licencia ni mantenimiento |
python-libnmap | Apache 2.0 | Soporte oficial solo hasta Python 3.8; proyecto en Python 3.14 | ❌ Descartada — riesgo de incompatibilidad futura |
subprocess + xml.etree.ElementTree (stdlib) | PSF (parte de CPython) | Mantenida por upstream Python indefinidamente | ✅ Elegida |
Decisión
Migrar a stdlib: invocar el binario nmap directamente con subprocess.run y parsear su salida XML con xml.etree.ElementTree.
Rationale
Las tres alternativas wrapper evaluadas están todas en estado de mantenimiento limitado o nulo, similar al python-nmap original. Reemplazar una dependencia abandonada por otra con los mismos síntomas no resuelve la deuda — solo la pospone. La stdlib es mantenida por upstream Python de forma indefinida y no introduce ninguna dependencia externa nueva.
Implementación
Archivo: network/services/device_discovery/service.py — método discover_nmap
Cambios clave:
- Detección del binario en PATH con
shutil.which("nmap")— falla con error claro si no está disponible. - Invocación:
nmap -oX - <args> <ip>viasubprocess.run(capture_output=True, text=True, timeout=120). - Fallback preservado: intenta
-sV -T4 -F --version-light; si falla, reintenta con-sV -T4 -F. - Timeout explícito de 120 segundos (antes implícito en
python-nmap). - Parser XML manual con
xml.etree.ElementTree:host/hostnames/hostname[@name]→hostnamehost/os/osmatch[@name]→os_familyhost/os/osmatch/osclass[@osfamily]→nmap_fingerprinthost/ports/port[@protocol=tcp][state/@state=open]→open_ports+services
- Firma de salida idéntica: mismo dict con claves
os_family,os_vendor,hostname,open_ports,services,nmap_fingerprint. Sin breaking changes para los consumidores del método.
Otros archivos modificados:
| Archivo | Cambio |
|---|---|
requirements.txt | Línea python-nmap>=0.7.1 eliminada |
core/licenses_data/python.py | Entrada python-nmap removida del inventario de licencias |
core/licenses_data/infrastructure.py | Descripción del binario nmap actualizada: “invoked via subprocess server-side; XML output parsed with stdlib xml.etree” |
CLAUDE.md (tabla de red) | python-nmap 0.7.1 → nmap (binario) 7.x con anotación del método |
Smoke test
Parser validado con XML sintético (hostname Cisco IOS + TCP ports + filtrado de UDP/closed states). Test real con binario activo se delega a STAGE/PROD (requiere nmap en PATH y host accesible).
Consecuencias
Positivas:
- Deuda técnica eliminada permanentemente, sin sustituirla por otra deuda futura.
- Cero dependencias externas para el scanner — solo stdlib + binario de sistema.
- Control total sobre el parser XML: filtros explícitos (solo TCP, solo
state=open). - Timeout explícito y detección de binario ausente con mensajes de error claros.
A vigilar:
- El binario
nmapdebe estar en PATH en todos los entornos (Local Agent, STAGE, PROD). Ya estaba documentado como dependencia de infraoperator-installedencore/licenses_data/infrastructure.py. - Cambios futuros en el formato XML de salida de
nmaprequerirán actualizar el parser manualmente (sin abstracción de wrapper).
Contexto Supercontexto
- Sesión: 30 (2026-04-26)
- Cluster cerrado: J2 (de Fase B post-audit Supercontexto)
- Clusters Fase B pendientes tras esta sesión: C (auth/crypto, requiere tests STAGE) y F (Redis/huey 3.0, esperar 1-2 meses madurez)
- Versión: v1.0.58+
Véase también
- [[crearack—network—discovery]]
- [[crearack—network—network-tools]]
- [[entity—network—model—deviceprofile]]
- [[entity—network—model—vendorprofile]]