🔐 candados: Gestión Segura de Secretos
Resumen Ejecutivo
candados es la herramienta central de seguridad del ecosistema ADN. Cifra y gestiona secretos con AES-256-GCM, implementando un sistema de Candado Temporal que requiere autorización explícita (5 min) antes de liberar credenciales.
Principio fundamental: Las contraseñas NUNCA deben aparecer en pantalla, logs ni archivos temporales.
⚙️ Arquitectura
- Cripto: Motor AES-256-GCM con IV aleatorio y autenticación.
- Bóveda: Persistencia cifrada en
.boveda.json(permisos 600). - MFA Temporal: Sesiones de 5 min via
.session(permisos 600). - Master Key:
.master.keylocal (permisos 600, nunca se comparte).
🚀 Comando Primario: run ★
El comando run es la forma recomendada de usar credenciales. Inyecta USR y PASS directamente en el entorno del subproceso sin imprimir nada:
# 1. Autorizar (dura 5 min)
ruby candados.rb authorize
# 2. Ejecutar comando con credenciales inyectadas
ruby candados.rb run srv-dasu:rmonla 'sshpass -p $PASS ssh $USR@host "comando"'
# Retrocompatible con variable legacy (SSHPASS, etc.)
ruby candados.rb run admindasu SSHPASS 'sshpass -e ssh root@host'
¿Qué pasa internamente?
- Descifra las credenciales de la bóveda
- Las inyecta como
USRyPASSen el entorno del subproceso - Ejecuta el comando
- Limpia las variables al terminar
- Nada se imprime en pantalla ni queda en logs
🔒 Comando: sudo
Ejecuta comandos con privilegios, resolviendo la contraseña automáticamente:
ruby candados.rb sudo tailscale set --operator=$USER
ruby candados.rb sudo apt update
La clave se busca automáticamente:
<hostname>:<usuario>:sudo(ej:ns8:rmonla:sudo)- Variantes normalizadas del hostname
- Fallback genérico:
sudo
📦 Comando Secundario: load
Para uso interactivo cuando se necesitan las variables en el shell actual. Nunca imprime la contraseña:
eval $(ruby candados.rb load srv-dasu:rmonla)
# USR y PASS están disponibles en el shell
Internamente escribe los exports a un archivo temporal (tmp/.candados_env_<hex>) con permisos 600, y a stdout solo emite el comando source + autoborrado.
Nota: Los temporales se guardan en tmp/ del repositorio (no en /tmp/) para cumplir con el principio 11 de 05_ia.md (Workspace Bounds).
🔑 Resolución Automática de Pares
Los comandos run y load detectan automáticamente el par usuario/contraseña:
| Formato de clave | USR | PASS |
|---|---|---|
srv-dasu:rmonla |
rmonla (parte después de :) |
Valor cifrado |
tailscale_dasuten_pass |
Busca tailscale_dasuten_user |
Valor cifrado |
admindasu |
Busca admindasu_user (si existe) |
Valor cifrado |
📋 Referencia Rápida
| Comando | Seguridad | Descripción |
|---|---|---|
run <clave> <cmd> |
✅ Nada expuesto | ★ PRIMARIO - Ejecuta con USR/PASS inyectados |
sudo <cmd> |
✅ Nada expuesto | Ejecuta con privilegios desde bóveda |
load <clave> |
✅ Archivo temporal 600 | Carga en shell (usar con eval) |
get <clave> |
⚠ Imprime a stdout | Obtener valor directo (usar con cuidado) |
authorize |
✅ | Abrir candado (5 min) |
set <clave> |
✅ Input sin eco | Guardar secreto |
list |
✅ | Listar claves |
🛡️ Auditoría
Archivo access.log (permisos 600) registra:
- Timestamp y Usuario del SO
- Acción:
AUTHORIZE,GET,LOAD,RUN,SUDO,LOCK,DENIED,EXPIRED - Detalle: Clave solicitada y comando ejecutado
🧠 Contexto para IA
- Siempre ejecutar
authorizeantes de operar - Usar
runcomo método primario (inyecta, no imprime) - Evitar
geten comandos automatizados (filtra en logs) - Cerrar sesión con
cerrarcuando ya no se necesite
ruby candados.rb authorize
ruby candados.rb run srv-dasu:rmonla 'sshpass -p $PASS ssh $USR@host "ls"'
ruby candados.rb cerrar
Generado siguiendo docs/prompt/documentacion.md