Descripción general
En s114 (2026-06-08), el Terminal ahora hereda automáticamente las credenciales SSH que se proporcionan durante el descubrimiento Auto-Provision. Antes, esas credenciales se usaban solo para verificar conectividad durante el discovery y luego se descartaban, obligando al usuario a re-teclearlas en Terminal.
Cambio de comportamiento:
- Antes: Descubres un dispositivo en Auto-Provision → ingresas usuario/contraseña SSH para escaneo → credenciales se descartan → en Terminal repites los datos.
- Ahora: Descubres dispositivo → ingresas credenciales → si SSH funciona, se guardan cifradas en
DeviceProfile→ al conectar desde Terminal, vienen pre-rellenadas y el usuario solo clickea “Conectar”.
Flujo técnico
1. Persistencia en Auto-Provision (provision_stages.py)
Cuando provision_device() ejecuta discover_ssh() y el SSH tiene éxito:
- Se capturan
ssh_usernameyssh_password(string en claro, en tránsito). - Antes de guardar en BD, se cifran con Fernet vía
CredentialManager.encrypt_credential(). - Se almacenan como
ssh_password_encrypteden el nuevo campo deDeviceProfile. - Regla importante: un re-discovery sin credenciales SSH (p.ej., solo SNMP) no borra las ya guardadas. Solo actualiza si hay nuevas credenciales válidas.
2. Nuevo endpoint de descifrado (GET /auto-provision/profiles/{profile_id}/credentials)
- Ruta:
/api/network/auto-provision/profiles/{profile_id}/credentials - Permisos:
require_perm(network, edit)+ validación de organización (RLS). - Respuesta:
{ "has_credentials": true, "ip": "10.5.5.5", "username": "admin", "password": "contraseña_descifrada", "port": 22 } - Si no hay credenciales: devuelve
has_credentials: false+ campos vacíos (no inventa datos).
3. Integración en Terminal UI (terminal.js)
La función quickConnectHost() ahora es async:
async quickConnectHost(ip, name, profileId, hasStored) {
// ... pre-rellena IP y puerto ...
if (hasStored && profileId) {
const creds = await ApiService.get(`/api/network/auto-provision/profiles/${profileId}/credentials`);
if (creds.has_credentials) {
document.getElementById('manual-ssh-username').value = creds.username;
document.getElementById('manual-ssh-password').value = creds.password;
}
}
this.openManualConnectionModal();
}
4. Contexto en la plantilla (templates/terminal/index.html)
Los dispositivos detectados ahora exponen:
profile_id: ID del DeviceProfile para llamar al endpoint.has_stored_ssh: propiedad@propertyde DeviceProfile que verificassh_username+ssh_password_encrypted.
Se actualiza el atributo data-args de los elementos:
<li data-action="TerminalApp.quickConnectHost"
data-args='["10.5.5.5", "Router-A", 123, true]'>
Cifrado de credenciales
Las credenciales se cifran con la misma estrategia que el management_config de racks:
- Algoritmo: Fernet (AES-128 simétrica).
- Almacén de claves:
core.security.CredentialManager. - Descifrado: bajo demanda via
profile.get_ssh_password()(solo si existessh_password_encrypted).
Seguridad:
- Las claves en la BD están siempre cifradas.
- Solo se descifran en respuesta a una petición gateada por
require_perm(network, edit). - El usuario debe tener permiso de edición en Network para acceder a las credenciales en claro.
Migración de base de datos
Migración aplicada: network/0047 (2026-06-08 10:52).
migrations.AddField(model_name='deviceprofile', name='ssh_username', ...)
migrations.AddField(model_name='deviceprofile', name='ssh_password_encrypted', ...)
Retrocompatibilidad: Los dispositivos ya existentes no heredan automáticamente credenciales antiguas (nunca se guardaron). Para que uno existente tenga credenciales, hay que re-ejecutar Auto-Provision con las claves en ese dispositivo.
Testing
Test suite: tests/api/test_terminal_hosts.py::TestProfileSshCredentials:
test_roundtrip_decrypts(): valida cifrado/descifrado.test_terminal_host_exposes_has_stored_ssh(): verifica queterminal_hosts()expone la bandera.test_endpoint_returns_decrypted_creds(): valida respuesta del endpoint.test_endpoint_no_creds(): sin credenciales → devuelve empty/false.test_viewer_cannot_get_credentials(): RLS + permisos → viewer rechazado (403).
Impacto en UX
Para el usuario final:
- Descubre un dispositivo en Auto-Provision → ingresa credenciales SSH.
- Si SSH funciona, se guardan automáticamente.
- En Terminal, elige el dispositivo detectado → se pre-rellena usuario/contraseña → escribe comando.
- Ahorro: ~30 segundos por conexión si hay 10 dispositivos.
Titulares en RELEASE_NOTES (s114):
Ahora hereda las credenciales SSH que diste en Auto-Provision… Si el SSH funcionó durante el descubrimiento, esas credenciales se guardan cifradas. Al conectarte desde el Terminal a ese dispositivo, vienen ya rellenadas.
Véase también
- [[entity—network—endpoint—get-profile-credentials]]
- [[entity—network—model—device-profile]]
- [[feature—terminal—detected-devices-support]]
- [[concept—network—auto-provision]]
- [[concept—saas—encryption-and-secrets]]