Vérifier des manifestes d’artefacts avec b2sum et GNU Parallel
Utilisez b2sum de GNU pour consigner un ensemble d’artefacts finalisés,
puis vérifiez cet ensemble sans régénérer les valeurs attendues. Ce tutoriel calcule en parallèle
les empreintes des fichiers d’un petit répertoire de sauvegarde, remplace le manifeste uniquement
si tous les calculs réussissent et propage les échecs de vérification au shell ou à une tâche CI.
Une empreinte seule ne permet pas d’établir qui a créé un fichier : obtenez la somme de contrôle attendue par un canal de confiance, comme une publication authentifiée ou un manifeste signé, plutôt que de télécharger le fichier et sa somme de contrôle depuis une source non fiable.
Choisir le format de somme de contrôle correspondant
b2sum de GNU
utilise par défaut BLAKE2b-512, représenté par 128 caractères hexadécimaux. Utilisez le même
algorithme et la même longueur d’empreinte que pour les valeurs attendues. BLAKE2s et SHA-256
sont des formats différents ; si un éditeur fournit une somme SHA-256, vérifiez-la avec
sha256sum plutôt que de créer une référence BLAKE2 à partir du fichier téléchargé.
Cette démonstration crée une référence locale à partir de fichiers connus. Dans un processus de publication, générez le manifeste du côté du producteur de confiance une fois les artefacts finalisés, puis protégez son origine et son contenu. Quiconque peut remplacer à la fois les artefacts et les valeurs attendues peut faire réussir la vérification.
Vérifier les prérequis sous Linux
Utilisez Linux avec Bash, GNU coreutils, GNU findutils, GNU Parallel et Python 3. Sous Debian ou
Ubuntu, les paquets correspondants sont bash, coreutils, findutils, parallel et python3.
GNU Parallel nécessite une installation distincte ; une autre commande nommée
parallel ne peut pas le remplacer.
Vérifiez leur disponibilité avant de créer le répertoire de démonstration :
bash --version && b2sum --version && find --version && parallel --version && python3 --version
L’exemple a été testé avec Bash 5.3.15, coreutils 9.11, findutils 4.11.0, GNU Parallel 20240222 et Python 3.14.7. Python sert uniquement à créer les fichiers de démonstration et ne nécessite aucun paquet tiers. Ce processus s’exécute localement sous Linux ; il ne s’agit pas d’une procédure pour macOS ou Windows.
Créer un petit ensemble d’artefacts
Commencez dans un répertoire que vous contrôlez. Cette commande crée un répertoire et s’y place, mais refuse de réutiliser un répertoire existant :
mkdir -- integrity-demo && cd -- integrity-demo
Conservez les autres fichiers et exécutez les autres commandes dans integrity-demo.
Enregistrez le code suivant dans make-fixture.py :
from pathlib import Path
root = Path('backups')
root.mkdir()
(root / 'archive').mkdir()
samples = {
'app.tar': b'first release\n',
'archive/app.tar': b'other release\n',
'empty.tar': b'',
'-draft.tar': bytes([0, 255, 16, 10]),
'café copy.tar': b'Unicode name\n',
'line\nbreak.tar': b'newline name\n',
}
for name, content in samples.items():
(root / name).write_bytes(content)
Exécutez-le une fois :
python3 -I make-fixture.py
Ces six petits fichiers couvrent les contenus vides et binaires, les noms de base identiques,
les espaces, Unicode et un saut de ligne dans un nom de fichier. Ils contiennent des octets
servant d’exemple et portent le suffixe .tar ; ce ne sont pas de véritables
archives tar. Le générateur refuse un répertoire backups existant. Si la
préparation est interrompue, inspectez le répertoire partiellement créé et commencez une nouvelle
démonstration dans un répertoire inutilisé ; relancer le générateur ne réparera ni n’écrasera les
fichiers précédents.
Générer un manifeste complet
Enregistrez ce code dans hash-backups.sh. Exécutez-le comme un script Bash enregistré
plutôt que de le coller dans votre shell :
#!/usr/bin/env bash
set -euo pipefail
export LC_ALL=C
umask 077
if (( $# != 1 )) || [[ -z $1 ]]; then
printf 'Usage: bash hash-backups.sh BACKUP_DIR\n' >&2
exit 2
fi
backupDir=$1
if [[ $backupDir != /* ]]; then
backupDir=./$backupDir
fi
if [[ ! -d $backupDir ]]; then
printf 'Not a directory: %s\n' "$backupDir" >&2
exit 2
fi
tempDir=$(mktemp -d .checksums.XXXXXX)
trap 'rm -rf -- "$tempDir"' EXIT
find "$backupDir" -type f -name '*.tar' -print0 > "$tempDir/files.nul"
if [[ ! -s $tempDir/files.nul ]]; then
printf 'No .tar files selected in %s\n' "$backupDir" >&2
exit 1
fi
sort -z "$tempDir/files.nul" |
parallel --plain --will-cite --tmpdir "$tempDir" -0 --jobs 4 \
--keep-order --halt now,fail=1 b2sum -- {} > "$tempDir/checksums.b2"
test -s "$tempDir/checksums.b2"
mv -fT -- "$tempDir/checksums.b2" checksums.b2
Exécutez le producteur :
bash hash-backups.sh backups
Il sélectionne récursivement les fichiers ordinaires portant le suffixe en minuscules
.tar, sans suivre les liens symboliques. GNU Parallel exécute jusqu’à
quatre tâches de hachage, regroupe leurs sorties et conserve l’ordre trié des entrées. Son
option --plain ignore les profils personnels
et les réglages PARALLEL, tandis que --halt now,fail=1 arrête
l’exécution si un calcul d’empreinte échoue. Une sélection vide, un échec du parcours du répertoire
ou un échec du calcul d’une empreinte entraîne une sortie avec un code non nul avant le
remplacement de checksums.b2.
Le répertoire temporaire se trouve à côté de la destination ; le mv
final publie donc le manifeste complet en le renommant sur le même système de fichiers.
Une nouvelle exécution réussie remplace le manifeste précédent ; en cas d’échec, celui-ci reste
intact et les fichiers temporaires sont supprimés. Exécutez un seul producteur à la fois et gardez
le répertoire des artefacts inchangé pendant le parcours, le calcul des empreintes ou la
vérification. Il ne s’agit pas d’un instantané du système de fichiers.
Vérifier les fichiers consignés
Exécutez le consommateur depuis le même répertoire integrity-demo, en laissant
checksums.b2 inchangé :
b2sum --check --strict --quiet checksums.b2 && printf 'All recorded files match checksums.b2\n'
All recorded files match checksums.b2
--check
lit les chemins contenus dans le manifeste. Ces chemins incluent les répertoires ; les deux
fichiers app.tar restent donc distincts. Les chemins relatifs sont résolus
à partir de votre répertoire courant, pas de celui du manifeste. Copiez toute l’arborescence avec
le manifeste lorsque vous vérifiez un ensemble transféré.
find -print0 et parallel -0 préservent les limites entre les
noms de fichiers. Le manifeste lui-même utilise le
format GNU délimité par des sauts de ligne avec échappement,
qui peut représenter les sauts de ligne et les barres obliques inverses dans les noms de fichiers.
Ne découpez pas ses enregistrements sur les caractères d’espacement et n’ajoutez pas
b2sum --zero : la sortie des sommes de contrôle délimitée par NUL
n’est pas prise en charge par --check.
Modifiez maintenant uniquement l’artefact voulu et répétez l’étape de vérification :
printf 'changed release\n' >> backups/app.tar &&
b2sum --check --strict --quiet checksums.b2
La commande se termine avec un code non nul et signale une somme de contrôle différente pour
./backups/app.tar, même si backups/archive/app.tar existe toujours.
Un fichier consigné manquant ou illisible provoque également un échec.
--strict fait aussi échouer la vérification en présence d’enregistrements
mal formés de sommes de contrôle. Corrigez l’artefact ou restaurez-le depuis une copie de confiance
avant de vérifier à nouveau ; régénérer le manifeste reviendrait à accepter les octets modifiés.
La vérification porte sur les fichiers consignés. Elle ne détecte pas les fichiers nouvellement ajoutés, ne vérifie pas la structure des archives et ne permet pas d’établir qui a créé les artefacts. Lorsque vous souhaitez changer la référence, effectuez une nouvelle exécution du producteur et soumettez son résultat à une revue, plutôt que de considérer les fichiers supplémentaires comme déjà vérifiés.
Propager les échecs en CI
Enregistrez la commande de vérification dans verify-backups.sh pour transmettre son
code de sortie à l’appelant :
#!/usr/bin/env bash
set -euo pipefail
b2sum --check --strict checksums.b2
Exécutez-la depuis le répertoire contenant le manifeste de confiance et l’arborescence qu’il consigne :
bash verify-backups.sh
Une tâche CI peut utiliser cette même invocation après avoir récupéré un manifeste protégé depuis le dépôt et rendu les artefacts disponibles aux chemins consignés. Gardez la génération du manifeste en dehors de la tâche de vérification. Examinez séparément les mises à jour légitimes de la référence et protégez l’accès en écriture au manifeste ainsi qu’aux artefacts. Transmettre la sortie de la vérification à une autre commande par un tube sans préserver son code de sortie peut masquer une différence de somme de contrôle.
Mesurer les performances sur votre charge de travail
Les performances dépendent de la taille des fichiers, du stockage, de la mise en cache, des
instructions du processeur et de l’implémentation. Ces commandes montrent comment mesurer le temps
de traitement du fichier de démonstration. Remplacez backups/app.tar par un fichier
représentatif finalisé pour obtenir des mesures pertinentes :
time b2sum -- backups/app.tar > /dev/null &&
time sha256sum -- backups/app.tar > /dev/null
Les minuscules fichiers de démonstration ne permettent pas de comparer utilement les vitesses.
Ne supposez pas que BLAKE2 est toujours plus rapide que SHA-256 avec accélération matérielle.
Le hachage parallèle peut entraîner une contention sur le même périphérique de stockage ;
mesurez donc l’effet du nombre de processus de travail sur votre propre jeu de données avant
d’augmenter --jobs.
Pour vérifier un seul fichier téléchargé après l’avoir déplacé, consultez le tutoriel de vérification avec b2sum.
