Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
5.0 KiB
Arquitectura de inventario — menú "Equipos"
Diseño del módulo Equipos de Project. Se trajo de linkedtrack.linkedcorp.net (que sigue como
producto aparte, sin cambios) y se reescribió siguiendo las reglas de Project: mismo login, roles,
auditoría, UI Fluent y una sola base project_linkedcorp.
Decisión de fondo
| Opción | Veredicto |
|---|---|
| Servidor GLPI completo | Descartado: demasiada administración para solo inventariar. |
| Agente 100% propio | Descartado: reescribir el sondeo de hardware (WMI, EDID, SNMP) es frágil y caro. |
| Agente GLPI oficial + colector propio dentro de Project | Elegido. El agente recolecta; Project recibe, guarda y muestra. |
Flujo
GLPI Agent (cada PC/servidor) --POST inventario--> https://project.linkedcorp.net/api/inventory
(ingest.js: token -> inflar -> parsear JSON/XML
-> normalizer.js -> upsert por deviceid
-> diff en device_changes)
Navegador (superadmin/admin/it_manager) --JWT--> /api/devices -> menú "Equipos"
- Handshake: el agente primero manda un
contact(JSON) oPROLOG(XML). Se responde sin guardar nada ({"status":"ok","expiration":"24"}o<REPLY><RESPONSE>SEND</RESPONSE>…). - Ingesta autenticada por token, no por JWT: tabla
inventory_tokens(solo hash sha256). El agente lo manda como contraseña Basic (user/passworddelagent.cfg),Bearer,X-Ingest-Tokeno?token=. Sin token válido →401. - Rutas:
POST /api/inventory(propia; pasa por el Custom Location/apide NPM sin cambios) y aliasPOST /front/inventory.php(ruta nativa de GLPI). Se montan ANTES deexpress.jsonporque usan cuerpo crudo. - Límites: cuerpo máx. 15 MB (
INVENTORY_MAX_BYTES), inflado máx. 4× (anti zip-bomb). - Upsert por
deviceid(estable), nunca por hostname. Componentes se reemplazan completos en una transacción; el diff (RAM, disco agregado/retirado, software instalado/desinstalado, SO, hostname) queda endevice_changes. - Baja lógica:
status = retired; un reporte nuevo NO reactiva un equipo dado de baja. - Crudo para depurar: último reporte por equipo en
storage/inventories/<hash>.json|xml(se sobrescribe; descargaGET /api/devices/:id/raw).
Normalización
backend/src/modules/devices/normalizer.js: el JSON nativo y el XML (en mayúsculas) comparten
nombres de campo, así que el XML se pasa a minúsculas y ambos usan el mismo mapeo. Todo campo
ausente queda null (el formato varía por versión del agente y SO). Tipo de equipo
(desktop/laptop/server/virtual/printer/network/other) se infiere de chassis_type, vmsystem,
nombre del SO e itemtype. Lo que no tiene columna (impresoras/red SNMP, antivirus, video,
batería) se guarda en devices.extra_json.
Instalar el agente en un equipo
- Superadmin/admin: menú Equipos → Agentes → Generar token (se muestra una sola vez).
- En el equipo, instalar GLPI Agent (MSI en Windows;
.deb/.rpm/tarball en Linux) con:Windows (instalador):server = https://project.linkedcorp.net/api/inventory user = project password = <token> tag = <opcional>SERVER=… USER=project PASSWORD=<token>. - Forzar un envío:
glpi-agent --force(Linux) / "Forzar inventario" en la página del agente (http://localhost:62354) en Windows. El equipo aparece en Equipos al primer POST.
Instalador con un clic (Windows)
Equipos → Agentes → "Instalador para Windows": genera instalar-glpi-agent.bat en el navegador con
SERVER=<origen>/api/inventory, USER=project, PASSWORD=<token> y TAG opcional. El .bat se
auto-eleva, descarga GLPI-Agent-<ver>-x64.msi de GitHub (versión fijada en
frontend/src/pages/Equipos/agentInstaller.js#GLPI_AGENT_VERSION; o usa el .msi que esté junto al
.bat), instala con msiexec /qn y RUNNOW=1, y verifica que el servicio glpi-agent corra. El
token solo se conoce al crearlo, por eso el .bat se genera en la pantalla y no en el servidor.
Antes de instalar, el .bat verifica el token (POST de prueba: 400 válido, 401 inválido, 000 sin
conexión) y se detiene si no es válido; después fuerza la configuración en el registro (cubre equipos que
ya tenían el agente). Proceso por cliente: generar UN token en su Project → descargar el .bat desde ahí →
ejecutarlo en cada PC.
Linux: usar el instalador oficial glpi-agent-<ver>-linux-installer.pl --server=… --user=… --password=….
Pendientes / por verificar con un agente real
- Confirmar que el agente acepta la respuesta del handshake tal cual (si no, ajustar
ingest.js). - Capturar un JSON real (
glpi-agent --local=/tmp/inv --json) y contrastar campos connormalizer.js(hoy basado en el formato documentado del agente). - Impresoras/red por SNMP (
netinventory): solo se guarda lo básico +extra_json; falta una vista propia cuando haya un caso real. - Panel de impresoras con contador de páginas/tóner y export CSV: fase 2.