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:
@@ -1,7 +1,9 @@
|
||||
# Secure NTP design — CA-authenticated time via NTS (F-03 / P-18)
|
||||
|
||||
> Status: **implemented (host + serving scaffold), BENCH-VERIFY.** Branch
|
||||
> `secure-ntp`. Closes SAR finding **F-03** / POA&M **P-18**.
|
||||
> Status: **NTS proven end-to-end on the metal (2026-07-11, comet-beacon-54:
|
||||
> `chronyc authdata` → NTS, Cook 8), pending a clean-build re-verify of the
|
||||
> dispatcher-collision fix.** Branch `secure-ntp`. Closes SAR finding **F-03** /
|
||||
> POA&M **P-18**. See "Bench findings" below.
|
||||
|
||||
## Problem
|
||||
|
||||
@@ -120,6 +122,35 @@ and is the standard chrony guidance for RTC-less devices.
|
||||
7. STIG: confirm remediation doesn't strip `ntstrustedcerts`/`nocerttimecheck` or
|
||||
the `nts` option in the sourcedir (host is a client; STIG-compatible).
|
||||
|
||||
## Bench findings
|
||||
|
||||
**2026-07-11 (comet-beacon-54, `secure-ntp-d1621e9`) — the chrony package's own NM
|
||||
dispatcher clobbered the NTS source (FIXED).** On the first clean-build deploy NTS
|
||||
was inactive: `chronyc -N authdata` showed the source as a plain IP (`192.168.50.10`)
|
||||
in Mode `-`, Cook 0, and the journal showed **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. Because `20-` sorts 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 — silently defeating authenticated time (last writer
|
||||
wins on a shared filename).
|
||||
|
||||
Proof + isolation: removing the distro script and hand-writing the NTS source
|
||||
(`printf 'server ntp.fleet.lab iburst nts\n' > …`) + `chronyc reload sources`
|
||||
immediately brought NTS up — `ntp.fleet.lab NTS … Cook 8`, zero NAKs — confirming
|
||||
the host image, the fleet-signed NTS-KE cert, DNS (`ntp.fleet.lab`→serving host),
|
||||
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 time (our dispatcher supersedes it in both modes); `20-chrony-onoffline`
|
||||
is left in place (harmless — it only marks sources online/offline). **BENCH-VERIFY
|
||||
on the next clean build:** with the distro script gone, a normal boot leaves
|
||||
`/run/chrony-dhcp/<iface>.sources` = the NTS line and `chronyc authdata` reaches
|
||||
`NTS`/cookies > 0 with no manual intervention.
|
||||
|
||||
## Toggle
|
||||
|
||||
`secure_ntp=false` reverts the dispatcher to the legacy unauthenticated DHCP
|
||||
|
||||
Reference in New Issue
Block a user