[Core/Infra] Provisionamiento SSH en pc-dasu0 y unificación Nginx tailscale

This commit is contained in:
Ricardo Monla
2026-03-14 10:29:54 -03:00
parent e554bb5d0d
commit b13a389568
50 changed files with 2702 additions and 561 deletions
+91 -40
View File
@@ -1,55 +1,106 @@
# 🔐 ns8-candados: Gestión de Secretos y Autorización SSH
# 🔐 candados: Gestión Segura de Secretos
## Resumen Ejecutivo
`ns8-candados` es una herramienta de seguridad robusta diseñada para centralizar, cifrar y gestionar secretos operativos del ecosistema `srv-ns8`. Utiliza el algoritmo industrial **AES-256-GCM** para garantizar la integridad y confidencialidad de las credenciales. Su arquitectura implementa un sistema de **Candado Temporal (MFA)** que requiere una autorización explícita para liberar secretos, protegiendo la información incluso si el servidor se ve comprometido.
`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.
---
## 🔍 Análisis Estructural
- **Tipo de Proyecto**: Utilidad de seguridad CLI escrita en Ruby.
- **Organización**: Estructura modular centrada en la protección del dato:
- `Cripto`: Motor criptográfico AES-256-GCM con IV aleatorio.
- `Boveda`: Persistencia cifrada en `.boveda.json`.
- **MFA / Autorización**: Sistema de sesiones temporales basadas en archivos con permisos restringidos.
- **Archivos Fundamentales**:
- `ns8-candados.rb`: Lógica central.
- `.master.key` (Local): La semilla de cifrado (permisos 600).
- `.boveda.json`: Almacén de secretos cifrados (permisos 600).
- `.session`: Token de autorización temporal (vida: 5 min, permisos 600).
## ⚙️ 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.key` local (permisos 600, nunca se comparte).
## ⚙️ Configuración y Dependencias
- **Tecnologías**: Ruby, OpenSSL.
- **Seguridad de Archivos**: Todos los archivos sensibles se manejan con `chmod 600`, asegurando que **solo el propietario** de la herramienta pueda operar.
- **Comandos de Gestión**:
- `ruby ns8-candados.rb authorize`: **Abre el candado**. Habilita el acceso a secretos durante 5 minutos.
- `ruby ns8-candados.rb cerrar`: **Cierra el candado** manualmente eliminando la sesión activa.
- `ruby ns8-candados.rb list`: Lista las claves guardadas (requiere autorización).
- `ruby ns8-candados.rb get <clave>`: Recupera el valor descifrado (requiere autorización).
## 🚀 Comando Primario: `run` ★
## 🛡️ Auditoría (logging)
La herramienta mantiene un archivo `access.log` en su directorio local que registra de forma inmutable:
- **Timestamp**: Fecha y hora exacta de la acción.
- **Usuario**: El usuario del sistema operativo que ejecutó el comando.
- **Acción**: `AUTHORIZE`, `GET`, `LOCK`, `DENIED` o `EXPIRED`.
- **Detalle**: Nombre de la clave solicitada (solo en comandos `get`).
El comando `run` es la forma **recomendada** de usar credenciales. Inyecta `USR` y `PASS` directamente en el entorno del subproceso sin imprimir nada:
El archivo tiene permisos `600` para asegurar que solo el propietario pueda auditar los accesos.
```bash
# 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?**
1. Descifra las credenciales de la bóveda
2. Las inyecta como `USR` y `PASS` en el entorno del subproceso
3. Ejecuta el comando
4. Limpia las variables al terminar
5. **Nada se imprime en pantalla ni queda en logs**
## 🔒 Comando: `sudo`
Ejecuta comandos con privilegios, resolviendo la contraseña automáticamente:
```bash
ruby candados.rb sudo tailscale set --operator=$USER
ruby candados.rb sudo apt update
```
La clave se busca automáticamente:
1. `<hostname>:<usuario>:sudo` (ej: `ns8:rmonla:sudo`)
2. Variantes normalizadas del hostname
3. Fallback genérico: `sudo`
## 📦 Comando Secundario: `load`
Para uso interactivo cuando se necesitan las variables en el shell actual. **Nunca imprime la contraseña:**
```bash
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.
## 🔑 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
- **Flujo Obligatorio**: Los agentes de IA DEBEN ejecutar `authorize` antes de intentar recuperar cualquier clave.
- **Captura Segura**: Capturar siempre la salida en variables silenciadas:
```bash
ruby tools/ns8-candados/ns8-candados.rb authorize
PASS=$(ruby tools/ns8-candados/ns8-candados.rb get clave)
# Operar y luego cerrar:
ruby tools/ns8-candados/ns8-candados.rb cerrar
```
## 🚀 Próximos Pasos
1. **Siempre** ejecutar `authorize` antes de operar
2. **Usar `run`** como método primario (inyecta, no imprime)
3. **Evitar `get`** en comandos automatizados (filtra en logs)
4. Cerrar sesión con `cerrar` cuando ya no se necesite
### Propuestas de Mejora
- **Auditoría**: Implementar un `access.log` para trazar quién y cuándo abrió el candado.
- **Notificación**: Enviar un mensaje (ej. Telegram/Mail) cada vez que se ejecute `authorize`.
```bash
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*