Aller au contenu

Sondes

Une sonde est un conteneur jetable. Le runner le démarre après la restauration, lui monte l'espace de travail en lecture seule sur /workspace, lui passe sa configuration en variables d'environnement, puis lit le fichier /out/result.json qu'il a écrit. Le conteneur est ensuite détruit.

Ce fichier est le seul verdict qui compte. Une sonde qui ne l'écrit pas, ou qui y met un statut autre que PASS, WARN ou FAIL, vaut FAIL : elle n'a rien prouvé, et le rapport le dit plutôt que de supposer le meilleur.

Il existe dix sondes.

Sonde Ce qu'elle prouve
archive-integrity L'archive sauvegardée se décompresse sans erreur.
filesystem-canary Les fichiers attendus sont là, avec le bon contenu et la bonne taille.
certificate Le certificat TLS restauré est valide et c'est le bon.
postgres La base PostgreSQL restaurée répond et contient les données.
mysql Idem pour MySQL / MariaDB.
mongodb Idem pour MongoDB.
sqlite Le fichier SQLite s'ouvre, n'est pas corrompu et contient les données.
pocketbase L'instance PocketBase redémarre sur les données restaurées.
ldap L'annuaire restauré répond, contient les entrées, et un compte peut s'y authentifier.
http Le service remonté sur les données restaurées répond ce qu'on attend.

Ce qui est commun à toutes

L'image

Par défaut ghcr.io/kolapsis/restoreproof/probe-<type>:latest, où <type> est le nom de la sonde dans le tableau ci-dessus.

Une sonde personnalisée, qui nomme sa propre image, ne tourne que si cette image est officielle (elle commence par ghcr.io/kolapsis/restoreproof/probe-, ou par le préfixe de RESTOREPROOF_PROBE_IMAGE_PREFIX) ou si vous l'avez listée dans RESTOREPROOF_PROBE_IMAGES (probes.allowed_images dans la configuration du runner). Une entrée est une référence exacte, comme registry.interne/controles/verif:1.2, ou un préfixe terminé par *, comme registry.interne/controles/*. Une image absente de la liste n'est même pas téléchargée : la sonde échoue avec un message qui nomme l'entrée à ajouter.

Les variables injectées par le runner

Vous n'avez pas à les fournir : le runner les pose sur chaque conteneur de sonde.

Variable Valeur
RESTOREPROOF_WORKSPACE /workspace — l'espace de travail, en lecture seule.
RESTOREPROOF_OUTPUT /out — où la sonde écrit result.json.
RESTOREPROOF_TIMEOUT_SECONDS Le délai configuré pour cette sonde dans le plan.

Le conteneur est limité à 512 Mo de mémoire, 1 CPU et 256 processus, et tué au bout du délai de la sonde. L'éditeur de plan propose 60 secondes pour une nouvelle sonde ; une sonde qui n'en porte aucun se voit appliquer cinq minutes par le runner.

Le résultat

{
  "status": "PASS",
  "message": "...",
  "metrics": { },
  "artifacts": []
}

FAIL fait sortir le conteneur en code 1. PASS et WARN sortent en 0.

Ce que les sondes rapportent

Une sonde lit vos données restaurées, mais ce qu'elle rapporte à RestoreProof reste structurel : des comptes, des oui ou non, des durées, des tailles, des versions et des noms de tables, de collections ou de bases. Jamais la valeur d'une cellule, le contenu d'un document, la valeur d'un attribut d'annuaire ou le corps d'une réponse HTTP. Une sonde qui compare le résultat d'une requête à un seuil dit si la comparaison est satisfaite, pas quelle valeur elle a lue. Une erreur de la base, de MongoDB ou de l'annuaire est rapportée par son code (SQLSTATE, code d'erreur du serveur, code de résultat LDAP), parce que le texte d'une erreur peut citer une valeur, comme un invalid input syntax for type integer: "…". Le texte complet reste dans les journaux du runner.

Ce que la sonde écrit sur sa sortie standard ne part pas non plus : le rapport ne contient, pour chaque sonde, que son nom, son type, son verdict et sa durée, et la sortie complète est écrite dans les journaux du runner.

La sonde des certificats suit la même règle : elle rapporte les dates de validité, l'algorithme et la taille de la clé, l'algorithme de signature, l'empreinte et quelques verdicts (expiré, auto-signé, chaîne cohérente), mais jamais le sujet, l'émetteur ou les noms alternatifs. Elle ne lit jamais une clé privée, elle note seulement sa présence.

Le runner borne ce qu'il transmet de ce résultat, pour toutes les sondes : le message est coupé à 1 Kio, au plus 64 mesures sont gardées, une clé de mesure de plus de 64 octets est écartée, une valeur texte est coupée à 256 octets et une autre valeur (liste, objet) est écartée au-delà de 1 Kio, et seuls les 32 premiers artefacts sont gardés, coupés à 256 octets chacun. Le fichier result.json lui-même ne doit pas dépasser 1 Mio.

Le contrat d'assertion

Six sondes partagent le même vocabulaire de comparaison, dans une variable ..._ASSERT : postgres, mysql, mongodb, sqlite, pocketbase et ldap.

Opérateur Vérifie
gte observé ≥ attendu
lte observé ≤ attendu
eq observé = attendu
zero observé = 0 (l'attendu vaut 0 s'il n'est pas fourni)

Deux règles de commodité, identiques pour postgres, mysql, mongodb, sqlite et pocketbase :

  • un seuil fourni sans opérateur vaut gte ;
  • zero sans seuil vaut « zéro ».

zero existe séparément de eq 0 parce que « ceci ne doit pas exister » (lignes orphelines, clés nulles) est la vérification qu'on écrit de travers.

Sans assertion, le comportement n'est pas le même partout

Ce n'est pas uniforme, et c'est délibéré.

Sonde Sans aucune assertion configurée
postgres, mysql, mongodb, sqlite, pocketbase PASS, en disant dans le message qu'aucune assertion n'était configurée.
ldap FAIL si aucun des trois contrôles n'est demandé. Avec un base DN mais pas d'opérateur : PASS, en indiquant le nombre observé.
filesystem-canary FAIL. Le message vous rend les chiffres de l'arborescence pour que vous en fassiez des seuils.
archive-integrity FAIL s'il n'a validé aucune archive.
certificate FAIL si aucun chemin n'est donné.
http Vérifie toujours le code de statut (200 par défaut).

Un PASS qui n'a rien vérifié est pire qu'un FAIL : c'est une preuve qui ment. Là où la sonde peut le dire, elle échoue plutôt que de passer en silence.


archive-integrity

Décompresse une archive de bout en bout pour prouver qu'elle est lisible.

Elle ne sert que dans un plan qui ne décompresse pas

Si votre plan contient une étape unpack, l'archive a déjà disparu de l'espace de travail quand la sonde s'exécute : elle ne trouvera rien à valider et échouera. Utilisez-la pour un plan « je télécharge et je vérifie que ça s'ouvre », pas pour un plan qui restaure une base.

Variable Défaut Rôle
RESTOREPROOF_ARCHIVE_PATH (vide) Le ou les fichiers à valider, séparés par des virgules. Chemins relatifs à /workspace (un chemin absolu est pris tel quel), les jokers (*, ?) sont acceptés.

Si la variable est vide, la sonde parcourt tout l'espace de travail et valide chaque fichier dont l'extension est .tar, .gz, .tgz ou .zip. Si elle n'en trouve aucun, elle échoue : compter des fichiers ne prouve pas qu'une sauvegarde est lisible.

Si la variable est remplie, chaque nom doit correspondre à au moins un fichier. Un fichier absent, ou dont l'extension n'est pas reconnue, fait échouer la sonde.

Ce qu'elle vérifie, précisément

Extension Ce qui est réellement parcouru
.tar Chaque en-tête d'entrée du tar, jusqu'à la fin.
.zip Chaque entrée est ouverte et décompressée intégralement.
.gz, .tgz La couche gzip seulement, décompressée entièrement.

Ce qu'un .tar.gz valide, et ce qu'il ne valide pas

Un .tar.gz est traité par son extension .gz : la sonde décompresse tout le flux. Le CRC de gzip couvre l'intégralité du flux, donc une troncature ou une corruption sont attrapées — c'est bien une vérification de bout en bout, pas une lecture de l'en-tête.

Mais elle ne parcourt pas le tar qui est à l'intérieur. Un tar structurellement cassé mais correctement compressé passerait. Pour vérifier aussi le contenu, décompressez dans le plan et utilisez filesystem-canary.

Mesures : archive_count, errors_count, et selon le mode — archives_expected (nombre de noms demandés par le plan) quand la variable est remplie, total_files et total_size quand elle est vide.


filesystem-canary

Vérifie que des fichiers précis sont là, et qu'ils contiennent bien quelque chose. Un fichier vide au bon nom se restaure aussi bien que le vrai : seule la vérification du contenu distingue les deux.

Variable Défaut Rôle
RESTOREPROOF_CANARY_PATH (vide) Forme ancienne de RESTOREPROOF_CANARY_FILES, toujours lue : un ou plusieurs chemins, séparés par des virgules, qui doivent exister après la restauration. Les nouveaux plans écrivent RESTOREPROOF_CANARY_FILES.
RESTOREPROOF_CANARY_FILES (vide) La même chose, plus ce que chaque fichier doit contenir, peser ou valoir. Voir ci-dessous.
RESTOREPROOF_CANARY_PATTERN (vide) Un motif de nom de fichier (*.sql) qu'au moins un fichier restauré doit satisfaire.
RESTOREPROOF_CANARY_MIN_FILES (vide) Nombre minimal de fichiers dans toute l'arborescence.
RESTOREPROOF_CANARY_MIN_TOTAL_SIZE (vide) Poids cumulé minimal, en octets.

Les cinq contrôles s'additionnent, ils ne se remplacent pas : nommer un fichier ne dit rien de la taille de l'arborescence autour de lui.

RESTOREPROOF_CANARY_FILES

Deux écritures sont acceptées.

Liste simple — les fichiers doivent exister, rien de plus :

data/app.db,etc/config.yaml

JSON — la seule forme qui atteint les vérifications de contenu :

[
  {"path": "config.json", "contains": "db_host", "min_size": 100},
  {"path": "data/app.db", "expected_hash": "9f86d081...", "must_be_file": true},
  {"path": "var/log/app.log", "matches": "^\\[INFO\\] démarrage"}
]
Champ Type Vérifie
path texte Le chemin, relatif à /workspace. Obligatoire.
expected_hash texte Le SHA-256 du fichier. 64 caractères hexadécimaux, sinon la sonde échoue en le disant.
contains texte Le fichier contient cette chaîne, littéralement.
matches texte Le contenu satisfait cette expression régulière (syntaxe Go).
min_size nombre Le fichier pèse au moins tant d'octets.
must_be_file booléen Le chemin est un fichier, pas un répertoire.

Un chemin qui existe et n'est décrit par aucun de ces champs peut être un répertoire. Dès qu'un champ de contenu, de taille ou de hachage est présent, un répertoire est un échec.

Les vérifications contains et matches lisent au plus 8 Mio du fichier. Si la limite est atteinte sans trouver, le message le dit plutôt que d'affirmer que le texte est absent.

Sans assertion, la sonde échoue

C'est voulu, et c'est l'étape de réglage normale : lancez le plan une première fois, lisez les chiffres que le message vous rend, et servez-vous-en comme seuils.

This probe was asked to prove nothing, so it proves nothing. Walking the restored tree found 1 842 file(s) in 96 directories, 412 998 231 bytes in total, but no check was configured…

Ces trois nombres sont exactement ce qu'il faut mettre dans RESTOREPROOF_CANARY_MIN_FILES et RESTOREPROOF_CANARY_MIN_TOTAL_SIZE.

Verdict

  • FAIL dès qu'un contrôle échoue, ou qu'un seuil n'est pas un entier supérieur ou égal à zéro. Un seuil ignoré en silence vous ferait croire à un plancher qui n'existe pas.
  • WARN si RESTOREPROOF_CANARY_PATTERN ne correspond à rien, ou si un chemin de l'arborescence n'a pas pu être lu.
  • PASS sinon.

Mesures : files, directories, total_size, errors, et selon les contrôles canary_files, verified, pattern, matches_found, min_files, min_total_size.


certificate

Lit un certificat TLS restauré et répond à deux questions : est-il encore utilisable, et est-ce bien le bon ?

Variable Défaut Rôle
RESTOREPROOF_CERT_PATH (obligatoire) Le ou les fichiers PEM, séparés par des virgules. Jokers acceptés. Un joker qui ne correspond à rien est un échec.
RESTOREPROOF_CERT_MIN_DAYS (vide) Nombre de jours de validité restants exigé. Les jours sont arrondis vers le bas : 29,9 jours ne satisfont pas 30.
RESTOREPROOF_CERT_EXPECT_CN (vide) Le common name attendu, comparé sans tenir compte de la casse.
RESTOREPROOF_CERT_EXPECT_SAN (vide) Un ou plusieurs SAN, séparés par des virgules, qui doivent tous être présents.
RESTOREPROOF_CERT_EXPECT_ISSUER (vide) Fragment que le nom de l'émetteur doit contenir.
RESTOREPROOF_CERT_FINGERPRINT (vide) L'empreinte SHA-256 du DER. 64 caractères hexadécimaux ; les :, espaces et - sont tolérés, la casse aussi.
RESTOREPROOF_CERT_REQUIRE_KEY false Exige qu'un bloc de clé privée soit présent dans le fichier. true, 1, yes ou on.

Pourquoi elle n'a rien de calibrable

Les autres sondes comparent un nombre observé à un seuil que vous ajustez après un premier essai. Ici il n'y a rien à ajuster : une date d'expiration, un common name, une empreinte sont des valeurs absolues, connues d'avance. Un certificat est valide ou expiré ; c'est le vôtre ou ce n'est pas le vôtre. RESTOREPROOF_CERT_MIN_DAYS est le seul chiffre, et il vient de votre politique de renouvellement, pas d'une mesure.

Ce qu'elle fait de la clé privée

Si le fichier contient un bloc de clé privée, la sonde le reconnaît par son type de bloc PEM et n'y touche pas. Ses octets ne sont ni lus, ni hachés, ni nommés. Le rapport dit seulement has_private_key: true.

Verdict : FAIL si le fichier est illisible, ne contient aucun bloc PEM, aucun bloc CERTIFICATE, si le certificat n'est pas analysable, pas encore valide, expiré, ou si l'une des attentes ci-dessus n'est pas satisfaite. PASS sinon.

Mesures (celles du certificat qui expire le plus tôt) : certificates, not_before, not_after, days_remaining, expired, not_yet_valid, self_signed, chain_length, chain_valid (chaque certificat du fichier est signé par le suivant), key_type, key_bits, signature_algorithm, fingerprint_sha256, is_ca. Avec plusieurs fichiers, le détail par fichier est ajouté sous files.

Le nom commun, les noms alternatifs et l'émetteur ne sont jamais rapportés : la sonde les compare à ce que vous attendez et dit seulement si l'attente est satisfaite. Un message d'échec nomme la valeur que vous attendiez, pas celle qu'elle a lue.


postgres

Se connecte à la base restaurée dans le bac à sable, relève sa forme, et compare un nombre à un seuil.

Variable Alias prioritaire Défaut
RESTOREPROOF_PG_HOST PGHOST localhost
RESTOREPROOF_PG_PORT PGPORT 5432
RESTOREPROOF_PG_USER PGUSER postgres
RESTOREPROOF_PG_PASSWORD PGPASSWORD (vide)
RESTOREPROOF_PG_DATABASE PGDATABASE (le pas de restauration)
RESTOREPROOF_PG_SSLMODE PGSSLMODE disable
RESTOREPROOF_PG_TABLE TABLE (vide)
RESTOREPROOF_PG_QUERY QUERY (vide)
RESTOREPROOF_PG_ASSERT ASSERT (vide)
RESTOREPROOF_PG_EXPECTED_ROWS EXPECTED_ROWS (vide)

L'alias est lu en premier : si PGHOST est défini, RESTOREPROOF_PG_HOST est ignoré. C'est ce que l'éditeur de plan utilise pour les six premières lignes. Les alias TABLE, QUERY, ASSERT et EXPECTED_ROWS sont des noms très courants : ne les utilisez que si vous maîtrisez l'environnement du conteneur.

La base ne se saisit pas ici. Elle est écrite une seule fois, dans le champ Base de données du pas restore_postgres, et le runner la transmet à toutes les sondes PostgreSQL du plan. Vous n'avez donc jamais à la répéter, et elle ne peut pas diverger entre la restauration et la vérification. Une valeur écrite malgré tout dans la configuration de la sonde reste prioritaire — c'est ce qui laisse fonctionner les plans créés avant ce changement.

Ce qui est compté. Une requête l'emporte sur une table : qui a écrit du SQL le pensait.

  • RESTOREPROOF_PG_QUERY — une requête qui rend une seule valeur. Si elle échoue, la sonde échoue. Si elle rend autre chose qu'un nombre et qu'une assertion est configurée, la sonde échoue en le disant. La valeur rendue ne quitte jamais votre machine : la sonde dit seulement si elle satisfait l'assertion, et une erreur de la base n'est rapportée que par son code SQLSTATE (voir ce que les sondes rapportent).
  • RESTOREPROOF_PG_TABLE — facultatif. La sonde fait un SELECT COUNT(*) dessus. La valeur sert aussi de fragment SQL : users WHERE akey <> '' est un compte conditionnel valide. Un identifiant simple est mis entre guillemets pour que les mots réservés fonctionnent. Le nombre de lignes n'est rapporté que pour un nom de table simple ; pour un fragment SQL, la sonde dit seulement si l'assertion est satisfaite, comme pour une requête. Laissée vide — et sans requête — la sonde vérifie la base entière : elle échoue si la base restaurée ne contient aucune table, et passe sinon. Aucun seuil de lignes ne s'applique alors, et RESTOREPROOF_PG_EXPECTED_ROWS est ignoré.

Verdict : FAIL si la connexion échoue, si la requête échoue, si le seuil n'est pas un entier, si une assertion est configurée mais que rien ne fournit de valeur, si la comparaison est fausse, ou si la base ne contient aucune table. WARN si la connexion réussit mais que SELECT version() échoue. PASS sinon.

Mesures : connect_time_ms, host, port, database, version, database_size_bytes, table_count, assertion, et selon le cas actual_rows (pour un nom de table simple), assert_source, expected_rows.


mysql

Même structure que postgres, pour MySQL et MariaDB.

Variable Alias prioritaire Défaut
RESTOREPROOF_MYSQL_HOST MYSQL_HOST localhost
RESTOREPROOF_MYSQL_PORT MYSQL_PORT 3306
RESTOREPROOF_MYSQL_USER MYSQL_USER root
RESTOREPROOF_MYSQL_PASSWORD MYSQL_PASSWORD (vide)
RESTOREPROOF_MYSQL_DATABASE MYSQL_DATABASE (le pas de restauration)
RESTOREPROOF_MYSQL_CHARSET MYSQL_CHARSET utf8mb4
RESTOREPROOF_MYSQL_TLS MYSQL_TLS false
RESTOREPROOF_MYSQL_TABLE TABLE (vide)
RESTOREPROOF_MYSQL_QUERY QUERY (vide)
RESTOREPROOF_MYSQL_ASSERT ASSERT (vide)
RESTOREPROOF_MYSQL_EXPECTED_ROWS EXPECTED_ROWS (vide)

Les alias sont lus en premier, exactement comme sous PostgreSQL, avec la même réserve sur TABLE, QUERY, ASSERT et EXPECTED_ROWS.

La base vient du champ Base de données du pas restore_mysql, comme sous PostgreSQL. L'éditeur de plan expose quand même MYSQL_DATABASE, dans les options avancées de la sonde : c'est l'exception d'un dump pris avec mysqldump --all-databases, qui en contient plusieurs et où la base à interroger n'est pas celle que le pas de restauration nomme.

RESTOREPROOF_MYSQL_TABLE est facultatif et accepte, comme sous PostgreSQL, un fragment SQL : users WHERE deleted_at IS NULL. Un identifiant simple est entouré de backquotes. Comme sous PostgreSQL, le nombre de lignes n'est rapporté que pour un nom de table simple, la valeur d'une requête ne l'est jamais, et une erreur de la base n'est rapportée que par son numéro et son code SQLSTATE. Laissé vide, et sans requête, la sonde vérifie la base entière : elle échoue si la base restaurée ne contient aucune table, et passe sinon, sans appliquer de seuil de lignes.

Mesures : connect_time_ms, host, port, database, version, database_size_bytes, table_count, assertion, et selon le cas actual_rows (pour un nom de table simple), assert_source, expected_rows.


mongodb

Variable Alias de repli Défaut
RESTOREPROOF_MONGO_HOST MONGO_HOST localhost
RESTOREPROOF_MONGO_PORT MONGO_PORT 27017
RESTOREPROOF_MONGO_USER MONGO_USER (vide — connexion anonyme)
RESTOREPROOF_MONGO_PASSWORD MONGO_PASSWORD (vide)
RESTOREPROOF_MONGO_DATABASE MONGO_DATABASE (le pas de restauration)
RESTOREPROOF_MONGO_AUTH_DATABASE MONGO_AUTH_DATABASE admin
RESTOREPROOF_MONGO_COLLECTION COLLECTION (vide)
RESTOREPROOF_MONGO_FILTER FILTER (vide)
RESTOREPROOF_MONGO_ASSERT ASSERT (vide)
RESTOREPROOF_MONGO_EXPECTED_ROWS EXPECTED_ROWS (vide)

Comme pour ldap, et contrairement aux sondes SQL, c'est ici la variable RESTOREPROOF_* qui est lue en premier, l'alias court ne servant que de repli. C'est ce que l'éditeur de plan écrit. Les alias COLLECTION, FILTER, ASSERT et EXPECTED_ROWS sont des noms très courants : ne les utilisez que si vous maîtrisez l'environnement du conteneur.

La base est celle du champ Base de données du pas restore_mongo : un mongorestore recrée la base sous le nom qu'elle porte dans le dump, et le runner transmet ce nom aux sondes MongoDB du plan. Vous ne le saisissez donc qu'une fois.

RESTOREPROOF_MONGO_FILTER est un filtre en JSON étendu MongoDB ({"status":"active"}). Un filtre invalide fait échouer la sonde.

Il n'y a pas de mode « requête libre » : le nombre observé est toujours le compte de documents d'une collection, éventuellement filtré.

Verdict : FAIL si la base n'est pas nommée, si la connexion échoue, si le filtre est invalide, si le comptage échoue, si une assertion est configurée sans collection, ou si la comparaison est fausse. WARN si la connexion réussit mais que la liste des collections échoue. PASS sinon.

Mesures : connect_time_ms, host, port, database, server_version, collection_count, assertion, et selon le cas actual_rows, assert_source, expected_rows, collections_found, databases_found.

Ce que la sonde vous montre quand elle ne trouve pas ce que vous visiez

Deux mesures de découverte, publiées seulement quand elles servent à quelque chose. Elles ne contiennent que des noms et des comptes, jamais le contenu des documents.

  • collections_found — la base contient des collections, mais aucune n'est configurée, ou celle du plan n'existe pas. La sonde liste ce qu'elle a trouvé, la plus remplie d'abord (les collections system.* sont écartées, et la liste s'arrête à cinquante entrées) :

    "collections_found": [
      {"name": "products", "documents": 50},
      {"name": "orders", "documents": 500}
    ]
    
  • databases_found — la base configurée est vide. La sonde liste alors les autres bases du serveur avec leur nombre de collections, ce qui suffit souvent à voir qu'on s'est trompé de nom. Les bases techniques admin, local et config sont écartées :

    "databases_found": [
      {"name": "demo", "collections": 3}
    ]
    

Le message de la sonde reprend les cinq premières entrées, pour que le verdict se lise sans ouvrir les mesures. L'essai de plan s'appuie sur ces deux mesures pour vous proposer la base, la collection et le seuil : voir la calibration.


sqlite

Lit un fichier de base SQLite dans l'espace de travail. Contrairement aux précédentes, elle ne parle à aucun bac à sable.

Variable Défaut Rôle
RESTOREPROOF_SQLITE_PATH (obligatoire) Le fichier, relatif à /workspace. Un joker est accepté (daily/*.db) ; s'il correspond à plusieurs fichiers, le premier par ordre alphabétique est retenu.
RESTOREPROOF_SQLITE_INTEGRITY quick quick (PRAGMA quick_check), full (PRAGMA integrity_check), ou off / none. Toute autre valeur fait échouer la sonde.
RESTOREPROOF_SQLITE_TARGET (vide) Nom d'une table ou d'une vue à compter. C'est un nom, jamais un fragment SQL.
RESTOREPROOF_SQLITE_QUERY (vide) Une requête rendant une seule valeur. L'emporte sur TARGET. La valeur n'est jamais rapportée : la sonde dit seulement si elle satisfait l'assertion.
RESTOREPROOF_SQLITE_ASSERT (vide) gte, lte, eq, zero.
RESTOREPROOF_SQLITE_EXPECTED_ROWS (vide) Le seuil.

Deux détails qui comptent

L'en-tête est vérifié avant tout le reste. Un téléchargement tronqué, un dump gzippé ou une page d'erreur HTML enregistrée en .db produisent un message qui nomme le vrai problème, au lieu du file is not a database du pilote.

La base est copiée à côté avant d'être ouverte. L'espace de travail est monté en lecture seule, et SQLite a besoin d'écrire : il rejoue et intègre le -wal à l'ouverture. La sonde copie le fichier et ses compagnons -wal et -shm dans un répertoire temporaire. C'est ce qui fait que les dernières transactions d'une base copiée à chaud font partie de la preuve.

Si TARGET nomme une table qui n'existe pas, le message liste les tables et vues réellement présentes.

Mesures : database, database_size_bytes, integrity, tables, page_count, page_size, schema_version, journal_mode, assertion, et selon le cas rows (pour une table nommée), assert_source, expected_rows, integrity_report.


pocketbase

Interroge une instance PocketBase en fonctionnement, remontée sur le pb_data restauré. Elle ne lit aucun fichier : il faut donc une étape start_sandbox avant elle.

Variable Défaut Rôle
RESTOREPROOF_PB_URL (obligatoire) L'URL de l'instance, par l'alias de son bac à sable : http://sandbox:8090.
RESTOREPROOF_PB_TOKEN (vide) Un jeton déjà obtenu. L'emporte sur le couple e-mail / mot de passe.
RESTOREPROOF_PB_ADMIN_EMAIL (vide) Identifiant du super-utilisateur.
RESTOREPROOF_PB_ADMIN_PASSWORD (vide) Son mot de passe.
RESTOREPROOF_PB_COLLECTION (vide) La collection dont on compte les enregistrements.
RESTOREPROOF_PB_FILTER (vide) Un filtre PocketBase, par exemple verified = true.
RESTOREPROOF_PB_ASSERT (vide) gte, lte, eq, zero.
RESTOREPROOF_PB_EXPECTED_ROWS (vide) Le seuil.
RESTOREPROOF_PB_TIMEOUT_SECONDS 30 Délai des appels HTTP. À défaut, RESTOREPROOF_TIMEOUT_SECONDS est utilisé.

Le déroulé. /api/health d'abord : une instance qui ne répond pas là n'a pas démarré sur les données restaurées, ce qui est précisément ce qu'on prouve. Puis l'authentification, si des identifiants sont fournis — /api/collections/_superusers/auth-with-password, avec repli sur /api/admins/auth-with-password pour les versions antérieures à PocketBase 0.23, qui sont exactement celles qu'on retrouve dans une vieille sauvegarde. Puis le comptage.

Les enregistrements ne sont jamais lus. La sonde demande une page d'un seul élément et ne retient que totalItems : le contenu est de la donnée client, il ne doit ni être tiré ni figurer au rapport. Un mot de passe glissé dans l'URL est remplacé par redacted avant que celle-ci n'entre dans le message.

Mesures : health, auth, assertion, pb_version, et selon le cas records, collections, expected_rows.


ldap

Trois contrôles indépendants, dont au moins un doit être demandé. Sinon la sonde échoue avant d'envoyer le moindre paquet.

Variable Défaut Rôle
RESTOREPROOF_LDAP_HOST localhost Alias de repli : LDAP_HOST.
RESTOREPROOF_LDAP_PORT 389 Alias de repli : LDAP_PORT.
RESTOREPROOF_LDAP_TLS none none, starttls ou ldaps. Toute autre valeur est un échec. Alias : LDAP_TLS.
RESTOREPROOF_LDAP_INSECURE false Ne pas vérifier le certificat du serveur. Alias : LDAP_INSECURE.
RESTOREPROOF_LDAP_BIND_DN (vide — connexion anonyme) Le DN de service. Alias : LDAP_BIND_DN.
RESTOREPROOF_LDAP_PASSWORD (vide) Son mot de passe. Alias : LDAP_PASSWORD.
RESTOREPROOF_LDAP_TIMEOUT 30 En secondes.

Contrairement aux sondes SQL, c'est ici la variable RESTOREPROOF_* qui est lue en premier, l'alias court ne servant que de repli.

Contrôle 1 — compter les entrées

Variable Défaut
RESTOREPROOF_LDAP_BASE_DN (vide)
RESTOREPROOF_LDAP_FILTER (objectClass=*)
RESTOREPROOF_LDAP_SCOPE sub — ou one, ou base
RESTOREPROOF_LDAP_ASSERT (vide)
RESTOREPROOF_LDAP_EXPECTED_ENTRIES (vide)

La recherche est paginée (500 entrées par page), donc un annuaire plus gros que la limite du serveur — slapd s'arrête à 500 par défaut — est compté en entier au lieu d'être tronqué en silence.

Si le serveur tronque quand même la réponse, la sonde échoue en disant que c'est une limite du serveur, sans rapport avec la restauration. Elle n'affirme jamais que la sauvegarde est incomplète alors qu'elle ne le sait pas.

Avec un base DN mais sans RESTOREPROOF_LDAP_ASSERT, la sonde rapporte le nombre observé et passe. Avec un opérateur mais sans seuil, le seuil vaut 1 (ou 0 pour zero).

Contrôle 2 — un DN doit exister

RESTOREPROOF_LDAP_EXPECT_DN — par exemple uid=jdoe,ou=people,dc=example,dc=org. Absent, c'est un échec.

Contrôle 3 — un compte doit pouvoir s'authentifier

RESTOREPROOF_LDAP_TEST_BIND_DN et RESTOREPROOF_LDAP_TEST_BIND_PASSWORD.

C'est le contrôle qui prouve qu'un userPassword restauré fonctionne encore. Il ouvre une seconde connexion pour ce test, plutôt que de réutiliser celle déjà authentifiée en tant qu'administrateur.

Mesures : connect_time_ms, server_host, expect_dn, bind_test, et selon le cas base_dn, filter, scope, paged, entries, assertion, expected_entries, naming_contexts.

naming_contexts est purement informatif — les suffixes que le serveur sert réellement. C'est la première chose à regarder quand un base DN ne rend aucune entrée.


http

Interroge un service remonté sur les données restaurées.

Variable Défaut Rôle
RESTOREPROOF_HTTP_URL (obligatoire) L'URL à appeler, sur l'alias d'un bac à sable de l'exécution : http://sandbox/, http://sandbox-2:8080/.
RESTOREPROOF_HTTP_METHOD GET Passe automatiquement à POST si un corps est fourni et que la méthode n'est pas définie.
RESTOREPROOF_HTTP_EXPECTED_STATUS 200 Le code attendu. Une valeur non numérique fait échouer la sonde en le disant.
RESTOREPROOF_HTTP_EXPECTED_BODY (vide) Chaîne que la réponse doit contenir.
RESTOREPROOF_HTTP_TIMEOUT 30 En secondes.
RESTOREPROOF_HTTP_INSECURE false true pour ne pas vérifier le certificat.
RESTOREPROOF_HTTP_HEADERS (vide) Cle1:Valeur1,Cle2:Valeur2.
RESTOREPROOF_HTTP_BODY (vide) Le corps de la requête.
RESTOREPROOF_HTTP_CONTENT_TYPE application/json (si un corps est fourni) Le type du corps.

Le code de statut ne prouve que le démarrage du conteneur. RESTOREPROOF_HTTP_EXPECTED_BODY est le champ qui prouve que ce sont bien vos données restaurées qui sont servies : le nom de votre boutique, un titre d'article, un identifiant qui n'existe que chez vous.

La réponse est lue au plus sur 1 Mio.

La sonde ne joint que les bacs à sable de son exécution. Une URL publique, une adresse de votre réseau ou celle de la machine du runner ne répondent pas : le réseau de l'exécution est fermé (voir l'isolement réseau).

Mesures : url, method, response_time_ms, status_code, content_length, body_size_bytes, content_type, et body_match si le contenu attendu a été trouvé.