secure-ntp: fix NTS defects surfaced by the F-03 bench

NTS proven end-to-end on comet-beacon-54 (chronyc authdata cookies > 0); these
close the gaps the bench found so a clean build/serving run reaches that state
without manual patching:

- dispatcher (10-chrony-dhcp-ntp): fall back to resolv.conf search/domain when NM
  doesn't export DHCP4_DOMAIN_NAME on the firing event, so the NTS source is
  written reliably at boot (tonight it needed a manual dispatcher run).
- STIG vs secure_ntp (P2, security): STIG's chronyd_specify_remote_server re-injects
  an UNAUTHENTICATED 'server 0.us.pool.ntp.mil maxpoll 16' AFTER the secure_ntp
  chrony step commented servers out -> a silent fallback that defeats NTS's
  DoS-only guarantee (host not fail-closed). Unselect chronyd_specify_remote_server
  + chronyd_or_ntpd_set_maxpoll in diskless-tailoring.xml, and re-strip any
  server/pool in 2c-STIG-postfix when secure_ntp=true. Documented: stig-deviations #17.
- nts-cert.sh (P3): the container's chrony user (non-root) can't read a 0640
  host-owned key -> NTS-KE TLS aborts ('non-properly terminated'). chown the key to
  the ntp container's chrony uid + keep 0640 (0644 works but chrony warns
  world-readable); 0644 fallback if the uid can't be found.

Bench-verified 2026-07-11; docs updated in docs/ssh-host-certificate-design.md's
sibling secure-ntp-design.md flow. F-03/P-18 stays open until a clean build shows
chrony.conf has no plain server and authdata cookies>0 as the only source.
This commit is contained in:
Audiobuzz
2026-07-11 11:21:46 +00:00
parent aab6c9919c
commit f9f7c7c940
5 changed files with 89 additions and 2 deletions
+36
View File
@@ -293,6 +293,42 @@ boot; (b) no other chrony-log AVC (extend here if one appears); (c)
**reproducibility** — `semodule -i` rebuilds the policy store, re-check verity hash
stability (same concern as #14/#15). Only shipped when `enable_stig=true`.
## 17. STIG NTP-server rules unselected under `secure_ntp` (added 2026-07-11)
**Rules waived:** `chronyd_specify_remote_server`, `chronyd_or_ntpd_set_maxpoll`
(unselected in `diskless-tailoring.xml`; plus a belt-and-suspenders re-strip in
`2c-STIG-postfix`).
**Why:** these rules remediate by writing a **static, unauthenticated**
`server <pool> maxpoll 16` into `/etc/chrony.conf`. The fleet instead configures
chrony's time source **dynamically at runtime** — a **fleet-CA-authenticated NTS**
server derived from the DHCP domain (`secure_ntp=true`, RFC 8915) or DHCP option-42
(`false`) — via the NM dispatcher writing `sourcedir /run/chrony-dhcp`, with
`ntstrustedcerts`/`nocerttimecheck` baked. The STIG *intent* (time is synchronised,
and under NTS **authenticated**) is fully met; the rules only fail because they
look for a literal baked `server` line the fleet deliberately doesn't have.
**The security reason this is not just cosmetic (F-03/P-18):** the ordering is the
trap — `2c-STIG` runs **after** the `secure_ntp` chrony step, so an un-waived
`chronyd_specify_remote_server` **re-injects** a plain `server 0.us.pool.ntp.mil
maxpoll 16` that the earlier step already commented out. That plain server is a
**silent unauthenticated fallback**: with it present, chrony will happily sync
non-NTS time, so a DHCP/DNS/NTP spoofer could shift the clock — defeating the whole
point of NTS. Leaving it in means the host is **not fail-closed**. Observed on
`comet-beacon-54` 2026-07-11: NTS working (`chronyc authdata` cookies > 0) *and* the
STIG `0.us.pool.ntp.mil` line still in `chrony.conf` and syncing in parallel.
**Fix:** unselect the two rules (so remediation injects nothing) **and**, when
`secure_ntp=true`, re-comment any `server`/`pool` in `2c-STIG-postfix` (in case a
future rule adds one) so **only** the NTS `sourcedir` + `ntstrustedcerts` remain.
Under `secure_ntp=false` the re-strip does not run (the DHCP option-42 dispatcher
path needs the handed servers).
**BENCH-VERIFY:** on a clean secure_ntp build, `grep -E '^(server|pool)'
/etc/chrony.conf` returns nothing (only `sourcedir`/`ntstrustedcerts`), and
`chronyc -N authdata` shows the NTS source with cookies > 0 as the **only** selected
source (no `0.us.pool.ntp.mil` fallback). Only applies when `enable_stig=true`.
## Things that are NOT deviations (kept / enforced)
- **SELinux enforcing** (`selinux --enforcing`; labels preserved into the erofs).