Set-OPS-Public/roles/chrony/templates/sonde-horloge.sh.j2
Daniel Allaire 6786d15068 l heure vient de la frontiere : la derniere dependance vivante tombe
Mesure sur les quatorze : aucune sortie TCP vers une adresse publique, apt
par le cache, noms autoritaires en local, unattended-upgrades masked. Et
quatre pairs NTP publics par machine. Le role chrony posait le fuseau et
installait le demon sans jamais toucher a ses sources : le defaut de Debian
tenait depuis le premier jour, herite et jamais choisi.

L autorite est la frontiere, par decision de l exploitant. Elle etait deja
stratum 2 et ecoutait en 123 ; il ne manquait que le passage. 9 anciennes
regles port 123 vers !SETOPS_INTERNES retirees, 9 regles nommees vers
SETOPS_FRONTIERE posees : le changement resserre autant qu il centralise.

Deux chemins parce que la topologie en a deux. Un tenant n atteint pas la
frontiere par sa passerelle de zone — tenue par le SDN — mais par le lien de
transit. Une machine du site a la frontiere pour passerelle directe. Les deux
valeurs sont derivees de l underlay, via reseau_transit() plutot que d un
prefixe d adresse qui aurait menti chez le prochain hebergeur.

La patte face aux tenants manquait a opnsense_if_zones, pour la meme raison
que grappe-controle la veille.

Sonde horloge ecrite en meme temps : synchronisee ET contre la source
DECLAREE. Une machine peut etre parfaitement a l heure contre quatre serveurs
publics — c est exactement l etat d avant.

14 tenant + 7 site, toutes disciplinees, sources publiques = 0.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Crgis8CxCWkAGFA1ecBz3q
2026-09-11 12:08:13 -04:00

71 lines
2.9 KiB
Django/Jinja

#!/bin/bash
# GENERE par Set-OPS (role chrony). Ne pas editer a la main.
#
# SONDE « horloge » — la machine est-elle synchronisee, ET contre LA SOURCE DECLAREE ?
#
# LES DEUX MOITIES COMPTENT. Une machine peut etre parfaitement a l'heure en interrogeant
# quatre serveurs publics : c'est le defaut de Debian, et il a tenu quatorze machines
# jusqu'au 2026-09-11 sans que rien ne le dise. Mesurer la seule derive laisserait ce
# retour en arriere invisible.
#
# POURQUOI L'HEURE MERITE UNE SONDE. step-ca emet des certificats a duree courte ; TLS
# refuse un certificat pas encore valide ; Loki rejette une ligne trop loin dans le futur ;
# les silences d'Icinga reposent sur des `ttl`. Une flotte dont les horloges divergent
# tombe en panne de l'interieur, avec des symptomes qui ressemblent a tout sauf a une
# horloge.
#
# Contrat : docs/supervision-conception.md (API des greffons Nagios) — une ligne, 0/1/2.
# Mise en defaut PAR PARAMETRE : `chrony_sonde_ecart_max` (le baisser a 0).
set -uo pipefail
ECART_MAX={{ chrony_sonde_ecart_max }}
ATTENDUS="{{ chrony_serveurs | join(' ') }}"
if ! systemctl is-active --quiet chrony; then
echo "chrony ne tourne pas : l'horloge derive sans que personne ne la corrige." \
"| ecart=U sources=0 declarees=0"
exit 2
fi
# `^*` marque la source RETENUE. Sans elle, chrony tourne mais ne suit personne.
retenue=$(chronyc -n sources 2>/dev/null | awk '/^\^\*/ {print $2; exit}')
sources=$(chronyc -n sources 2>/dev/null | tail -n +3 | wc -l)
if [[ -z "${retenue}" ]]; then
echo "chrony tourne mais n'a retenu AUCUNE source (${sources} candidate(s)) :" \
"l'heure n'est plus disciplinee." \
"| ecart=U sources=${sources} declarees=0"
exit 2
fi
# L'ecart en millisecondes, en valeur absolue.
ecart=$(chronyc tracking 2>/dev/null \
| awk '/^Last offset/ {o=$4+0; if (o<0) o=-o; printf "%.0f", o*1000}')
# `$4+0` FORCE LE NUMERIQUE. `chronyc` prefixe la valeur d'un `+` ou d'un `-` ; sans la
# conversion, awk compare une CHAINE a zero et la valeur absolue ne mord pas. Le symptome
# etait discret — `ecart=-0ms` en perfdata — et c'est precisement ce qu'un grapheur avale
# sans rien dire.
ecart=${ecart:-0}
declarees=0
for s in ${ATTENDUS}; do
[[ "${retenue}" == "${s}" ]] && declarees=1
done
if [[ -n "${ATTENDUS}" && "${declarees}" -eq 0 ]]; then
echo "L'heure vient de ${retenue}, qui n'est PAS la source declaree (${ATTENDUS}) :" \
"la machine est sortie de l'ecosysteme pour se synchroniser." \
"| ecart=${ecart}ms;${ECART_MAX} sources=${sources} declarees=0"
exit 2
fi
if (( ecart > ECART_MAX )); then
echo "Synchronisee sur ${retenue}, mais l'ecart atteint ${ecart} ms" \
"(seuil ${ECART_MAX} ms) : les certificats a duree courte vont souffrir." \
"| ecart=${ecart}ms;${ECART_MAX} sources=${sources} declarees=1"
exit 1
fi
echo "Horloge disciplinee par ${retenue}, ecart ${ecart} ms." \
"| ecart=${ecart}ms;${ECART_MAX} sources=${sources} declarees=1"
exit 0