id: ADR-013 title: L’acquisition de la clé maître repose sur une seule autorité de source de clés configurée date: 2026-07-25 status: proposé 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 : L’acquisition de la clé maîtresse utilise une seule autorité de source de clé configurée
Contexte
Lorsque le chiffrement des secrets est activé, ZeroClaw conserve normalement les valeurs #[secret] non vides au format enc2:, avec une clé maîtresse par racine de configuration. L’implémentation actuelle obtient cette clé depuis .secret_key, un fichier hexadécimal en clair protégé par les permissions du système de fichiers. Cette valeur par défaut est pratique pour le développement local et les déploiements qui montent des éléments de clé protégés, mais elle ne permet pas de prendre en charge les trousseaux de clés du système d’exploitation, les clés dérivées d’une phrase secrète ou les systèmes externes de gestion des secrets.
L’emplacement de la clé n’est qu’une partie du contrat. Chaque consommateur en production doit s’accorder sur la source qui détient la clé, sur la différence entre le provisionnement lors de la première utilisation et l’indisponibilité temporaire, et sur ce qui se produit lorsqu’une source configurée ne peut pas fournir la clé attendue. Une lecture directe de .secret_key en dehors du périmètre canonique des secrets, un repli implicite vers une autre source ou un changement de backend non sécurisé peuvent rendre le texte chiffré existant illisible ou affaiblir la protection visée par le déploiement.
RFC #9127 définit une architecture par phases pour les sources de clés. L’implémentation initiale #9194 extrait la source fichier et renforce la publication atomique des fichiers de clés, sans remplacement ni suivi, tout en préservant la configuration et la sémantique du texte chiffré. Cette sécurisation peut nécessiter des dépendances bas niveau spécifiques à la cible ; #9460 suit la limite restante liée aux ACL Windows lors de la création. Ce document décrit la cible durable sans prétendre que les sources configurées autres que des fichiers ou la prise en charge de la migration ont été livrées.
Décision
Utilisez une seule frontière canonique pour les sources de clés
L’acquisition de la clé maîtresse relève d’une frontière KeySource au sein du sous-système de configuration et des secrets. SecretStore et tout autre consommateur en production de matériel de clés de déploiement doivent utiliser cette frontière plutôt que de lire .secret_key, d’invoquer un magasin de la plateforme ou de mettre directement en cache une clé obtenue indépendamment.
À un moment donné, une seule source configurée fait autorité pour un déploiement. La source basée sur un fichier reste la valeur par défaut assurant la rétrocompatibilité. L’ajout d’une autre source ne doit modifier ni le format du texte chiffré enc2: ni le contrat de chiffrement ChaCha20-Poly1305.
La sélection de la source est résolue à partir de la Config typée canonique et ancrée sur Config::install_root_dir(). La couche d’assemblage du binaire et de l’exécution construit une seule autorité de source partagée pour chaque génération de processus et l’injecte dans SecretStore et dans tout autre consommateur de clés. Les consommateurs peuvent cloner cette autorité, mais ils ne doivent pas choisir de racine, reconstruire une autorité à partir d’un instantané conservé de la configuration des secrets, ni lire directement les données du backend. Les processus indépendants résolvent déterministiquement la même autorité configurée ; les caches du backend restent locaux au processus.
La question de savoir si un consommateur non lié au chiffrement reçoit un accès limité à la source ou dérive une sous-clé spécifique à une finalité constitue une décision de sécurité distincte. Cet ADR exige une obtention canonique, mais ne choisit ni une dérivation ni un contrat de compatibilité pour la signature d’identité TUI ou pour un autre protocole. Tant que cette décision n’est pas consignée, un consommateur non lié au chiffrement ne doit pas réutiliser silencieusement la clé maître de chiffrement brute.
La frontière peut n’exposer les octets de la clé que pendant la durée d’une opération synchrone. Il s’agit d’une contrainte de correction et de durée de vie, et non d’un bac à sable : le code exécuté dans cette opération pourrait tout de même copier les octets. Les implémentations doivent minimiser les copies et effacer les données temporaires lorsque la plateforme et le modèle de dépendances le permettent.
Cette frontière fondée sur des clés brutes ne s’applique qu’aux sources pouvant renvoyer du matériel de clé exportable de 32 octets. Les éléments sécurisés non exportables exposent des opérations cryptographiques plutôt que des octets de clé et nécessitent une frontière fondée sur les opérations et une décision d’architecture distinctes.
Séparer l’état de provisionnement de la disponibilité
Une source doit distinguer ces états :
- le matériel de clé local existe et peut être vérifié ;
- le matériel de clé local doit être initialisé ; ou
- Le matériel de clés est approvisionné en externe et ne fait l’objet d’aucune vérification locale pertinente de son existence.
Une sonde locale de provisionnement ne doit pas exécuter inopinément un programme d’assistance, contacter un service réseau, demander une intervention de l’utilisateur ou déverrouiller un trousseau. L’accès effectif à la clé constitue une opération distincte et peut échouer parce que la source configurée est indisponible, verrouillée, mal configurée ou renvoie une clé incorrecte.
L’initialisation ne crée du nouveau matériel de clés que pour une source qui le prend explicitement en charge. L’initialisation d’un fichier doit publier un fichier complet aux permissions restrictives, sans remplacer le matériel existant ni accepter une redirection par lien symbolique. La rotation n’est pas une initialisation et nécessite sa propre opération protégée.
Échouer de manière sécurisée sans modifier les autorisations
Lorsqu’une fonctionnalité activée nécessite la clé configurée et que la source ne peut pas la fournir, le démarrage de cette fonctionnalité ou son opération liée aux informations d’identification échoue avec des diagnostics sûrs et spécifiques à la source. ZeroClaw ne doit pas revenir silencieusement à .secret_key, générer des données de remplacement ni essayer un autre backend. Les octets bruts de la clé et la sortie des utilitaires susceptibles de les contenir ne doivent apparaître ni dans les journaux ni dans les erreurs renvoyées.
Un échec d’acquisition de la source configurée ne doit pas sélectionner implicitement une identité TUI non signée. Si l’identité TUI non signée reste prise en charge, elle doit relever d’une politique explicitement sélectionnée par l’opérateur, avec son propre modèle de menace, ses propres diagnostics et ses propres tests. Lorsqu’une identité signée est configurée, l’échec de l’acquisition de sa clé doit faire échouer le démarrage ou la connexion concernés. La question de savoir si la signature TUI reçoit un accès à la source limité à son périmètre ou dérive une clé spécifique à sa finalité reste une décision de sécurité distincte.
Les implémentations de sources doivent indiquer leur modèle de menace et leurs dépendances opérationnelles. Un trousseau de clés du système d’exploitation ne protège pas un processus ZeroClaw compromis ; une source de phrase secrète dépend de l’interaction de l’utilisateur et de la robustesse du mot de passe ; un assistant externe dépend de son exécutable, de son environnement, de son transport et de son système de secrets en amont. Le seul nom d’un backend ne constitue pas une garantie de sécurité.
Les assistants externes, lorsqu’ils seront implémentés, exécutent un exécutable absolu explicitement configuré, sans intermédiaire shell. Le contrat initial n’accepte aucun argument ; la prise en charge ultérieure des arguments nécessite un examen séparé et doit représenter les valeurs séparément plutôt qu’analyser une commande shell. L’exécution est limitée par un délai d’expiration, et l’implémentation conserve puis réapère le processus enfant en cas d’expiration du délai ou de sortie. L’assistant renvoie exactement une clé de 32 octets sous la forme de 64 caractères hexadécimaux minuscules ; les sorties brutes de stdout et stderr ne sont jamais consignées dans les journaux ni incluses dans les erreurs renvoyées. Le contrat initial hérite de l’environnement du processus et doit documenter cette exposition. Les nouvelles tentatives et les caches sont limités, les éléments de clé expirés sont effacés et l’échec de l’actualisation reste fermé par défaut.
Séparez la migration et la rotation
Déplacer la même clé maître vers une autre source correspond à une migration. Générer une nouvelle clé et rechiffrer chaque valeur protégée correspond à une rotation. Ces opérations ont des règles d’échec et de restauration différentes et ne doivent pas être représentées comme une seule modification générique du backend.
La modification de la source configurée alors que des valeurs chiffrées existent nécessite un chemin de migration vérifié. Tant que l’outillage de migration n’est pas disponible, ZeroClaw doit rejeter toute modification de source qui ne permet pas de prouver l’accès à la clé servant à déchiffrer les valeurs enc2: existantes. La migration doit conserver l’ancienne source jusqu’à ce que la nouvelle source ait été écrite et relue avec succès. La rotation doit conserver l’ancienne clé et la configuration d’origine jusqu’à ce que chaque valeur ait été rechiffrée et que la nouvelle configuration soit validée de manière atomique.
zeroclaw secrets migrate doit être livré dans le même changement que celui qui rend sélectionnable la première source non basée sur un fichier, ou avant celui-ci. Chaque source ultérieure doit disposer d’un parcours de transition pris en charge avant que les opérateurs puissent la sélectionner. Une source qui ne peut pas importer la clé maître existante, telle qu’une source dérivée uniquement d’une phrase secrète, nécessite le parcours de rotation examiné séparément, plutôt que de prétendre qu’une migration avec la même clé est possible.
La migration et la rotation doivent inventorier tous les détenteurs persistants du texte chiffré de SecretStore. L’inventaire initial inclut la configuration TOML et la sortie de configuration générée ou migrée, <install>/auth-profiles.json, <install>/auth-<provider>-pending.json, <install>/otp-secret et <data>/webauthn_credentials.json. Les futurs magasins durables qui écrivent des valeurs enc2: doivent figurer dans le même inventaire. La construction d’un magasin sans ajout d’un format de texte chiffré persistant ne crée pas un autre détenteur de migration.
La sélection de la source de clés n’est pas appliquée à chaud par cette décision. Une modification de source enregistrée ne prend effet qu’après la validation de la migration et le rechargement complet du démon ou le redémarrage du processus. Tout futur transfert à chaud devra définir un mécanisme de protection par génération dans une décision d’implémentation distincte.
Adopter la limite dans l’ordre de sécurité
L’extraction de la source fichier est livrée en premier, sans modifier la configuration ni la sémantique du texte chiffré. Elle peut renforcer la création et la publication des fichiers de clés, avec des dépendances bas niveau spécifiques à la cible, tout en conservant le backend fichier comme référence de compatibilité. Les consommateurs en production et la sélection de source en mode fail-closed passent ensuite derrière cette frontière. Les outils de migration doivent être livrés au plus tard avec la première source non fichier sélectionnable. Les sources non fichiers sont ensuite livrées une à une, avec des modèles de menace propres à chaque source, une prise en charge de la transition et des tests. La rotation générale des clés reste un flux soumis à une revue distincte.
Cet ADR reste proposé jusqu’à ce que toutes ces conditions soient remplies :
- la source de fichier préserve la compatibilité avec les données
.secret_keyetenc2:existantes vis-à-vis de fixtures littérales de clés et de textes chiffrés antérieures à l’extraction, et publie de nouveaux fichiers de clés sans remplacement ni suivi des liens symboliques ; - la configuration typée canonique sélectionne la source et la racine d’installation, et la couche d’assemblage des binaires ou d’exécution injecte une autorité partagée unique par génération de processus dans chaque consommateur de production ;
- la configuration sélectionne exactement une source, utilise par défaut la source de fichier pour assurer la compatibilité et échoue de manière sécurisée sans solution de repli ni génération de clés de remplacement ;
- une défaillance de la source configurée ne peut pas activer implicitement une identité TUI non signée ; tout mode non signé maintenu relève d’une politique explicite de l’opérateur, avec son propre modèle de menace, ses diagnostics et ses tests ;
- les sondes de provisionnement distinguent les éléments absents des échecs d’inspection, et un accès réussi via
with_keyinvoque sa fonction de rappel exactement une fois, avec des tests aux limites couvrant zéro ou plusieurs invocations de la fonction de rappel ainsi que les échecs d’inspection liés aux permissions ou transitoires ; zeroclaw secrets migrateest disponible avant que la première source autre qu’un fichier puisse être sélectionnée, et chaque source ultérieure dispose d’un parcours de migration ou de rotation vérifié avant son activation ;- au moins une source prise en charge autre qu’un fichier démontre que la frontière fonctionne au-delà de l’implémentation basée sur des fichiers ; et
- Le basculement de source est refusé, sauf si l’inventaire complet des textes chiffrés persistants peut être déchiffré ou si une migration documentée, atomique et permettant un retour arrière s’achève avec succès.
Conséquences
Conséquences positives :
- Les déploiements sur poste de travail, sur serveur et en conteneur peuvent choisir une autorité de clés exportable adaptée à leur environnement d’exploitation.
- Tous les consommateurs d’informations d’identification partagent une source unique de vérité et un même cycle de vie qui reste fermé en cas d’échec.
- Le déploiement existant basé sur des fichiers reste la référence en matière de compatibilité.
- La migration, la rotation et le démarrage normal ne peuvent pas être confondus silencieusement.
Conséquences négatives :
- Le démarrage nécessite désormais des sémantiques explicites de provisionnement et de disponibilité pour chaque source.
- Les sources autres que les fichiers ajoutent des dépendances à la plateforme, des invites, des comportements liés aux processus externes ou des exigences de disponibilité des services que la source fichier ne présente pas.
- Le changement de backend ne peut pas se résumer à une simple modification de la configuration lorsque des valeurs chiffrées existent déjà.
- La transition doit détecter et supprimer les lectures directes de fichiers de clés dans tous les consommateurs en production avant que la frontière ne soit entièrement établie.
Références
- RFC #9127 : abstraction de la source des clés et classification du déploiement
- PR #9194 : Extraction de source de clé basée sur un fichier
- Problème #9460 : renforcement des ACL du fichier de clé Windows lors de la création
- Modèle de sécurité
- Cycle de vie de la configuration
crates/zeroclaw-config/src/secrets.rscrates/zeroclaw-runtime/src/rpc/tui_identity.rs