Skip to content
GitHub

Seguridad de Infraestructura

La seguridad de infraestructura sigue el modelo de responsabilidad compartida, aprovechando las capacidades de nuestros proveedores Cloud (Cloudflare, Render, Neon).


graph TD
    subgraph Internet["🌐 Internet"]
        USER[👤 Usuario]
    end
    
    subgraph Edge["☁️ Capa 1: Edge (Cloudflare)"]
        WAF[WAF + DDoS]
        SSL[SSL/TLS Termination]
    end
    
    subgraph Backend["🖥️ Capa 2: API (Render)"]
        CORS[CORS Middleware]
        RATE[Rate Limiting]
        API[Orchestrator]
    end
    
    subgraph Data["🗄️ Capa 3: Datos (Neon)"]
        POOL[Connection Pool]
        DB[(PostgreSQL)]
    end
    
    USER -->|HTTPS| WAF
    WAF --> SSL
    SSL --> CORS
    CORS --> RATE
    RATE --> API
    API -->|SSL/TLS| POOL
    POOL --> DB
    
    classDef edge fill:#f39c12,stroke:#d35400,color:#000;
    classDef backend fill:#27ae60,stroke:#2ecc71,color:#fff;
    classDef data fill:#16a085,stroke:#1abc9c,color:#fff;
    
    class WAF,SSL edge;
    class CORS,RATE,API backend;
    class POOL,DB data;

El tráfico entrante pasa primero por la red global de Cloudflare:

ControlDescripción
DDoS ProtectionMitigación automática de ataques L3/L4
WAFReglas OWASP Top 10 activadas
SSL/TLS OffloadingTerminación segura de HTTPS
HSTSForzar HTTPS por 1 año
Bot ManagementDetección y bloqueo de bots maliciosos

El servicio Orchestrator corre en un entorno contenerizado aislado.

Cross-Origin Resource Sharing debe configurarse correctamente:

app.ts
import cors from 'cors';
const whitelist = [
'https://jean-d-arc.pages.dev', // Producción
'http://localhost:4321' // Desarrollo local
];
const corsOptions: cors.CorsOptions = {
origin: (origin, callback) => {
// Permitir requests sin 'origin' (curl, Postman)
if (!origin || whitelist.includes(origin)) {
callback(null, true);
} else {
callback(new Error('Bloqueado por CORS policy'));
}
},
credentials: true, // Permitir cookies
methods: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS'],
allowedHeaders: ['Content-Type', 'Authorization', 'X-Requested-With'],
maxAge: 86400 // Cachear preflight por 24h
};
app.use(cors(corsOptions));

ControlImplementación
Conexiones SSLSolo permitidas via TLS
Connection Poolingpg-pool con límites configurados
Aislamiento Multi-TenantCada tenant en database separada
Queries ParametrizadasPrevención de SQL Injection
lib/db.ts
import { Pool } from 'pg';
// Pool con configuración optimizada
const poolConfig = {
max: 20, // Máximo de conexiones
idleTimeoutMillis: 30000, // Cerrar idle después de 30s
connectionTimeoutMillis: 2000, // Fail fast
ssl: process.env.PG_SSL === '1'
? { rejectUnauthorized: false }
: undefined,
};
export const centralPool = new Pool({
...poolConfig,
database: 'nostromo_command',
});

  1. Revisa la pestaña Network del navegador
  2. Analiza la petición OPTIONS (Preflight)
  3. Si Preflight falla (403/404) → servidor rechazó el origen
  4. Si Preflight pasa pero request falla → header Authorization no permitido
  5. Verifica que el origen exacto esté en whitelist

Se recomienda configurar alertas para:

MétricaUmbralAcción
Tráfico inusual+500% baselineRevisar posible DDoS
Errores 401/403>100/horaPosible brute force
Latencia DB>500ms p95Revisar queries lentas
CPU/Memory>80%Escalar recursos