diff --git a/04_SEGURIDAD/secretos.md b/04_SEGURIDAD/secretos.md index 355b789..bf5f943 100644 --- a/04_SEGURIDAD/secretos.md +++ b/04_SEGURIDAD/secretos.md @@ -5,205 +5,266 @@ --- -## Estado Actual: Triple Gestión +## Arquitectura de Secretos -**PROBLEMA CRÍTICO:** Actualmente existen tres fuentes de secretos sin sincronización. +### Principio Fundamental + +> **DECK y CORP son instancias autónomas. Deben operar independientemente de ARCHITECT.** + +ARCHITECT es el constructor/coordinador. DECK y CORP son instancias diseñadas para trabajar solas. + +### Modelo de Gestión ``` ┌─────────────────────────────────────────────────────────────────┐ -│ FUENTES DE SECRETOS │ +│ ARCHITECT │ +│ (Constructor) │ │ │ -│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ -│ │ Infisical │ │ creds_* │ │ .env │ │ -│ │ (central) │ │ (PostgreSQL)│ │ (archivos) │ │ -│ └─────────────┘ └─────────────┘ └─────────────┘ │ -│ │ │ │ │ -│ ▼ ▼ ▼ │ -│ ┌─────────────────────────────────────────────────────────┐ │ -│ │ ❌ SIN SINCRONIZACIÓN - Riesgo de inconsistencia │ │ -│ └─────────────────────────────────────────────────────────┘ │ -└─────────────────────────────────────────────────────────────────┘ +│ ┌──────────────┐ │ +│ │ Infisical │ ← Gestión centralizada │ +│ │ :8082 │ Single source of truth │ +│ └──────┬───────┘ │ +│ │ │ +└───────────────────────────┼─────────────────────────────────────┘ + │ + sync/push │ (en deploy o periódico) + │ + ┌────────────────┴────────────────┐ + ▼ ▼ +┌──────────────────────┐ ┌──────────────────────┐ +│ DECK │ │ CORP │ +│ (Instancia) │ │ (Instancia) │ +│ │ │ │ +│ ┌──────────────┐ │ │ ┌──────────────┐ │ +│ │ Vaultwarden │ │ │ │ Vaultwarden │ │ +│ │ :8085 │ │ │ │ :8081 │ │ +│ └──────┬───────┘ │ │ └──────┬───────┘ │ +│ │ │ │ │ │ +│ ▼ │ │ ▼ │ +│ CLARA, ALFRED │ │ MARGARET, JARED │ +│ leen de aquí │ │ MASON, FELDMAN │ +│ │ │ leen de aquí │ +└──────────────────────┘ └──────────────────────┘ +``` + +### Gestores por Servidor + +| Servidor | Gestor | Puerto | Rol | +|----------|--------|--------|-----| +| ARCHITECT | Infisical | 8082 | Gestión central, source of truth | +| DECK | Vaultwarden | 8085 | Operación autónoma DECK | +| CORP | Vaultwarden | 8081 | Operación autónoma CORP | + +--- + +## Flujo de Secretos + +### Administración (en ARCHITECT) + +``` +Administrador + │ + ▼ +┌─────────────┐ +│ Infisical │ ← Crear/modificar/rotar secretos aquí +│ (central) │ +└─────────────┘ +``` + +### Sincronización (ARCHITECT → Instancias) + +``` +Infisical (ARCHITECT) + │ + │ Script de sync / deploy + │ + ├────────────────┬────────────────┐ + ▼ ▼ ▼ +Vaultwarden Vaultwarden (otras instancias + DECK CORP futuras) +``` + +### Operación (en cada instancia) + +``` +┌──────────────────────────────────────┐ +│ DECK │ +│ │ +│ CLARA ──────► Vaultwarden ◄─────── ALFRED +│ :8085 │ +│ │ +│ ✅ No depende de ARCHITECT │ +│ ✅ Opera si ARCHITECT está caído │ +└──────────────────────────────────────┘ ``` --- -## Fuente 1: Infisical +## Estado Actual: Problema -**URL:** http://localhost:8082 (ARCHITECT) -**Estado:** Operativo +**Triple gestión sin sincronización:** -### Configuración +| Fuente | Ubicación | Estado | +|--------|-----------|--------| +| Infisical | ARCHITECT :8082 | Parcialmente usado | +| creds_* | PostgreSQL ARCHITECT | Activo | +| .env | /opt/*/.env en cada servidor | Activo, **permisos 644** | -```bash -# Acceso a Infisical -infisical login -infisical secrets --env=prod -``` - -### Ventajas -- Centralizado -- Versionado -- Auditable -- SDK para múltiples lenguajes - -### Uso Actual -- Parcial - no todos los servicios lo usan +**Problemas:** +- Secretos duplicados en múltiples lugares +- Sin sincronización entre fuentes +- .env legibles por todos (644) +- Vaultwarden de DECK/CORP no integrados --- -## Fuente 2: Tablas creds_* (PostgreSQL) - -**Base de datos:** architect -**Estado:** Activo - -### Tablas - -| Tabla | Contenido | -|-------|-----------| -| creds_ia | APIs de IA (OpenAI, Anthropic, etc.) | -| creds_runpod | API keys de RunPod | -| creds_r2 | Credenciales Cloudflare R2 | -| creds_gitea | Tokens Gitea | -| creds_mail | Credenciales SMTP | -| creds_apis | APIs externas varias | - -### Schema Típico - -```sql -CREATE TABLE creds_ia ( - id SERIAL PRIMARY KEY, - servicio VARCHAR(50) NOT NULL, - api_key TEXT NOT NULL, - descripcion TEXT, - activo BOOLEAN DEFAULT true, - created_at TIMESTAMP DEFAULT NOW(), - updated_at TIMESTAMP DEFAULT NOW() -); -``` - -### Acceso - -```sql --- Consultar credenciales -sudo -u postgres psql -d architect -c "SELECT servicio, descripcion FROM creds_ia;" -``` - ---- - -## Fuente 3: Archivos .env - -**Ubicaciones:** -- /opt/clara/.env -- /opt/alfred/.env -- /opt/margaret/.env -- /opt/mason/.env -- /opt/feldman/.env - -### ALERTA CRÍTICA - -``` -Permisos actuales: 644 (legibles por todos) -Permisos correctos: 600 (solo propietario) -``` - -### Contenido Típico - -```bash -# Ejemplo .env -DB_HOST=localhost -DB_PORT=5432 -DB_NAME=corp -DB_USER=margaret -DB_PASSWORD=secreto_aqui # ⚠️ Expuesto si 644 - -R2_ACCESS_KEY=access_key_aqui -R2_SECRET_KEY=secret_key_aqui # ⚠️ Expuesto si 644 -``` - ---- - -## Decisión D-001: Migración a Infisical +## Decisión D-001: Arquitectura de Secretos ### Objetivo -Infisical como **única fuente de verdad** para todos los secretos. -### Plan de Migración +1. **Infisical** (ARCHITECT): Única fuente de verdad para administración +2. **Vaultwarden** (DECK/CORP): Gestores locales para operación autónoma +3. **Sync**: Mecanismo de propagación Infisical → Vaultwarden + +### División de Responsabilidades + +| Tipo de Secreto | Gestión en | Operación en | +|-----------------|------------|--------------| +| API keys externas (OpenAI, etc.) | Infisical | Vaultwarden local | +| R2 credentials | Infisical | Vaultwarden local | +| Gitea tokens | Infisical | Vaultwarden local | +| DB password DECK | Infisical | Vaultwarden DECK | +| DB password CORP | Infisical | Vaultwarden CORP | +| Tokens internos DECK | Infisical | Vaultwarden DECK | +| Tokens internos CORP | Infisical | Vaultwarden CORP | + +### Flujo de Trabajo ``` -Fase 1: Inventario -├── Catalogar todos los secretos en creds_* -├── Catalogar todos los secretos en .env -└── Identificar duplicados/inconsistencias - -Fase 2: Centralización -├── Migrar todos los secretos a Infisical -├── Organizar por proyecto/ambiente -└── Establecer políticas de acceso - -Fase 3: Actualización de Servicios -├── CLARA: Usar Infisical SDK -├── MARGARET: Usar Infisical SDK -├── MASON: Usar Infisical SDK -├── FELDMAN: Usar Infisical SDK -└── ALFRED/JARED: Usar Infisical SDK - -Fase 4: Deprecación -├── Eliminar archivos .env -├── Marcar creds_* como "solo referencia" -└── Documentar proceso de rotación -``` - -### Implementación con SDK - -```python -from infisical_client import InfisicalClient - -client = InfisicalClient( - host="http://localhost:8082", - token=INFISICAL_TOKEN -) - -# Obtener secreto -db_password = client.get_secret( - secret_name="DB_PASSWORD", - project_id="tzzr", - environment="production" -) +1. Admin modifica secreto en Infisical (ARCHITECT) + │ + ▼ +2. Script de sync detecta cambio + │ + ▼ +3. Propaga a Vaultwarden de DECK y/o CORP + │ + ▼ +4. Servicios locales usan Vaultwarden local + │ + ▼ +5. ARCHITECT puede caer → DECK/CORP siguen operando ``` --- -## Rotación de Secretos +## Plan de Migración -### Política Propuesta - -| Tipo | Frecuencia | Responsable | -|------|------------|-------------| -| API Keys externas | 90 días | Orchestrator | -| Contraseñas DB | 180 días | DBA | -| SSH Keys | 365 días | SysAdmin | -| Tokens Gitea | 180 días | DevOps | - -### Proceso de Rotación +### Fase 1: Inventario ``` -1. Generar nuevo secreto -2. Actualizar en Infisical -3. Desplegar servicios afectados -4. Verificar funcionamiento -5. Revocar secreto anterior -6. Documentar en changelog +├── Catalogar todos los secretos en creds_* +├── Catalogar todos los secretos en .env +├── Identificar duplicados/inconsistencias +└── Mapear qué secretos necesita cada instancia +``` + +### Fase 2: Centralización en Infisical + +``` +├── Migrar todos los secretos a Infisical +├── Organizar por instancia (DECK, CORP) +├── Establecer políticas de acceso +└── Documentar cada secreto +``` + +### Fase 3: Configurar Vaultwarden en Instancias + +``` +├── DECK: Configurar Vaultwarden :8085 +│ ├── Crear organización "DECK" +│ ├── Importar secretos de DECK desde Infisical +│ └── Configurar acceso para servicios +│ +└── CORP: Configurar Vaultwarden :8081 + ├── Crear organización "CORP" + ├── Importar secretos de CORP desde Infisical + └── Configurar acceso para servicios +``` + +### Fase 4: Implementar Sync + +``` +├── Crear script de sincronización +│ └── infisical export → vaultwarden import +├── Configurar trigger (manual, cron, o webhook) +└── Probar sync en ambas direcciones +``` + +### Fase 5: Actualizar Servicios + +``` +├── CLARA: Leer de Vaultwarden DECK +├── ALFRED: Leer de Vaultwarden DECK +├── MARGARET: Leer de Vaultwarden CORP +├── JARED: Leer de Vaultwarden CORP +├── MASON: Leer de Vaultwarden CORP +└── FELDMAN: Leer de Vaultwarden CORP +``` + +### Fase 6: Deprecación + +``` +├── Eliminar archivos .env +├── Marcar creds_* como "solo referencia histórica" +└── Documentar proceso completo +``` + +--- + +## Implementación + +### Lectura desde Vaultwarden (Python) + +```python +import requests + +VAULTWARDEN_URL = "http://localhost:8085" # DECK +# VAULTWARDEN_URL = "http://localhost:8081" # CORP + +def get_secret(name: str) -> str: + """Obtiene secreto de Vaultwarden local.""" + # Implementar según API de Vaultwarden/Bitwarden + pass +``` + +### Script de Sync (Infisical → Vaultwarden) + +```bash +#!/bin/bash +# /opt/scripts/sync_secrets.sh + +# Exportar desde Infisical +infisical export --env=deck --format=json > /tmp/deck_secrets.json +infisical export --env=corp --format=json > /tmp/corp_secrets.json + +# Importar a Vaultwarden DECK +ssh deck 'bw import --format json /tmp/deck_secrets.json' + +# Importar a Vaultwarden CORP +ssh corp 'bw import --format json /tmp/corp_secrets.json' + +# Cleanup +rm /tmp/*_secrets.json ``` --- ## Mitigación Inmediata -### Paso 1: Permisos .env +### Paso 1: Permisos .env (URGENTE) ```bash -# Ejecutar en todos los servidores - # DECK ssh -i ~/.ssh/tzzr root@72.62.1.113 'chmod 600 /opt/clara/.env /opt/alfred/.env' @@ -211,82 +272,73 @@ ssh -i ~/.ssh/tzzr root@72.62.1.113 'chmod 600 /opt/clara/.env /opt/alfred/.env' ssh -i ~/.ssh/tzzr root@92.112.181.188 'chmod 600 /opt/margaret/.env /opt/mason/.env /opt/feldman/.env' ``` -### Paso 2: Auditoría +### Paso 2: Verificar Vaultwarden ```bash -# Verificar permisos -ls -la /opt/*/.env +# DECK +curl -s http://72.62.1.113:8085/api/health -# Buscar secretos expuestos -grep -r "password\|secret\|key" /opt/*/ 2>/dev/null +# CORP +curl -s http://92.112.181.188:8081/api/health ``` --- -## Inventario de Secretos +## Rotación de Secretos -### APIs de IA +### Política -| Servicio | Ubicación Actual | Notas | -|----------|------------------|-------| -| OpenAI | creds_ia | GPT-4 | -| Anthropic | creds_ia | Claude | -| Replicate | creds_ia | Modelos varios | -| RunPod | creds_runpod | GRACE, PENNY, FACTORY | +| Tipo | Frecuencia | Responsable | +|------|------------|-------------| +| API Keys externas | 90 días | Admin vía Infisical | +| Contraseñas DB | 180 días | Admin vía Infisical | +| SSH Keys | 365 días | Admin vía Infisical | +| Tokens Gitea | 180 días | Admin vía Infisical | -### Infraestructura +### Proceso -| Servicio | Ubicación Actual | Notas | -|----------|------------------|-------| -| PostgreSQL | .env + creds_* | Múltiples usuarios | -| R2/Cloudflare | .env + creds_r2 | Access + Secret key | -| Gitea | .env + creds_gitea | Read + Write tokens | -| SMTP | creds_mail | Mailcow | - -### Servicios Externos - -| Servicio | Ubicación Actual | Notas | -|----------|------------------|-------| -| Stripe | creds_apis | (si aplica) | -| Twilio | creds_apis | (si aplica) | -| AWS | creds_apis | (si aplica) | - ---- - -## Verificación de Seguridad - -### Checklist Diario - -- [ ] Permisos .env son 600 -- [ ] No hay secretos en logs -- [ ] No hay secretos en commits git -- [ ] Infisical accesible - -### Comandos de Verificación - -```bash -# Verificar permisos -find /opt -name ".env" -exec ls -la {} \; - -# Buscar secretos en git history -git log -p | grep -i "password\|secret\|key\|token" - -# Verificar Infisical -curl -s http://localhost:8082/api/v1/health +``` +1. Rotar en Infisical (ARCHITECT) +2. Ejecutar sync a Vaultwarden (DECK/CORP) +3. Verificar servicios operando +4. Documentar rotación ``` --- -## Buenas Prácticas +## Verificación -### DO (Hacer) -- Usar Infisical para todos los secretos nuevos -- Rotar secretos según política -- Auditar accesos regularmente -- Cifrar secretos en reposo +### Checklist -### DON'T (No Hacer) -- Hardcodear secretos en código -- Commitear .env a repositorios -- Compartir secretos por chat/email -- Usar el mismo secreto en múltiples servicios +- [ ] Infisical operativo en ARCHITECT +- [ ] Vaultwarden operativo en DECK (:8085) +- [ ] Vaultwarden operativo en CORP (:8081) +- [ ] Sync configurado y probado +- [ ] Servicios leen de Vaultwarden local +- [ ] .env eliminados o con permisos 600 +- [ ] DECK opera si ARCHITECT cae +- [ ] CORP opera si ARCHITECT cae + +### Test de Autonomía + +```bash +# 1. Detener ARCHITECT (simulado) +# 2. Verificar DECK sigue operando +curl http://72.62.1.113:5051/health # CLARA + +# 3. Verificar CORP sigue operando +curl http://92.112.181.188:5051/health # MARGARET +``` + +--- + +## Resumen + +| Componente | Rol | +|------------|-----| +| **Infisical (ARCHITECT)** | Gestión centralizada, source of truth | +| **Vaultwarden (DECK)** | Operación autónoma instancia personal | +| **Vaultwarden (CORP)** | Operación autónoma instancia empresarial | +| **Sync** | Propagación de cambios | + +**Principio clave:** Las instancias (DECK, CORP) nunca dependen de ARCHITECT en runtime.