Saltearse al contenido

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ón
  • sk_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:

  1. Se extrae el prefijo de la key (sk_live_ o sk_test_) para seleccionar la tabla de hashes correcta.
  2. Se calcula argon2id(key_received) y se compara con el hash almacenado.
  3. 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-keys
Authorization: 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:

  1. Descripción del problema
  2. Pasos para reproducir
  3. Impacto estimado

Nos comprometemos a acusar recibo en menos de 48 horas y a publicar un advisory en menos de 90 días.