Sauvegarde, restauration & rétention
Une propriété gouverne tout ce qui suit : l’intégrité voyage avec les données, pas avec la sauvegarde. Chaque enregistrement est chaîné par hachage et signé à l’origine, chaque point de contrôle est signé et revérifié au chargement, et un store dont le disque a été édité refuse de s’ouvrir plutôt que de servir une histoire réécrite. Une sauvegarde protège donc la disponibilité et la confidentialité. Corollaire : une copie restaurée se prouve elle-même ou refuse de se charger, si bien que chaque restauration se termine par un verdict vérifiable par machine.
Ce qu’il y a à sauvegarder
Section intitulée « Ce qu’il y a à sauvegarder »| Artefact | Écrit par | Contenu |
|---|---|---|
| Répertoire du WAL | passerelle | un <chain>.jsonl par chaîne d’audit (transport HTTP : un par session) |
| Store du ledger | ledger | par chaîne : <chain>.checkpoints.jsonl, <chain>.anchors.jsonl ; pour tout le store : keys.json |
| Packs de preuves | obsign-ledger export | preuve autonome — l’artefact de rétention |
| Matériel de confiance | ops | trusted-keys.json, le bundle de déploiement signé — à traiter comme de la configuration |
| Clé de scellement | HSM | pas à vous de la copier en fichier : la cérémonie de sauvegarde du fournisseur s’applique. La perdre arrête les nouveaux scellements ; elle n’invalide rien de déjà scellé. Un remplacement prend un nouveau key_id |
Tout ce qui figure dans les trois premières lignes est du JSONL ou du JSON, en
ajout seul. C’est délibéré, et cela rend la sauvegarde ennuyeuse : les
fichiers ne font que grandir, une dernière ligne déchirée est tolérée et
rognée par le processus propriétaire, et keys.json est remplacé
atomiquement. Les copies à chaud sont sûres au niveau du fichier.
Sauvegarder
Section intitulée « Sauvegarder »L’ordre de copie compte. Les fichiers du store se référencent
mutuellement, et Store::open refuse un store dont les références pendent.
Copiez dans l’ordre des références, et le store avant le WAL (la
couverture scellée ne doit jamais dépasser la fin du journal) :
# Hot backup, safe while gateway and ledger run.rsync -a store/*.anchors.jsonl backup/store/ 2>/dev/null || truersync -a store/*.checkpoints.jsonl backup/store/rsync -a store/keys.json backup/store/rsync -a wal/ backup/wal/Un instantané de système de fichiers atomique unique (LVM, ZFS, EBS) des deux répertoires est équivalent et plus simple.
Fréquence. Votre intervalle de sauvegarde est votre RPO pour la piste
d’audit. Le WAL est en ajout seul et persisté par fsync à chaque
enregistrement, ce qui rend la réplication continue peu coûteuse ; au minimum,
sauvegardez à l’intervalle de scellement.
Vérifiez chaque sauvegarde. Une sauvegarde que personne n’a ouverte est un espoir :
for f in backup/wal/*.jsonl; do chain=$(basename "$f" .jsonl) obsign-ledger export --wal backup/wal --store backup/store \ --chain-id "$chain" --out "/tmp/$chain.pack.json" \ --deployment-bundle deployment-bundle.json obsign verify --strict --trusted-keys trusted-keys.json \ "/tmp/$chain.pack.json" || echo "BACKUP BAD: $chain"doneCode de sortie 0, ou la sauvegarde n’en est pas une. Chiffrez ensuite et appliquez le 3-2-1 : les copies ne portent aucun matériel de clé, mais elles portent qui a fait quoi.
Restaurer
Section intitulée « Restaurer »Règles de base : restaurez le WAL et le store depuis le même jeu de
sauvegarde. Un WAL plus récent avec un store plus ancien convient (la queue
non scellée sera scellée au passage suivant) ; un WAL plus ancien avec un
store plus récent donne TruncatedLog.
- Hôte de la passerelle perdu — restaurez le WAL sur un volume qui honore
fsync, redémarrez. La passerelle rejoue le journal, vérifie la signature d’origine de chaque enregistrement et reprend là où la copie s’arrête. UnForeignRecordà la reprise signifie soit une falsification, soit une clé de rotation manquante dans le bundle de déploiement : rien n’est rogné ni adopté ; un humain décide. Les actes accomplis après la dernière sauvegarde sont absents. Dites-le dans le compte rendu d’incident : une lacune documentée est défendable, une chaîne discrètement raccourcie ne l’est pas. - Hôte du ledger perdu — restaurez le store et exécutez une passe de
scellement. Un
Store::openréussi est le contrôle d’intégrité. UnDivergedLogsignifie que le WAL et le store ne s’accordent pas sur l’histoire scellée : l’un des deux n’est pas l’original, et les ancres arbitrent : un jeton RFC 3161 fixe ce que le point de contrôle disait, et quand. - Les deux hôtes perdus — les packs de preuves archivés sont autonomes et se vérifient hors ligne sans aucun service : l’histoire n’est pas perdue, elle est déjà sous sa forme de long terme. L’exploitation reprend sur de nouvelles chaînes. Ne reconstruisez pas de fichiers WAL depuis les packs. Les packs sont la preuve qui fait foi ; le travail nouveau obtient des chaînes nouvelles.
- Clé de scellement perdue — rien de déjà scellé n’est affecté.
Provisionnez une nouvelle clé, scellez sous un nouveau
key_id. L’ancien identifiant reste lié à l’ancienne clé pour toujours ; c’est cette liaison qui garde les anciens scellés vérifiables.
Rétention
Section intitulée « Rétention »L’artefact de rétention est le pack de preuves : un seul fichier JSON,
vérifiable hors ligne aussi longtemps que vous saurez exécuter sha256 et
Ed25519. Par chaîne, le cycle de vie est le suivant : fermer, sceller, ancrer,
exporter (auto-vérification), vérifier indépendamment avec les clés hors
bande, archiver (le pack et son sha256 dans un stockage immuable, par
exemple S3 Object Lock, en deux emplacements), et seulement ensuite élaguer
les fichiers de travail de la chaîne. L’élagage supprime les fichiers de
chaînes entières, jamais des lignes à l’intérieur d’un fichier : un fichier
raccourci est indiscernable d’une falsification, et l’outillage le traitera
comme telle.
Revérification périodique
Section intitulée « Revérification périodique »Chaque trimestre, et après chaque restauration :
fail=0for pack in archive/*/*/*.pack.json; do sha256sum -c "$pack.sha256" || fail=1 obsign verify --strict --trusted-keys trusted-keys.json "$pack" [ $? -eq 0 ] || { echo "FAIL: $pack"; fail=1; }doneexit $failTraitez toute sortie non nulle comme un échec, y compris 3 : dans une tâche planifiée, le code 3 signifie que le fichier de clés de confiance n’est pas parvenu au vérificateur, pas que la vérification est passée.
Deux points de long terme : le trusted-keys.json utilisé pour la
revérification doit être la copie hors bande sous votre contrôle, et il doit
s’accumuler, jamais se réduire. Une clé retirée des nouveaux déploiements
vérifie encore deux ans d’anciens scellés. Et archivez la chaîne de
certificats de la TSA aux côtés des packs : prouver qui a émis un horodatage
la deuxième année exige les certificats de l’émetteur, et la TSA aura fait sa
rotation d’ici là.
Une fois par an, faites un exercice de restauration : restaurez un jeu de sauvegarde tiré au hasard sur un hôte de test et exécutez la boucle ci-dessus. Le code de sortie de l’exercice est la seule preuve que ce runbook fonctionne.