Rotación de Clave de Cifrado de Credenciales
Descripción
Procedimiento operacional para rotar la clave de cifrado de credenciales Fernet en CreaRack Pro, manteniendo la integridad de todos los datos encriptados existentes sin downtime.
Cuándo ejecutar
- Rotación preventiva: Anualmente o cada 6 meses (según política de seguridad).
- Compromiso sospechado: Si existe evidencia de que la clave ha sido expuesta.
- Cambio de gestión: Al transferir la instalación a nuevo responsable de seguridad.
- Actualización de key rotation policy: Si se cambian los requisitos de rotación.
Requisitos
- Acceso SSH/shell a servidor de producción.
- Permisos para ejecutar comandos Django en el contenedor app.
- Variable de entorno
CREDENTIALS_ENCRYPTION_KEYeditable en Dokploy (o.envlocal). CREDENTIALS_LEGACY_KEYSconfigurable (lista colon-separated).- BD PostgreSQL accesible desde el contenedor (standard).
- Backup reciente de BD (ejecutar antes de este procedimiento como precaución).
Pasos
Fase 1: Preparación
-
Generar nueva clave Fernet:
python -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())" # Output: gAAAAABnFhZZA6-K3... (32 bytes, base64)Guardarlo en un lugar temporal seguro (p.ej. KeePass, vault).
-
Crear backup de BD (como precaución):
docker exec crearacksql pg_dump -U crearacksql > backup_pre_rotation_$(date +%Y%m%d_%H%M%S).sql -
Validar acceso a settings:
- Si usa Dokploy: acceder al dashboard, ir a
Environment. - Si usa
.envlocal: verificar que el archivo sea editable.
- Si usa Dokploy: acceder al dashboard, ir a
Fase 2: Actualizar claves en configuración
-
Mover clave actual a legacy:
- Obtener el valor actual de
CREDENTIALS_ENCRYPTION_KEY. - Añadirlo a
CREDENTIALS_LEGACY_KEYS(formato:clave1:clave2:clave3).
Ejemplo:
CREDENTIALS_ENCRYPTION_KEY = gAAAAABnFhZZA6-K3... (VIEJA, será legacy) CREDENTIALS_LEGACY_KEYS = "" (antes vacío) # DESPUÉS: CREDENTIALS_ENCRYPTION_KEY = gAAAAABnFhZZA6-K3... (NUEVA, generada en paso 1) CREDENTIALS_LEGACY_KEYS = "gAAAAABnFhZZA6-K3..." (VIEJA, para descifrado de datos históricos) - Obtener el valor actual de
-
Desplegar cambios (via Dokploy o manual):
- Si Dokploy: guardar cambios, aguardar redeploy automático (típicamente <5 min).
- Si manual: actualizar
.env, reiniciar contenedordocker-compose restart app.
Validar deployment:
# Esperar a que el contenedor esté ready docker logs crearacksql_app | tail -20 # Buscar "Running on ..."
Fase 3: Re-cifrar datos existentes
-
Ejecutar command en modo —dry-run (validación):
docker exec crearacksql python manage.py reencrypt_credentials --dry-runOutput esperado:
[reencrypt_credentials] rows scanned=1245 reencrypted=892 failed=0 [reencrypt_credentials] DeviceProfile: 234 rows scanned, 189 reencrypted [reencrypt_credentials] MonitoringTarget: 567 rows scanned, 403 reencrypted [reencrypt_credentials] StoredCredential: 234 rows scanned, 189 reencrypted ...Validar que:
failed=0(ningún error).reencrypted > 0(hay datos que fueron re-cifrados, lo que esperamos).- No hay excepciones en los logs.
-
Ejecutar en producción (sin
--dry-run):docker exec crearacksql python manage.py reencrypt_credentialsSalida similar a dry-run, pero esta vez actualiza la BD.
Tiempo estimado:
- Base de datos típica (1k-10k credenciales): 10-60 segundos.
- Si toma más: es normal (DB I/O), monitorear en paralelo con
docker stats.
-
Validar en logs:
docker logs crearacksql_app | grep "reencrypt_credentials" | tail -20Buscar mensaje final:
[reencrypt_credentials] ✓ completed successfully.
Fase 4: Verificación post-rotación
-
Verificar polling SNMP (validar que credenciales siguen siendo válidas):
- Acceder al dashboard.
- Navegar a Network → Device Profiles.
- Seleccionar un profile con SNMP v2c/v3.
- Ejecutar “Test SNMP” o “Refresh Interfaces”.
- Debe responder sin error (las credenciales descifran correctamente).
-
Verificar monitoreo (targets siguen recolectando métricas):
- Ir a Monitoring → Targets.
- Seleccionar un target activo.
- Verificar que last polling time es reciente (< 2 min).
- Métricas deben estar actualizándose.
-
Revisar logs de aplicación:
docker logs crearacksql_app | grep -i "decrypt\|encrypt\|credential" | tail -50No deben haber errores como:
Invalid tokenDecryption failedKey not found
Fase 5: Limpieza (opcional, después de días/semanas)
- Opcionalmente, limpiar legacy keys (después de verificar estabilidad por ≥1 semana):
- Si todos los datos han sido re-cifrados con la nueva clave,
CREDENTIALS_LEGACY_KEYSpuede ser vaciado. - Pero: es recomendable mantenerlo por ≥3 meses por si hay rollback de BD (disaster recovery).
CREDENTIALS_LEGACY_KEYS = "" (limpiar)- Redeploy (paso 5).
- Si todos los datos han sido re-cifrados con la nueva clave,
Rollback
Si algo falla o necesita revertir:
Antes del paso 7 (aún no re-cifrado)
- Revertir
CREDENTIALS_ENCRYPTION_KEYyCREDENTIALS_LEGACY_KEYSa valores anteriores. - Redeploy.
- Todo sigue funcionando (datos aún están cifrados con clave original).
Después del paso 7 (ya re-cifrado)
- No hay rollback fácil: los datos ya están con nueva clave.
- Opción: restaurar BD desde backup del paso 2.
Luego revertir claves y redeploy.docker exec crearacksql psql -U crearacksql < backup_pre_rotation_YYYYMMDD_HHMMSS.sql
Troubleshooting
| Síntoma | Causa | Solución |
|---|---|---|
reencrypt_credentials devuelve failed > 0 | Token Fernet corrupto (raro) o clave no en legacy chain | Verificar CREDENTIALS_LEGACY_KEYS incluye todas las claves históricas. Ver logs detallados. |
| SNMP test falla post-rotación | Credenciales aún en plaintext (migración incompleta) o token no descifra | Revisar que decrypt_or_passthrough está siendo usado en pollers. Ejecutar command nuevamente. |
| BD no contesta tras rotación | Timeout DB | Aumentar timeout en --timeout del command (si aplica). Verificar conectividad SSH/DB. |
| Dokploy no redeploy automático | Settings cambios no detectados | Forzar redeploy manual en dashboard o CLI. |
Automatización (opcional)
Para instalaciones con rotación frecuente, considerar cron job:
# /etc/cron.d/crearacksql_credential_rotation (trimestral, p.ej. primer domingo del trimestre)
0 2 1 */3 0 root docker exec crearacksql python manage.py reencrypt_credentials >> /var/log/crearacksql/credential_rotation.log 2>&1
Véase también
- [[entity—core—service—credential-manager]]
- [[entity—network—model—device-profile]]
- [[entity—monitoring—model—monitoring-target]]
- [[feature—security—t1-cifrado-snmp-reposo]]
- [[concept—security—credential-encryption]]