secure-ntp: remove the chrony pkg NM dispatcher that clobbered the NTS source

NTS was inactive on the clean-build deploy (secure-ntp-d1621e9, comet-beacon-54):
chronyc authdata showed a plain IP source in Mode '-', Cook 0, with no NTS-KE
attempt at all -- chrony was on plain NTP.

Root cause: NetworkManager runs dispatcher scripts from BOTH
/etc/NetworkManager/dispatcher.d and /usr/lib/NetworkManager/dispatcher.d, merged
and sorted by filename. The chrony RPM ships
/usr/lib/NetworkManager/dispatcher.d/20-chrony-dhcp, which writes the DHCP
option-42 server to the SAME /run/chrony-dhcp/<iface>.sources file our
10-chrony-dhcp-ntp uses. Sorting after 10-, it ran last and overwrote our
`server ntp.fleet.lab iburst nts` line with `server 192.168.50.10 iburst`, then
reloaded chrony -- last writer wins on the shared filename, silently defeating
authenticated time.

Isolation proof: removing the distro script + hand-writing the NTS source brought
NTS up immediately (ntp.fleet.lab NTS, Cook 8, zero NAKs), confirming the host
image, the fleet-signed NTS-KE cert, DNS, and tcp/4460 were all already correct --
the collision was the sole defect.

Fix: the provisioner removes /usr/lib/NetworkManager/dispatcher.d/20-chrony-dhcp
at build (our dispatcher supersedes it in both modes); 20-chrony-onoffline is left
in place (harmless). Documents the finding in the dispatcher header,
docs/secure-ntp-design.md, and the CLAUDE.md secure_ntp note. BENCH-VERIFY on the
next clean build: a normal boot reaches NTS/cookies>0 with no manual step.
This commit is contained in:
Audiobuzz
2026-07-11 14:02:40 +00:00
parent d1621e9b74
commit 5a3eaedec5
4 changed files with 55 additions and 3 deletions
@@ -22,6 +22,12 @@
#
# Installed 0755 root:root. Lenient on purpose: a hiccup here must never break
# networking. @NTP_MODE@/@NTP_PREFIX@ are substituted at build time.
#
# NB: the chrony package ships its OWN dispatcher at
# /usr/lib/NetworkManager/dispatcher.d/20-chrony-dhcp writing option-42 servers to
# the SAME <iface>.sources. NM merges /etc + /usr/lib sorted by name, so it runs
# AFTER us and would clobber the NTS line — the provisioner removes it (it defeated
# NTS on the bench: chrony fell back to plain NTP). This script supersedes it.
MODE="@NTP_MODE@" # nts | dhcp
PREFIX="@NTP_PREFIX@" # nts: server name = <PREFIX>.<dhcp-domain>