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:
@@ -46,7 +46,28 @@ incca step ca certificate "${NTP_SAN}" \
|
||||
mkdir -p "$OUT"
|
||||
cp "$PKI/nts/nts.crt" "$OUT/nts.crt"
|
||||
cp "$PKI/nts/nts.key" "$OUT/nts.key"
|
||||
chmod 0644 "$OUT/nts.crt"; chmod 0640 "$OUT/nts.key"
|
||||
chmod 0644 "$OUT/nts.crt"
|
||||
|
||||
# The ntp container's chronyd runs as a non-root 'chrony' user (post-PRIVDROP) —
|
||||
# NOT the host user that wrote this key. So `0640` owned by the host user is
|
||||
# UNREADABLE inside the container ("Missing read access ... : Permission denied" ->
|
||||
# "Could not set credentials"), and every NTS-KE TLS handshake then fails with
|
||||
# "The TLS connection was non-properly terminated" (bench 2026-07-11 on
|
||||
# comet-beacon-54). `0644` works but chrony warns "World-readable permissions". The
|
||||
# right answer: chown the key to the container's chrony uid + keep 0640. The ntp
|
||||
# service is in the PARENT compose project (serving/), so query it from there.
|
||||
chmod 0640 "$OUT/nts.key"
|
||||
NTP_DIR="$(cd .. 2>/dev/null && pwd)"
|
||||
CHRONY_UID="$(cd "$NTP_DIR" 2>/dev/null && docker compose exec -T ntp sh -c 'awk -F: "/chrony/{print \$3; exit}" /etc/passwd' 2>/dev/null | tr -d '\r ' || true)"
|
||||
if [ -n "$CHRONY_UID" ]; then
|
||||
chown "$CHRONY_UID" "$OUT/nts.key" 2>/dev/null || sudo chown "$CHRONY_UID" "$OUT/nts.key"
|
||||
echo " NTS key owned by the ntp container's chrony uid ($CHRONY_UID), mode 0640."
|
||||
else
|
||||
chmod 0644 "$OUT/nts.key"
|
||||
echo " WARNING: couldn't determine the ntp container's chrony uid (is the ntp"
|
||||
echo " service running?). Left the key 0644 (world-readable) so chrony"
|
||||
echo " can read it — chown it to the chrony uid + 0640 for production."
|
||||
fi
|
||||
echo "==> wrote $OUT/nts.crt + $OUT/nts.key"
|
||||
echo " Ensure the image's ntp_server = ${NTP_SAN}, dnsmasq resolves ${NTP_SAN},"
|
||||
echo " open tcp/4460 (NTS-KE) on the boot NIC, and restart the ntp service."
|
||||
|
||||
Reference in New Issue
Block a user