Saltar al contenido

Rotación de claves maestras y de firma, y acceso de emergencia

Rota la clave maestra que protege las credenciales guardadas y usa el acceso de emergencia.

Ver como Markdown

Los controles de la sección 14 de 21-compliance.md que los auditores solicitan por nombre. Esta página describe el procedimiento; los registros que genera son la evidencia.

Las claves

Cada credencial guardada se cifra con una clave nueva de cifrado de datos (DEK). La DEK se envuelve con la clave maestra (KEK) y su referencia queda guardada junto a ella (key_ref o la referencia dentro de un valor empaquetado). Rotar la clave maestra vuelve a envolver las DEK. No descifra ni vuelve a cifrar ninguna credencial.

Configuración Significado
QUIRE_MASTER_KEY Clave maestra actual: 32 bytes en base64. Todos los secretos nuevos se envuelven con ella
QUIRE_MASTER_KEY_VERSION Etiqueta de versión. v1 si no se configura. Auméntala cada vez que cambies la clave
QUIRE_MASTER_KEY_RETIRED Claves anteriores que todavía pueden proteger secretos, en el formato v1=<base64>,v0=<base64>. Se leen, nunca se escriben

La capa web, el worker y el comando bun run kek:rotate leen estas mismas tres configuraciones. Deben tener los mismos valores; de lo contrario, un proceso no podrá abrir lo que otro cifró.

Sin QUIRE_MASTER_KEY, cada subsistema conserva la clave que deriva de QUIRE_SECRET_KEY. Así funciona, aunque la página Estado del sistema indica una condición degradada. El contenido sigue siendo legible después de configurar una clave maestra; por eso la primera rotación permite dejar de usar la clave derivada. Cualquier persona que pueda leer el entorno del proceso puede descifrar todas las credenciales guardadas; por eso, una instalación de producción debe tener una clave maestra en un almacén de secretos, separada del respaldo de la base de datos.

Rotar la clave

La antigüedad de la clave aparece en Consola de la plataforma, Seguridad, Clave maestra, y en la métrica quire.secrets.master_key.age (días). La programación diaria platform.key_age (03:41 UTC) escribe un recordatorio en la cadena de auditoría de la plataforma cuando la clave cumple 365 días y repite el aviso cada 30 días hasta que la rotes. Rótala cuando recibas el aviso y siempre que exista la posibilidad de que se haya expuesto.

  1. Genera una clave nueva: openssl rand -base64 32.
  2. Configura QUIRE_MASTER_KEY con ella y QUIRE_MASTER_KEY_VERSION con la siguiente etiqueta (v2). Mueve la clave anterior a QUIRE_MASTER_KEY_RETIRED como v1=<old base64>. Guarda una copia de ambas fuera de este host.
  3. Despliega la capa web y el worker con la nueva configuración. Los secretos nuevos se envuelven con env:QUIRE_MASTER_KEY:v2; los anteriores se siguen abriendo con la clave retirada.
  4. Solicita la rotación e indica el motivo que se guardará en el historial de auditoría:
    • en la consola: Seguridad, Clave maestra, Rotar la clave maestra; o
    • en una terminal con el mismo entorno: bun run kek:rotate request --reason "Annual rotation, ticket SEC-114".
  5. El worker vuelve a envolver un lote por minuto (la programación platform.key_rotation del scheduler) y retoma el trabajo al reiniciarse. Para terminarlo de una vez: bun run kek:rotate run. Revisa el avance con bun run kek:rotate status.
  6. Cuando el registro indique que la rotación terminó con cero pendientes sin resolver y cero fallas, quita la clave retirada de QUIRE_MASTER_KEY_RETIRED y vuelve a desplegar. Hasta entonces, consérvala: cualquier valor que no pudo migrar todavía está envuelto con la clave anterior.

Qué recorre la tarea

Cada almacén que contiene una DEK envuelta: los que enumera SEALED_STORES (apps/worker/src/key-rotation.ts). Los almacenes de la base de control se recorren allí; los de cada organización se recorren de una en una, con seguridad a nivel de fila y en la base donde vive la organización, así que un tenant fijado a una base dedicada rota en esa base. Una prueba falla si el esquema agrega una columna con clave envuelta que la lista no identifica; otra, si la revisión de credenciales clasifica una columna cifrada que la lista omite.

El registro

  • ops.key_rotation: una fila por rotación, con el motivo, quién la solicitó, su estado y sus totales (vueltas a envolver, ya actualizadas, pendientes sin resolver y fallidas).
  • ops.key_rotation_progress: una fila por almacén y alcance después de recorrerlo, con las referencias de claves que no se pudieron leer y cuántos valores correspondían a cada una. Una rotación reanudada omite esas filas.
  • Cadena de auditoría de la plataforma: platform/key_rotation_request (con el motivo), una entrada platform/key_rotation_store por almacén con sus recuentos y platform/key_rotation_complete o platform/key_rotation_fail; platform/key_age_reminder para los recordatorios.
  • Métricas: quire.secrets.master_key.age y quire.secrets.rewrap.outstanding (valores que la última rotación no pudo migrar).

Si quedan valores sin resolver

Un valor queda sin resolver si está envuelto con una referencia de clave que esta instalación no tiene o si no tiene el formato que indica su columna. El registro de avance muestra la referencia (por ejemplo, env:QUIRE_MASTER_KEY:v0 (unreadable)). Vuelve a agregar esa clave a QUIRE_MASTER_KEY_RETIRED y ejecuta otra rotación. Si se perdió definitivamente, pide al administrador de la organización que ingrese otra vez la credencial; entonces se cifra con la clave actual. El registro muestra el error de las rotaciones fallidas; corrige la causa y vuelve a solicitarlas.

Claves de firma

Por separado de la clave maestra, cada organización firma sus tokens OpenID Connect y mensajes LTI con su propia clave RSA, publicada en /.well-known/jwks.json. Esto no requiere intervención del operador. La programación horaria platform.signing_keys publica una clave sucesora siete días antes de que la actual cumpla 90 días. Una semana después, la sucesora empieza a firmar y la anterior pasa a retirarse; noventa días más tarde, la clave anterior se elimina del conjunto. Cada paso agrega una entrada platform/signing_key_advance a la cadena de auditoría de la plataforma.

Para reemplazar antes una clave de la organización, por ejemplo, si se expuso:

  • en la consola: Seguridad, Clave maestra, Publicar una clave de firma nueva (requiere platform/keys_manage); o
  • en una terminal con el entorno del worker: bun run kek:rotate signing-keys rotate --tenant <slug or id> --reason "Key exposed, INC-3310". bun run kek:rotate signing-keys status muestra las claves de cada organización por etapa.

La clave nueva se publica de inmediato y empieza a firmar después de siete días, cuando se retira la actual. El plazo es intencional: los sistemas que confían en la clave guardan en caché el conjunto, y un periodo de superposición más corto haría que todas las herramientas fallaran al mismo tiempo. La clave retirada permanece en el conjunto durante otros 90 días para seguir verificando los tokens que ya firmó. Si la exposición exige dejar de confiar en ella antes, se elimina su fila con el acceso propio del operador a la base de datos y bajo un registro de cambios (el acceso de emergencia es de solo lectura); a partir de ese momento, no se verifican los tokens que firmó. La rotación forzada queda en la cadena de auditoría como platform/signing_key_rotate, junto con el motivo. El worker necesita la misma configuración QUIRE_MASTER_KEY que la capa web para envolver la clave nueva; bun run kek:rotate de la clave maestra vuelve a envolver también las claves de firma (oauth_signing_key está en SEALED_STORES).

Acceso de emergencia a producción

Nadie tiene acceso permanente a producción. Si algo no puede esperar, una persona propietaria concede un acceso de emergencia: Consola de la plataforma, Seguridad, Acceso de emergencia.

  • El acceso define un alcance (una organización o el registro de la plataforma), un motivo de al menos 20 caracteres que identifique el incidente o ticket y un periodo de 5 a 240 minutos. Vence por sí solo: se comprueba la hora en cada instrucción.
  • Puede concederse a la misma persona propietaria que lo solicita o a otra (modalidad de dos personas). Solo puede usarlo la persona indicada. Para concederlo se requiere platform/break_glass_issue, y para usarlo, platform/break_glass_use; de forma predeterminada, ambos permisos son exclusivos de propietarios.
  • Las instrucciones pasan por la puerta de enlace, no por un acceso a la base de datos: son de solo lectura, se ejecutan de una en una, se limitan a la organización o al registro de control, tienen un tiempo de espera de cinco segundos y devuelven como máximo 500 filas. Los valores binarios se muestran por tamaño.
  • La cadena de auditoría de la plataforma registra la concesión (junto con el motivo), su revocación, cada instrucción antes de ejecutarla (platform/break_glass_statement; las rechazadas quedan con resultado denied) y cada resultado (platform/break_glass_result). ops.break_glass_statement guarda los ID de entradas de auditoría, así la concesión se puede vincular con ellas.
  • No se ofrecen escrituras. Un cambio que no pueda esperar a una versión se hace fuera del producto, con el acceso propio del operador a la base de datos y bajo su propio registro de cambios; ese registro debe citar la referencia del incidente indicada aquí.

¿Por qué no entregar credenciales de base de datos? Un acceso a Postgres sigue vigente después de que termine la sesión que lo solicitó, evita la seguridad a nivel de fila que usa la aplicación y no puede escribir en la cadena de auditoría del producto. Así, las instrucciones solo quedarían auditadas hasta donde alguien hubiera enviado los registros del servidor. La puerta de enlace convierte el historial de auditoría en una propiedad del acceso, en lugar de una práctica que lo rodea.

Para responder a una auditoría: consulta las concesiones del periodo (Acceso de emergencia), abre el historial de una concesión para ver sus instrucciones y los ID de entradas de auditoría, y revisa esas entradas en la cadena de auditoría de la plataforma (bun run audit:verify --platform comprueba que la cadena siga intacta).

Navegación

Escribe para buscar…

↑↓ navegar↵ seleccionarEsc cerrar