Seguridad
Esta página documenta las decisiones de diseño de seguridad de Celestín. Si tienes una duda o encuentras una vulnerabilidad, escríbenos a security@celestin.es.
Credenciales — API keys
Formato
Las API keys tienen el formato sk_{env}_{24-caracteres-aleatorios}:
sk_live_...— producción, consume cuota, genera facturaciónsk_test_...— entorno de pruebas, sin cuota, sin coste
Almacenamiento en servidor
Las API keys se almacenan exclusivamente como hash argon2id con parámetros m=65536, t=3, p=4. El valor en claro se muestra una única vez en el momento de creación y no puede recuperarse. Si pierdes una key, debes revocarla y generar una nueva.
El proceso de verificación en cada petición:
- Se extrae el prefijo de la key (
sk_live_osk_test_) para seleccionar la tabla de hashes correcta. - Se calcula
argon2id(key_received)y se compara con el hash almacenado. - Si coincide, se resuelve el partner y se verifica el tenant del header.
Rotación
Puedes tener hasta 5 API keys activas simultáneamente. Esto permite rotación sin tiempo de inactividad: crea la nueva key, despliégala en tus sistemas y luego revoca la antigua.
POST /v1/api-keysAuthorization: Bearer sk_live_...
{ "name": "produccion-2026-q2", "expires_at": "2026-09-30T00:00:00Z" // opcional}BYOK — Bring Your Own Key
Con BYOK, la clave de cifrado de los datos de un tenant está derivada de tu MASTER_KEY. Celestín nunca almacena la clave maestra; solo almacena el material cifrado.
El esquema de derivación usa HKDF-SHA256:
tenant_key = HKDF( ikm = MASTER_KEY, // tu clave maestra, 32 bytes salt = tenant_id_bytes, info = "celestin-tenant-v1", length = 32)La clave derivada se usa para cifrar en reposo con AES-256-GCM. El nonce (96 bits) se genera aleatoriamente por operación y se incluye en el ciphertext.
Si no configuras BYOK, Celestín usa una clave gestionada internamente con rotación trimestral. BYOK te da control total pero implica que si pierdes la MASTER_KEY, los datos cifrados son irrecuperables.
Configurar BYOK por tenant
PATCH /v1/tenants/{id}Authorization: Bearer sk_live_...Content-Type: application/json
{ "byok": { "master_key_fingerprint": "sha256:a4b7c9e2...", "enabled": true }}El master_key_fingerprint es el SHA-256 de tu clave maestra. Celestín lo almacena para verificar en el futuro que las peticiones usan la misma clave sin necesidad de recibir la clave en sí.
Webhooks — firmas HMAC
Cada evento webhook incluye el header Celestin-Signature con un HMAC-SHA256 del cuerpo:
Celestin-Signature: t=1713179834,v1=a4b7c9e2...Campos:
t— timestamp Unix del envío (usa esto para anti-replay)v1— HMAC-SHA256 del string{t}.{body}con tu webhook secret
Verificación en Node.js
import { createHmac } from "crypto";
function verifyWebhook(body: string, signature: string, secret: string): boolean { const parts = Object.fromEntries( signature.split(",").map((p) => p.split("=")) ); const timestamp = parseInt(parts.t, 10);
// Anti-replay: rechazar eventos de más de 300 segundos if (Math.abs(Date.now() / 1000 - timestamp) > 300) { return false; }
const expected = createHmac("sha256", secret) .update(`${timestamp}.${body}`) .digest("hex");
return parts.v1 === expected;}La ventana anti-replay es de 300 segundos. Eventos más antiguos se rechazan aunque la firma sea válida.
TLS y terminación de red
- Todas las conexiones a la API usan TLS 1.3 como mínimo. TLS 1.2 y versiones anteriores están desactivadas.
- La terminación TLS se realiza en el edge de Cloudflare. El tráfico entre el edge y el servidor de aplicación viaja por la red privada de Cloudflare.
- Los certificados se gestionan automáticamente con renovación por ACME (Let’s Encrypt / Cloudflare CA).
- HSTS preload está activo con
max-age=31536000; includeSubDomains.
Sin PII en reposo
Por diseño, el servidor no recibe datos en claro cuando la anonimización del SDK está activa. Los tokens almacenados en base de datos son opacos: <NIF:D4E2A1> en lugar de 12345678Z.
Para los usuarios que no activen la anonimización del SDK (por ejemplo, integraciones directas desde entornos de back-end confiables), los datos se almacenan cifrados con la clave AES-256-GCM del tenant. En cualquier caso, los campos marcados como PII en el schema nunca se indexan en claro.
RGPD — derechos del interesado
Celestín implementa los siguientes mecanismos para cumplir con el RGPD:
Soft-delete (artículo 17 — derecho al olvido)
Cuando suspendes o eliminas un tenant, sus datos entran en un período de soft-delete de 30 días. Durante este período son recuperables. Al finalizar los 30 días, se ejecuta un purge automático e irreversible.
Para solicitar un purge inmediato por derecho al olvido, abre un ticket a privacy@celestin.es con el tenant ID.
Portabilidad (artículo 20)
GET /v1/tenants/{id}/export devuelve un ZIP con todos los datos del tenant en formato JSON estructurado. El endpoint requiere autenticación del partner y genera un link de descarga con TTL de 1 hora.
Registro de actividad
Celestín mantiene un log de auditoría por tenant con todas las operaciones mutantes (creates, updates, deletes) durante 90 días. Accesible via GET /v1/tenants/{id}/audit-log.
Divulgación responsable
Si descubres una vulnerabilidad de seguridad, escribe a security@celestin.es con:
- Descripción del problema
- Pasos para reproducir
- Impacto estimado
Nos comprometemos a acusar recibo en menos de 48 horas y a publicar un advisory en menos de 90 días.