Vérification finale et tests d’acceptation#
Pourquoi#
Chaque chapitre précédent a sa propre section “Vérifier”, ciblée sur un composant isolé. Mais un système fait de vingt pièces qui fonctionnent individuellement ne garantit pas qu’elles fonctionnent bien ensemble, et surtout, tester manuellement vingt points à chaque changement de configuration est long et sujet à l’oubli. La solution : un script d’acceptation unique, exécutable en une commande, qui audite l’ensemble du système et catégorise chaque vérification en OK / WARN / CRITICAL.
Comment#
Principe de structure#
#!/bin/bash
OK_COUNT=0; WARN_COUNT=0; CRIT_COUNT=0
ok() { printf " [ OK ] %s\n" "$1"; OK_COUNT=$((OK_COUNT+1)); }
warn() { printf " [ WARN ] %s (%s)\n" "$1" "$2"; WARN_COUNT=$((WARN_COUNT+1)); }
critical() { printf " [ CRITICAL ] %s (%s)\n" "$1" "$2"; CRIT_COUNT=$((CRIT_COUNT+1)); }Chaque vérification suit ce schéma : mesurer une valeur, la comparer à un
seuil, et appeler ok/warn/critical selon le résultat. Par exemple,
pour le RMS offset (chapitre Chrony) :
RMS=$(chronyc tracking 2>/dev/null | awk '/^RMS offset/ {print $4}')
if [ "$(echo "$RMS < 0.000001" | bc -l)" = "1" ]; then
ok "RMS offset = ${RMS}s (< 1µs)"
elif [ "$(echo "$RMS < 0.00001" | bc -l)" = "1" ]; then
warn "RMS offset = ${RMS}s" "cible < 1µs"
else
critical "RMS offset = ${RMS}s" "dérive importante"
fiCatégories de vérification couvertes#
Un script d’acceptation complet pour ce type de serveur couvre typiquement :
| Catégorie | Exemples de vérifications |
|---|---|
| Services critiques | chrony/nginx/fail2ban/auditd actifs, aucun service en échec |
| Synchronisation horaire | Stratum, Reference ID, RMS offset, skew, leap status |
| PPS/GNSS | /dev/pps0 présent, impulsions actives, fix 3D, nombre de satellites |
| Réseau | adressage IPv4/IPv6, routes par défaut, résolution DNS |
| Web | config nginx valide, accessibilité HTTPS, fraîcheur de la télémétrie |
| TLS | validité du certificat, type de clé, version TLS négociée |
| Sécurité | jails fail2ban actives, tables nftables provisionnées, règles auditd |
| Système | usage disque/RAM, absence de swap, fraîcheur des graphes Munin |
| Journaux | erreurs récentes, absence d’OOM killer, anomalies d’audit |
Assembler un script minimal#
Les fragments ci-dessus se combinent en un script réel, court mais déjà utile, à étendre au fil des chapitres avec ses propres seuils :
cat > acceptance.sh <<'EOF'
#!/bin/bash
OK_COUNT=0; WARN_COUNT=0; CRIT_COUNT=0
ok() { printf " [ OK ] %s\n" "$1"; OK_COUNT=$((OK_COUNT+1)); }
warn() { printf " [ WARN ] %s (%s)\n" "$1" "$2"; WARN_COUNT=$((WARN_COUNT+1)); }
critical() { printf " [ CRITICAL ] %s (%s)\n" "$1" "$2"; CRIT_COUNT=$((CRIT_COUNT+1)); }
# Services critiques
for svc in chrony nginx fail2ban auditd; do
if systemctl is-active --quiet "$svc"; then
ok "$svc actif"
else
critical "$svc inactif" "systemctl status $svc"
fi
done
# RMS offset (chapitre Chrony)
RMS=$(chronyc tracking 2>/dev/null | awk '/^RMS offset/ {print $4}')
if [ -z "$RMS" ]; then
critical "RMS offset illisible" "chronyc injoignable ?"
elif [ "$(echo "$RMS < 0.000001" | bc -l)" = "1" ]; then
ok "RMS offset = ${RMS}s (< 1µs)"
elif [ "$(echo "$RMS < 0.00001" | bc -l)" = "1" ]; then
warn "RMS offset = ${RMS}s" "cible < 1µs"
else
critical "RMS offset = ${RMS}s" "dérive importante"
fi
# PPS/GNSS
if [ -e /dev/pps0 ]; then
ok "/dev/pps0 présent"
else
critical "/dev/pps0 absent" "module pps-gpio chargé ?"
fi
# Système : pas de swap actif
if [ "$(swapon --show | wc -l)" -eq 0 ]; then
ok "aucun swap actif"
else
warn "swap actif détecté" "cf. chapitre Système de fichiers"
fi
echo
echo "RÉSUMÉ ACCEPTANCE"
printf " OK : %3d\n" "$OK_COUNT"
printf " WARN : %3d\n" "$WARN_COUNT"
printf " CRITICAL : %3d\n" "$CRIT_COUNT"
echo
if [ "$CRIT_COUNT" -gt 0 ]; then
echo ">>> ÉCHEC - $CRIT_COUNT problème(s) critique(s)"
elif [ "$WARN_COUNT" -gt 0 ]; then
echo ">>> SUCCÈS PARTIEL - $WARN_COUNT avertissement(s)"
echo ">>> Surveillance recommandée"
else
echo ">>> SUCCÈS COMPLET"
fi
EOF
chmod +x acceptance.shCette version tient en quelques exemples de vérifications pour rester lisible dans ce guide. Le script réel de ce projet en compte près d’une centaine, une par ligne du tableau ci-dessus, ajoutée progressivement à chaque chapitre au fil de l’installation.
Erreurs à éviter#
Un test qui échoue systématiquement, quel que soit l’état réel du système, est pire qu’aucun test. Il crée une fausse habitude d’ignorer les avertissements (“ce WARN-là, c’est normal, il est toujours là”). C’est arrivé concrètement sur ce projet avec un test TLS : la vérification cherchait la chaîne exacte
Protocol : TLSv1.3dans la sortie d’openssl s_clientpour confirmer la version négociée. Un changement mineur de version d’OpenSSL a suffi à faire disparaître cet espacement précis (Protocol : TLSv1.3, deux espaces au lieu d’un) : le test échouait en permanence, alors que TLS 1.3 était bel et bien négocié à chaque connexion. Quand un test échoue de façon constante sur un système qui semble par ailleurs sain, la première question à se poser n’est pas “qu’est-ce qui est cassé côté serveur ?” mais “le test lui-même mesure-t-il ce qu’il prétend mesurer ?”
- Seuils WARN/CRITICAL copiés sans adaptation au contexte réel. Un seuil de température de 60 °C peut être parfaitement normal sous un climat tempéré et systématiquement dépassé sous un climat plus chaud, sans que cela reflète un vrai problème. Calibrer les seuils sur l’observation réelle du système, pas sur une valeur générique trouvée ailleurs.
- Laisser des WARN permanents s’installer comme bruit de fond. Sur un système avec plusieurs dizaines de vérifications, certains constats relèvent d’une limitation réelle, connue et acceptée (bug matériel documenté, faux positif d’un outil tiers). Les laisser en WARN à chaque exécution contredirait le principe ci-dessus : c’est exactement ainsi que naît l’habitude d’ignorer les avertissements. Le bon traitement est d’en faire une exception explicite dans le test lui-même : le cas connu passe en OK, accompagné de sa justification dans le message, comme le fait la batterie de ce projet pour l’horodatage matériel TX (« bug driver macb Pi 5, attendu », chapitre PHC). Un WARN reste alors réservé aux états transitoires appelés à disparaître (fonctionnalité pas encore déployée), et la sortie normale tend vers zéro avertissement : tout WARN qui apparaît est un signal neuf qui mérite attention, jamais un bruit ambiant.
Vérifier#
./acceptance.shSortie attendue en fin de script :
RÉSUMÉ ACCEPTANCE
OK : 83
WARN : 0
CRITICAL : 0
>>> SUCCÈS COMPLETCe script doit tourner après chaque modification de configuration,
pas seulement à l’installation initiale : c’est le meilleur filet de
sécurité contre les régressions silencieuses. Un 0 CRITICAL est le
seuil minimal de mise en production ; les WARN doivent tous être
expliqués (voir ci-dessus), pas simplement ignorés.