Keyboard shortcuts

Press or to navigate between chapters

Press ? to show this help

Press Esc to hide this help


id: ADR-013 title: La adquisición de la clave maestra utiliza una única autoridad de origen de claves configurada date: 2026-07-25 status: propuesta relates-to:

  • https://github.com/zeroclaw-labs/zeroclaw/issues/9127
  • https://github.com/zeroclaw-labs/zeroclaw/pull/9194
  • docs/book/src/security/model.md
  • docs/book/src/architecture/config-lifecycle.md
  • crates/zeroclaw-config/src/secrets.rs

ADR-013: La obtención de la clave maestra utiliza una única autoridad de origen de claves configurada

Contexto

Cuando el cifrado de secretos está habilitado, ZeroClaw normalmente persiste los valores no vacíos de #[secret] en el formato enc2:, con una clave maestra por cada raíz de configuración. La implementación actual obtiene esa clave de .secret_key, un archivo hexadecimal de texto plano protegido por los permisos del sistema de archivos. Este valor predeterminado resulta práctico para el desarrollo local y las implementaciones que montan material de claves protegido, pero no permite usar llaveros del sistema operativo, claves derivadas de frases de contraseña ni sistemas de secretos externos.

La ubicación de la clave es solo una parte del contrato. Todos los consumidores en producción deben acordar qué fuente es responsable de la clave, en qué se diferencia el aprovisionamiento del primer uso de la indisponibilidad temporal y qué sucede cuando una fuente configurada no puede proporcionar la clave esperada. Una lectura directa de .secret_key fuera de los límites canónicos de secretos, una conmutación por error implícita a otra fuente o un cambio inseguro de backend pueden hacer que el texto cifrado existente sea ilegible o debilitar la protección prevista de la implementación.

El RFC #9127 define una arquitectura de fuentes de claves por fases. La implementación inicial #9194 extrae la fuente basada en archivos y refuerza la publicación atómica, sin reemplazo y sin seguimiento de archivos de claves, al tiempo que conserva la configuración y la semántica del texto cifrado. Este refuerzo puede requerir dependencias de bajo nivel específicas del destino; #9460 realiza el seguimiento del límite pendiente de las ACL de Windows durante la creación. Este registro captura el objetivo estable sin afirmar que se hayan incorporado fuentes configuradas que no sean de archivo ni compatibilidad con la migración.

Decisión

Usa un único límite canónico para el origen de las claves

La obtención de la clave maestra está encapsulada en una frontera KeySource del subsistema de configuración y secretos. SecretStore y cualquier otro consumidor de producción del material de claves de despliegue deben usar esa frontera en lugar de leer .secret_key, invocar un almacén de la plataforma o almacenar en caché directamente una clave obtenida de forma independiente.

Solo una fuente configurada tiene autoridad para una implementación en cada momento. La fuente de archivo sigue siendo el valor predeterminado compatible con versiones anteriores. Agregar otra fuente no debe cambiar el formato del texto cifrado enc2: ni el contrato de cifrado ChaCha20-Poly1305.

La selección del origen se resuelve a partir de la Config tipada canónica y se ancla en Config::install_root_dir(). La capa de composición del binario y del entorno de ejecución construye una única autoridad de origen compartida para cada generación de procesos y la inyecta en SecretStore y en cualquier otro consumidor de claves. Los consumidores pueden clonar esa autoridad, pero no deben elegir una raíz, reconstruir una autoridad a partir de una instantánea conservada de la configuración de secretos ni leer directamente el material del backend. Los procesos independientes resuelven determinísticamente la misma autoridad configurada; las cachés del backend siguen siendo locales al proceso.

Que un consumidor no relacionado con el cifrado reciba acceso con alcance al origen o derive una subclave específica para un propósito es una decisión de seguridad independiente. Este ADR requiere una adquisición canónica, pero no elige un contrato de derivación o compatibilidad para la firma de identidad de TUI ni para otro protocolo. Hasta que se registre esa decisión, un consumidor no relacionado con el cifrado no debe reutilizar silenciosamente la clave maestra de cifrado sin procesar.

El límite puede exponer los bytes de la clave únicamente durante la duración de una operación síncrona. Esto es una restricción de corrección y de tiempo de vida, no un entorno aislado: el código que se ejecute dentro de esa operación aún podría copiar los bytes. Las implementaciones deben minimizar las copias y borrar el material temporal cuando la plataforma y el modelo de dependencias lo permitan.

Este límite de clave sin procesar se aplica únicamente a las fuentes que pueden devolver material de clave exportable de 32 bytes. Los elementos seguros no exportables exponen operaciones criptográficas en lugar de bytes de clave y requieren un límite independiente basado en operaciones y una decisión de arquitectura.

Separar el estado de aprovisionamiento de la disponibilidad

Una fuente debe distinguir entre estos estados:

  • existe material de claves local y se puede verificar;
  • el material de claves local necesita inicialización; o
  • El material de claves se aprovisiona externamente y no tiene una comprobación de existencia local significativa.

Una sonda local de aprovisionamiento no debe ejecutar inesperadamente un programa auxiliar, ponerse en contacto con un servicio de red, pedir intervención al usuario ni desbloquear un llavero. El acceso real a la clave es una operación independiente y puede fallar porque la fuente configurada no está disponible, está bloqueada o configurada incorrectamente, o devuelve la clave equivocada.

La inicialización crea material de claves nuevo únicamente para una fuente que lo admita explícitamente. La inicialización de archivos debe publicar un archivo completo con permisos restrictivos, sin reemplazar el material existente ni aceptar la redirección mediante enlaces simbólicos. La rotación no es inicialización y requiere su propia operación protegida.

Fallar en modo cerrado sin cambiar la autoridad

Cuando una función habilitada requiere la clave configurada y la fuente no puede proporcionarla, el inicio o la operación de credenciales de esa función falla con diagnósticos seguros y específicos de la fuente. ZeroClaw no debe recurrir silenciosamente a .secret_key, generar material de reemplazo ni intentar usar otro backend. Los bytes sin procesar de la clave y la salida de las funciones auxiliares que pueda contenerlos no deben aparecer en los registros ni en los errores devueltos.

El fallo al adquirir la fuente configurada no debe seleccionar implícitamente una identidad TUI sin firmar. Si se sigue admitiendo la identidad TUI sin firmar, debe ser una política seleccionada explícitamente por el operador, con su propio modelo de amenazas, diagnósticos y pruebas. Cuando se configura una identidad firmada, el fallo al adquirir su clave debe hacer fallar el inicio o la conexión afectados. Determinar si la firma TUI recibe acceso con alcance restringido a la fuente o deriva una clave específica para el propósito sigue siendo una decisión de seguridad independiente.

Las implementaciones de las fuentes deben indicar su modelo de amenazas y sus dependencias operativas. Un llavero del sistema operativo no protege un proceso de ZeroClaw comprometido; una fuente de frase de contraseña depende de la interacción del usuario y de la solidez de la contraseña; un ayudante externo depende de su ejecutable, entorno, transporte y sistema de secretos subyacente. El nombre de un backend por sí solo no constituye una garantía de seguridad.

Los auxiliares externos, cuando se implementen, ejecutan un archivo ejecutable absoluto configurado explícitamente sin un intermediario de shell. El contrato inicial no acepta argumentos; la compatibilidad posterior con argumentos requiere una revisión independiente y debe representar los valores por separado en lugar de analizar un comando de shell. La ejecución está limitada por un tiempo de espera, y la implementación conserva y recoge el proceso hijo cuando se agota el tiempo de espera o termina. El auxiliar devuelve exactamente una clave de 32 bytes como 64 caracteres hexadecimales en minúsculas; stdout y stderr sin procesar nunca se incluyen en los registros ni en los errores devueltos. El contrato inicial hereda el entorno del proceso y debe documentar dicha exposición. Los reintentos y las cachés están acotados, el material de clave caducado se borra y los fallos de actualización siguen aplicando un comportamiento de bloqueo seguro.

Mantén la migración y la rotación separadas

Mover la misma clave maestra a otro origen es una migración. Generar una clave nueva y volver a cifrar cada valor protegido es una rotación. Tienen reglas de fallo y reversión diferentes y no deben representarse como un único cambio genérico del backend.

Cambiar la fuente configurada mientras existen valores cifrados requiere una ruta de migración verificada. Hasta que estén disponibles las herramientas de migración, ZeroClaw debe rechazar cualquier cambio de fuente que no pueda demostrar el acceso a la clave que descifra los valores enc2: existentes. La migración debe conservar la fuente anterior hasta que la nueva fuente se haya escrito y leído correctamente. La rotación debe conservar la clave anterior y la configuración original hasta que todos los valores se hayan vuelto a cifrar y la nueva configuración se haya confirmado atómicamente.

zeroclaw secrets migrate debe publicarse con el cambio que permite seleccionar la primera fuente que no sea de archivo, o en uno anterior. Cada fuente posterior debe tener una ruta de transición compatible antes de que los operadores puedan seleccionarla. Una fuente que no pueda importar la clave maestra existente, como una fuente derivada únicamente de una frase de contraseña, requiere la ruta de rotación revisada por separado, en lugar de fingir que es posible migrar con la misma clave.

La migración y la rotación deben inventariar todos los propietarios persistentes del texto cifrado de SecretStore. El inventario inicial incluye el TOML de configuración y la salida de configuración generada o migrada, <install>/auth-profiles.json, <install>/auth-<provider>-pending.json, <install>/otp-secret y <data>/webauthn_credentials.json. Los futuros almacenes persistentes que escriban valores enc2: se incorporan al mismo inventario. Construir un almacén sin añadir un formato persistente de texto cifrado no crea otro propietario de migración.

Esta decisión no aplica en vivo la selección de la fuente de claves. Un cambio de fuente guardado solo entra en vigor tras la validación de la migración y una recarga completa del demonio o un reinicio del proceso. Cualquier transferencia en vivo futura debe definir el aislamiento por generaciones en una decisión de implementación independiente.

Adopta el límite en el orden de seguridad

La extracción de la fuente de archivos se incorpora primero sin cambiar la configuración ni la semántica del texto cifrado. Puede reforzar la creación y publicación de archivos de claves, con dependencias de bajo nivel específicas del destino, al tiempo que conserva el backend de archivos como base de compatibilidad. A continuación, los consumidores de producción y la selección de fuentes con cierre ante fallos pasan a situarse detrás de ese límite. Las herramientas de migración deben incorporarse a más tardar con la primera fuente no basada en archivos que se pueda seleccionar. Después, las fuentes no basadas en archivos se incorporan una a una, con modelos de amenazas específicos de cada fuente, compatibilidad de transición y pruebas. La rotación general de claves sigue siendo un flujo revisado por separado.

Este ADR permanece propuesto hasta que se cumplan todas estas condiciones:

  • la fuente de archivos conserva la compatibilidad con los datos existentes de .secret_key y enc2: frente a fixtures literales de claves y textos cifrados previos a la extracción, y publica nuevos archivos de claves sin sobrescribir ni seguir enlaces simbólicos;
  • la configuración tipada canónica selecciona el origen y la raíz de instalación, y la capa de ensamblaje del binario o del tiempo de ejecución inyecta una única autoridad compartida por generación de proceso en cada consumidor de producción;
  • la configuración selecciona exactamente una fuente, usa la fuente de archivo de forma predeterminada para mantener la compatibilidad y falla de forma segura sin recurrir a alternativas ni generar claves de reemplazo;
  • un fallo de la fuente configurada no puede habilitar implícitamente una identidad TUI sin firma; cualquier modo sin firma que se mantenga es una política explícita del operador con su propio modelo de amenazas, diagnósticos y pruebas;
  • las sondas de aprovisionamiento distinguen entre la ausencia del material y un fallo de inspección, y un acceso correcto a with_key invoca su función de devolución de llamada exactamente una vez, con pruebas de casos límite que cubren cero o múltiples invocaciones de la función de devolución de llamada, así como errores de permisos o errores transitorios de inspección;
  • zeroclaw secrets migrate está disponible antes de que se pueda seleccionar la primera fuente que no sea de archivo, y cada fuente posterior tiene una ruta de migración o rotación verificada antes de la habilitación;
  • al menos una fuente compatible que no sea un archivo demuestra que el límite funciona más allá de la implementación basada en archivos; y
  • El cambio de origen se rechaza a menos que se pueda descifrar el inventario completo de textos cifrados persistentes o se complete correctamente una migración documentada, atómica y con capacidad de reversión.

Consecuencias

Consecuencias positivas:

  • Las implementaciones de escritorio, servidor y contenedor pueden elegir una autoridad de claves exportable que se adapte a su entorno operativo.
  • Todos los consumidores de credenciales comparten una única fuente de verdad y un único ciclo de vida que se cierra ante fallos.
  • El despliegue existente basado en archivos sigue siendo la referencia de compatibilidad.
  • La migración, la rotación y el inicio normal no pueden confundirse silenciosamente.

Consecuencias negativas:

  • El inicio ahora requiere una semántica explícita de aprovisionamiento y disponibilidad para cada fuente.
  • Las fuentes que no son archivos añaden dependencias de la plataforma, solicitudes de entrada, comportamiento de procesos externos o disponibilidad de servicios que la fuente de archivo no tiene.
  • Cambiar de backend no puede ser una simple edición de la configuración cuando ya existen valores cifrados.
  • La transición debe localizar y eliminar las lecturas directas de archivos de claves en todos los consumidores de producción antes de que se complete el límite.

Referencias