Resumen
Modelo Django que representa un perfil de configuración para un equipo de red (switch, SAI, AP WiFi, firewall, etc.). Almacena credenciales de acceso (SNMP v2c/v3, SSH) y metadatos del dispositivo (vendor, modelo, interfaces, OIDs).
Cifrado en reposo (T1): Las credenciales SNMP (snmp_community, snmp_v3_auth_key, snmp_v3_priv_key) y SSH (ssh_password_encrypted) se cifran automáticamente en save() con Fernet vía CredentialManager. Nunca quedan en plaintext en la BD.
Estructura
Campos principales
| Campo | Tipo | Descripción | Cifrado |
|---|---|---|---|
organization | FK → Organization | Tenant (multi-tenancy RLS) | No |
ip_address | CharField(15) | Dirección IP del equipo | No |
hostname | CharField(255) | Nombre FQDN o alias | No |
vendor | CharField(100) | Vendor (Cisco, Juniper, etc.) | No |
model | CharField(255) | Modelo del dispositivo | No |
serial_number | CharField(100) | Número de serie | No |
location | TextField | Ubicación física | No |
supports_snmp | BooleanField | ¿Responde SNMP? | No |
supports_ssh | BooleanField | ¿Permite SSH? | No |
supports_netconf | BooleanField | ¿NETCONF disponible? | No |
supports_restconf | BooleanField | ¿RESTCONF disponible? | No |
| SNMP v2c/v3 | |||
snmp_version | CharField(10) | “v2c” o “v3” | No |
snmp_community | TextField | Community string SNMP v2c | SÍ (Fernet) |
snmp_v3_username | CharField(100) | USM username | No |
snmp_v3_auth_protocol | CharField(20) | MD5, SHA, SHA256, etc. | No |
snmp_v3_auth_key | TextField | Auth passphrase v3 | SÍ (Fernet) |
snmp_v3_priv_protocol | CharField(20) | DES, AES128, AES256, etc. | No |
snmp_v3_priv_key | TextField | Privacy passphrase v3 | SÍ (Fernet) |
| SSH | |||
ssh_port | IntegerField | Puerto SSH (default 22) | No |
ssh_username | CharField(100) | Usuario SSH | No |
ssh_password_encrypted | TextField | Contraseña SHA256 + salt | SÍ (Fernet) |
| Metadatos SNMP | |||
snmp_sys_descr | TextField | OID 1.3.6.1.2.1.1.1.0 | No |
snmp_sys_object_id | CharField(100) | OID 1.3.6.1.2.1.1.2.0 | No |
snmp_uptime | BigIntegerField | Uptime en centisegundos | No |
last_verified | DateTimeField | Último polling exitoso | No |
linked_monitoring_target_id | FK → MonitoringTarget | Target vinculado (observatory) | No |
created_at | DateTimeField | Timestamp creación | No |
updated_at | DateTimeField | Timestamp actualización | No |
Accesores de descifrado (T1)
Properties que descifran las credenciales en el punto de uso. Devuelven plaintext (o vacío si token corrupto):
snmp_community_plain: descifrasnmp_communityo devuelve tal cual si es plaintext legado.snmp_v3_auth_key_plain: descifrasnmp_v3_auth_key.snmp_v3_priv_key_plain: descifrasnmp_v3_priv_key.get_ssh_password(): método existente — descifrassh_password_encrypted.
Constante: SNMP_SECRET_FIELDS = ("snmp_community", "snmp_v3_auth_key", "snmp_v3_priv_key") — lista de campos cifrados, reutilizada por reencrypt_credentials.
Métodos clave
save(*args, **kwargs)
Sobrescrito (T1). Antes de guardar:
for field in self.SNMP_SECRET_FIELDS:
setattr(self, field, CredentialManager.encrypt_if_plain(getattr(self, field)))
super().save(*args, **kwargs)
Idempotente: valores ya cifrados (tokens Fernet) no se re-cifran. SSH password ya es cifrado por set_ssh_password().
update_last_verified()
Actualiza timestamp de último polling exitoso (usado por servicios de discovery).
Puntos de lectura (descifrado automático)
Las credenciales SNMP se descifran en estos puntos de uso exactos:
- SNMPService.from_config(): descifra community/v3 keys del dict
configantes de pasar a pysnmp. - DeviceDiscoveryService.build_snmp_auth_from_profile(): descifra credenciales del profile.
- Endpoints Deep-discover (
network/api/discovery.py,monitoring/api/targets.py): usansnmp_community_plain, etc. - WS consumer _send_targets(): descifra antes de serializar para el Agente.
- REST sentinel.get_agent_targets(): idem.
- Modal Config (network/api/assign.py): descifra para mostrar al usuario.
- Provisioning (
monitoring/services/provisioning.py): extrae credenciales (cifradas) al construirMonitoringTarget.config. - DeviceProfileOut resolver (graphql): descifra
snmp_communityen la respuesta (statu quo, deuda A4 sa1).
Relaciones
- → Organization: FK multi-tenancy (RLS).
- → MonitoringTarget (via
linked_monitoring_target_id): Un profile puede estar vinculado a un target de monitoreo (relación 1:0..1). - ← MonitoringTarget.device_profile (via FK en monitoring): Un target puede referenciar un profile (aunque no siempre).
- ← ScanSession: Un profile se descubre generalmente via una sesión de scan.
Migraciones (T1)
network/0049_alter_deviceprofile_snmp_community_and_more
Altera los 3 campos SNMP de CharField a TextField (el token Fernet es más largo que 255).
network/0050_encrypt_snmp_credentials
Cifra todos los DeviceProfile existentes en la BD.
- Idempotente:
encrypt_if_plainsalta valores ya cifrados. - Reverse: no-op deliberado (descifrar re-expondría secretos).
- Dokploy ejecuta automáticamente al desplegar.
Seguridad
- Cifrado en reposo: Fernet (AES-128 + HMAC-SHA256), administrado por
CredentialManager. - Rotación de claves: soportada vía command
reencrypt_credentials. - Plaintext legado: tolerante;
decrypt_or_passthroughdevuelve valores no-token tal cual. - Token corrupto: degrada a
""(nunca filtra ciphertext). - Multi-instalación: credenciales específicas de la clave; backup/restore cifra al guardar.
Ejemplos de uso
Crear un profile SNMP v2c
from network.models import DeviceProfile
profile = DeviceProfile(
organization=org,
ip_address="10.0.1.5",
hostname="core-switch-01",
vendor="Cisco",
supports_snmp=True,
snmp_version="v2c",
snmp_community="s3cr3t", # Será cifrado en save()
)
profile.save()
# Leer en claro:
print(profile.snmp_community_plain) # "s3cr3t"
print(profile.snmp_community) # "gAAAAA..." (token Fernet)
Usar en un poller SNMP
from monitoring.services.snmp_service import SNMPService
snmp = SNMPService.from_config(
ip=profile.ip_address,
config=profile_config_dict, # Dict con creds cifradas
)
# SNMPService.from_config descifra automáticamente
result = snmp.get("1.3.6.1.2.1.1.1.0")
Véase también
- [[entity—monitoring—model—monitoring-target]] — target de monitoreo vinculado
- [[entity—core—service—credential-manager]] — servicio Fernet de cifrado/descifrado
- [[feature—security—t1-cifrado-snmp-reposo]] — tanda T1 de cifrado SNMP
- [[concept—saas—multi-tenancy]] — RLS por organization
- [[concept—network—device-inventory]] — inventario de dispositivos de red