guest@6admin.io:~$

Quand un checksum Chocolatey casse tout un provisioning

Le provisioning d’un parc de machines Windows s’arrête net sur une tâche Ansible qui installe un package Chocolatey et le message est un classique du genre:

ERROR: Checksum for 'p4vinst64.exe' did not meet '45648d...852bd5'
for checksum type 'sha256'.

Le checksum attendu par le package ne correspond pas au binaire téléchargé. Rien dans mon infrastructure n’a changé et pourtant la veille ça passait. L’histoire est courte, mais elle dit quelque chose d’important sur ce que signifie “dépendre d’un package communautaire”.

Ce qui s’est passé

Le package p4v de Chocolatey Community n’embarque pas le binaire, il pointe vers le serveur de téléchargement de l’éditeur et vérifie un checksum. Perforce a publié une nouvelle version de p4vinst64.exe sur son serveur sans que le mainteneur du package n’ait mis à jour le checksum correspondant. Résultat, le hash réel du binaire ne correspond plus au hash figé dans le package, Chocolatey refuse l’installation et Ansible échoue.

C’est le comportement correct, il faut le souligner: la vérification de checksum a fait exactement son travail, elle a refusé un binaire dont l’empreinte ne correspondait pas à celle attendue. Le problème n’est pas le contrôle, c’est la désynchronisation entre deux parties que je ne contrôle ni l’une ni l’autre, l’éditeur qui pousse le binaire et le mainteneur bénévole qui met à jour le package. Et cette désynchronisation est fréquente pour les packages dont le binaire est hébergé chez l’éditeur plutôt qu’embarqué dans le paquet.

Les trois sorties et ce qu’elles coûtent

La première est d’attendre: signaler au mainteneur et patienter qu’il republie. C’est propre, ça ne touche à rien chez moi et c’est inutilisable quand un provisioning est bloqué, parce que le délai se compte en heures ou en jours.

La deuxième est de passer ignore_checksums et c’est là qu’il faut être discipliné. Activé globalement sur la boucle d’installation, ce flag désactive la vérification pour tous les packages, pas seulement celui qui coince, ce qui revient à éteindre le détecteur de fumée parce qu’une poêle a brûlé. La bonne écriture est de le conditionner au seul package fautif:

- name: Install packages
  chocolatey.chocolatey.win_chocolatey:
    name: "{{ item.name | default(item) }}"
    state: present
    ignore_checksums: "{{ item.ignore_checksums | default(false) }}"
  loop: "{{ packages }}"
packages:
  - git
  - vscode
  - name: p4v
    ignore_checksums: true

C’est un déblocage, assumé comme tel, à retirer dès que le package amont est corrigé et jamais un réglage permanent par défaut.

La troisième est la vraie réponse de fond: héberger ses propres packages NuGet, avec le binaire embarqué dans le paquet plutôt que téléchargé chez l’éditeur. On gagne le contrôle des versions et des checksums, l’indépendance vis-à-vis de la communauté et surtout la reproductibilité, un déploiement qui donne le même résultat aujourd’hui et dans six mois. On y perd l’effort de mise en place et la maintenance continue, surveiller les releases amont et rebuilder, mais pour les outils critiques d’un parc, ceux qui présentent régulièrement ce genre d’aléa, c’est le prix de la reproductibilité.

Un octet, tout le provisioning par terre

Un checksum qui refuse un binaire n’est pas une panne, c’est un contrôle qui fonctionne et le réflexe --ignore-checksums global est exactement la mauvaise réponse parce qu’il transforme un incident ponctuel en angle mort permanent. Dépendre d’un package dont le binaire vit chez l’éditeur, c’est accepter deux points de défaillance qu’on ne maîtrise pas et pour un provisioning qu’on veut reproductible, l’hébergement interne des packages critiques n’est pas une sur-ingénierie, c’est la condition pour que “le même playbook” veuille dire “le même résultat”. Court terme, le bypass conditionnel sur le seul package fautif; moyen terme, le dépôt NuGet interne pour les outils qui comptent.