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:
@@ -39,9 +39,15 @@ file="$dir/${interface}.sources"
|
||||
mkdir -p "$dir"
|
||||
|
||||
if [ "$MODE" = nts ]; then
|
||||
# Prefer option 15 (domain-name); fall back to the first option-119 search domain.
|
||||
# Prefer option 15 (domain-name); fall back to the first option-119 search
|
||||
# domain; finally fall back to resolv.conf's search/domain. NM does not export
|
||||
# $DHCP4_DOMAIN_NAME on every dispatcher event — at boot the source wasn't
|
||||
# written because the firing event carried no DHCP domain in env, yet
|
||||
# resolv.conf already had `search <domain>` (bench 2026-07-11). Reading it here
|
||||
# makes the NTS source get written reliably regardless of which event fires.
|
||||
domain="${DHCP4_DOMAIN_NAME:-}"
|
||||
[ -z "$domain" ] && domain="${DHCP4_DOMAIN_SEARCH%% *}"
|
||||
[ -z "$domain" ] && domain=$(awk '/^(search|domain)[[:space:]]/{print $2; exit}' /etc/resolv.conf 2>/dev/null)
|
||||
if [ -n "$domain" ]; then
|
||||
printf 'server %s.%s iburst nts\n' "$PREFIX" "$domain" > "$file"
|
||||
# Pick up the new source without restarting chronyd.
|
||||
|
||||
@@ -173,5 +173,20 @@
|
||||
<xccdf:select idref="xccdf_org.ssgproject.content_rule_disable_ctrlaltdel_reboot" selected="false"/>
|
||||
<xccdf:select idref="xccdf_org.ssgproject.content_rule_disable_ctrlaltdel_burstaction" selected="false"/>
|
||||
|
||||
<!-- NTP time source (secure_ntp): the fleet configures chrony's time source
|
||||
DYNAMICALLY at runtime — a fleet-CA-authenticated NTS server derived from
|
||||
the DHCP domain (secure_ntp=true) or DHCP option-42 (false) — via the NM
|
||||
dispatcher + `sourcedir /run/chrony-dhcp`, NOT a static baked `server`
|
||||
line. These rules remediate by INJECTING an unauthenticated
|
||||
`server <pool> maxpoll 16` into chrony.conf; under secure_ntp that plain
|
||||
server is a silent fallback that DEFEATS the NTS DoS-only guarantee (a
|
||||
DNS/NTP spoofer could shift the clock through it — the exact F-03 risk).
|
||||
Unselect so remediation adds no plain server; 2c-STIG-postfix also
|
||||
re-strips any server/pool when secure_ntp=true (belt-and-suspenders).
|
||||
The STIG intent (time IS synchronised, authenticated under NTS) is met.
|
||||
Justified in docs/stig-deviations.md #17. -->
|
||||
<xccdf:select idref="xccdf_org.ssgproject.content_rule_chronyd_specify_remote_server" selected="false"/>
|
||||
<xccdf:select idref="xccdf_org.ssgproject.content_rule_chronyd_or_ntpd_set_maxpoll" selected="false"/>
|
||||
|
||||
</xccdf:Profile>
|
||||
</xccdf:Tailoring>
|
||||
|
||||
Reference in New Issue
Block a user