---
title: "Rotación de claves maestras y de firma, y acceso de emergencia"
description: "Rota la clave maestra que protege las credenciales almacenadas y utiliza el acceso de emergencia."
image: "https://docs.quirelms.com/og.png"
---

> Documentation Index
> Fetch the complete documentation index at: https://docs.quirelms.com/es/llms.txt
> Use this file to discover all available pages before exploring further.

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

<span id="master-key-and-signing-key-rotation-and-break-glass-access"></span>

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

## Las claves <!--quire:the-keys-->

Cada credencial almacenada se cifra con una clave de cifrado de datos (DEK) nueva. La DEK se envuelve con la clave maestra (KEK), y la referencia de la clave maestra se almacena junto a ella (`key_ref` o la referencia dentro de un valor empaquetado). Rotar la clave maestra vuelve a envolver las DEK. Nunca descifra ni vuelve a cifrar una credencial.

| Parámetro | Significado |
| --- | --- |
| `QUIRE_MASTER_KEY` | Clave maestra actual: 32 bytes en base64. Todas las claves nuevas se envuelven con ella |
| `QUIRE_MASTER_KEY_VERSION` | Etiqueta de versión. `v1` si no se establece. Auméntala cada vez que cambies la clave |
| `QUIRE_MASTER_KEY_RETIRED` | Claves anteriores que aún pueden proteger secretos, en el formato `v1=<base64>,v0=<base64>`. Solo se leen; nunca se escriben |

La capa web, el worker y el comando `bun run kek:rotate` leen los mismos tres parámetros. Deben tener los mismos valores en los tres sitios; de lo contrario, alguno no podrá abrir lo que otro haya cifrado.

Sin `QUIRE_MASTER_KEY`, cada subsistema conserva la clave que deriva de `QUIRE_SECRET_KEY`. Funciona, la página Estado del sistema lo muestra como degradado y los valores siguen siendo legibles después de configurar una clave maestra; así, la primera rotación los saca de la clave derivada. Cualquier persona que pueda leer el entorno del proceso puede descifrar todas las credenciales almacenadas, por lo que una instalación de producción debe tener una clave maestra guardada en un almacén de secretos y fuera de la misma copia de seguridad que la base de datos.

## Rotación <!--quire:rotating-->

La antigüedad de la clave aparece en Consola de plataforma, Seguridad, Clave maestra y en la métrica `quire.secrets.master_key.age` (días). La tarea diaria `platform.key_age` (03:41 UTC) añade un recordatorio a la cadena de auditoría de la plataforma cuando la clave alcanza los 365 días y, luego, cada 30 días hasta que se rote. Rótala cuando aparezca el recordatorio y siempre que la clave pueda haberse expuesto.

1. Genera la clave nueva: `openssl rand -base64 32`.
2. Establece `QUIRE_MASTER_KEY` con ella y `QUIRE_MASTER_KEY_VERSION` con la siguiente etiqueta (`v2`). Pasa la clave anterior a `QUIRE_MASTER_KEY_RETIRED` como `v1=<old base64>`. Guarda ambas claves fuera de este host.
3. Despliega la capa web y el worker con los nuevos parámetros. Desde ese momento, los secretos nuevos se envuelven con `env:QUIRE_MASTER_KEY:v2`; los antiguos siguen abriéndose con la clave retirada.
4. Solicita la rotación e indica el motivo que se incluirá en el historial de auditoría:
   - en la consola: Seguridad, Clave maestra, Rotar la clave maestra; o
   - en un shell 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 tarea programada `platform.key_rotation` del scheduler) y reanuda el proceso después de reiniciarse. Para completarlo de una vez: `bun run kek:rotate run`. Consulta el progreso con `bun run kek:rotate status`.
6. Cuando el registro indique que la rotación se completó con **cero valores pendientes sin resolver y cero fallos**, elimina la clave retirada de `QUIRE_MASTER_KEY_RETIRED` y vuelve a desplegar. Consérvala hasta entonces: los valores que no pudo migrar siguen protegidos con la clave anterior.

### Qué procesa el trabajo <!--quire:what-the-job-walks-->

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 datos de control se procesan en esa base; los almacenes de cada organización se procesan de uno en uno, con seguridad a nivel de fila y en la base de datos donde esté la organización, para que las organizaciones fijadas a una base de datos dedicada roten allí. Una prueba falla si el esquema añade una columna con una clave envuelta que no esté en la lista; otra falla si la revisión de credenciales clasifica una columna cifrada que la lista omite.

### El registro <!--quire:the-record-->

- `ops.key_rotation`: una fila por rotación, con el motivo, quién la solicitó, su estado y los totales (vueltas a envolver, ya actualizadas, sin resolver y fallidas).
- `ops.key_rotation_progress`: una fila por almacén y ámbito después de procesarlo, con las referencias de claves que no se pudieron leer y cuántos valores usaban cada una. Una rotación reanudada omite estos valores.
- 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 el recordatorio.
- Métricas: `quire.secrets.master_key.age` y `quire.secrets.rewrap.outstanding` (valores que la última rotación no pudo migrar).

### Cuando hay valores sin resolver <!--quire:when-values-are-unresolved-->

Un valor queda sin resolver si está envuelto con una referencia de clave que esta instalación no tiene o no tiene el formato que indica su columna. El registro de progreso indica la referencia (por ejemplo, `env:QUIRE_MASTER_KEY:v0 (unreadable)`). Recupera esa clave en `QUIRE_MASTER_KEY_RETIRED` y ejecuta otra rotación; si se ha perdido definitivamente, pide al administrador de la organización que vuelva a introducir la credencial, que entonces se cifrará con la clave actual. Las rotaciones fallidas muestran su error en el registro; corrige la causa y vuelve a solicitarlas.

## Claves de firma <!--quire:signing-keys-->

Aparte de la clave maestra, cada organización firma sus tokens de OpenID Connect y sus mensajes LTI con su propia clave RSA, publicada en `/.well-known/jwks.json`. El operador no tiene que intervenir. La tarea horaria `platform.signing_keys` publica una clave sucesora siete días antes de que la actual cumpla noventa días; una semana después, la nueva empieza a firmar y la anterior pasa a estado de retirada; noventa días más tarde, la clave antigua se elimina junto con el conjunto de claves. Cada paso genera una entrada `platform/signing_key_advance` en la cadena de auditoría de la plataforma.

Para sustituir antes la clave de una organización, por ejemplo, si se ha expuesto:

- en la consola: Seguridad, Clave maestra, Publicar una clave de firma nueva (requiere `platform/keys_manage`); o
- en un shell 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` enumera las claves de cada organización por etapa.

La clave nueva se publica de inmediato y empieza a firmar al cabo de siete días, cuando se retira la actual. Ese plazo es deliberado: las partes que confían en la clave almacenan el conjunto en caché, y un solapamiento más corto haría fallar todas las herramientas a la vez. La clave retirada permanece otros noventa días en el conjunto para seguir validando los tokens que ya firmó. Si la exposición exige dejar de confiar en ella cuanto antes, eliminar su fila es una acción que se realiza con el acceso propio del operador a la base de datos, bajo un registro de cambios (el acceso de emergencia es de solo lectura); los tokens que firmó dejarán de poder verificarse. La rotación forzada se registra como `platform/signing_key_rotate` en la cadena de auditoría, junto con el motivo. El worker necesita los mismos parámetros `QUIRE_MASTER_KEY` que la capa web para proteger la clave nueva; `bun run kek:rotate` para la clave maestra vuelve a envolver las claves de firma junto con las demás (`oauth_signing_key` está en `SEALED_STORES`).

## Acceso de emergencia a producción <!--quire:break-glass-production-access-->

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

- El acceso especifica un ámbito (una organización o el registro de la plataforma), un motivo de al menos 20 caracteres que identifica el incidente o ticket y un plazo de 5 a 240 minutos. Caduca automáticamente: se comprueba el reloj en cada instrucción.
- Se puede conceder a quien lo emite o a otra persona responsable (con intervención de dos personas). Solo puede usarlo la persona indicada. Para emitirlo se requiere `platform/break_glass_issue` y para usarlo, `platform/break_glass_use`; de forma predeterminada, ambos permisos solo se asignan a responsables.
- Las instrucciones se ejecutan mediante la pasarela, no desde una conexión a la base de datos: son de solo lectura, de una en una, limitadas a la organización o al registro de control, con un tiempo de espera de cinco segundos y un máximo de 500 filas. Los valores binarios se muestran mediante su tamaño.
- La cadena de auditoría de la plataforma registra la concesión (con el motivo), su revocación, cada instrucción antes de ejecutarse (`platform/break_glass_statement`; las rechazadas tienen el resultado `denied`) y cada resultado (`platform/break_glass_result`). `ops.break_glass_statement` contiene los ID de las entradas de auditoría, así que el registro de concesión se puede vincular con ellas.
- No se ofrecen operaciones de escritura. Si un cambio no puede esperar a una versión, se realiza con el acceso propio del operador a la base de datos, fuera de este producto y bajo su propio registro de cambios; ese registro debe incluir la referencia del incidente indicada aquí.

¿Por qué no conceder credenciales de base de datos? Un inicio de sesión de Postgres sigue funcionando cuando termina la sesión que lo solicitó, evita la seguridad a nivel de fila de la aplicación y no puede escribir en la cadena de auditoría del producto; por tanto, sus instrucciones solo quedan auditadas hasta donde alcance el registro del servidor. La pasarela hace que el historial de auditoría sea una propiedad del acceso, no una práctica que lo rodea.

Para responder a una solicitud de auditoría, enumera las concesiones del periodo (Acceso de emergencia), abre el historial de cada concesión para consultar sus instrucciones y los ID de entradas de auditoría, y lee esas entradas en la cadena de auditoría de la plataforma (`bun run audit:verify --platform` demuestra que la cadena está intacta).

Source: https://docs.quirelms.com/es/ops/key-rotation/index.mdx
