aboutsummaryrefslogtreecommitdiff
path: root/scripts/post-rebuild-check
diff options
context:
space:
mode:
authorCraig Jennings <c@cjennings.net>2026-08-19 12:32:02 -0700
committerCraig Jennings <c@cjennings.net>2026-08-19 12:32:02 -0700
commitec3a63caca4f2d955e594318a9a690e4c28af19e (patch)
tree4ad5a438b38f92d49dbbcd2dd22e950831535f37 /scripts/post-rebuild-check
parentafbf011aa0937b5702b6d8c1bfca0809ed809425 (diff)
downloadarchsetup-ec3a63caca4f2d955e594318a9a690e4c28af19e.tar.gz
archsetup-ec3a63caca4f2d955e594318a9a690e4c28af19e.zip
fix(check): read NTP sources only from files chrony is told to read
Check 6 globbed /etc/chrony.d unconditionally. A drop-in is inert unless chrony.conf names its directory, and Arch's stock chrony.conf names none, so a machine with the IP-addressed source on disk and no confdir line would show the literal and pass. That is a false pass on exactly the misconfiguration the check exists to catch, and it describes a file chrony never opens. Sources now come only from chrony.conf plus whatever confdir or sourcedir it actually names. The config path is a seam so the confdir logic can be tested against a fixture instead of the real /etc. This should have been in the previous commit, whose message already describes it. I staged before reviewing, fixed the finding, then committed the stale index.
Diffstat (limited to 'scripts/post-rebuild-check')
-rwxr-xr-xscripts/post-rebuild-check25
1 files changed, 22 insertions, 3 deletions
diff --git a/scripts/post-rebuild-check b/scripts/post-rebuild-check
index c18ae8f..24e99a4 100755
--- a/scripts/post-rebuild-check
+++ b/scripts/post-rebuild-check
@@ -56,6 +56,8 @@
# the special value MISSING = binary absent
# PRC_NTP_SOURCES newline list of configured NTP server addresses;
# the special value MISSING = no NTP daemon active
+# PRC_CHRONY_CONF path to chrony.conf (a fixture, under test) -- the
+# confdir it names is what decides which drop-ins count
# PRC_SYSTEMCTL path to the systemctl binary (a fake, under test)
# PRC_SYSTEMCTL_TIMEOUT seconds to allow each systemctl call (default 5)
#
@@ -101,6 +103,7 @@ ntp_missing=""
# own outage, and the machine most in need of checking is the one it hangs on.
# A timeout yields empty output and a non-zero status, and both are already
# handled as findings, so bounding the call is all that is needed to fail closed.
+CHRONY_CONF=${PRC_CHRONY_CONF:-/etc/chrony.conf}
SCTL_TIMEOUT=${PRC_SYSTEMCTL_TIMEOUT:-5}
SYSTEMCTL=${PRC_SYSTEMCTL:-systemctl}
@@ -435,9 +438,25 @@ if [ -n "${PRC_NTP_SOURCES+set}" ]; then
ntp_missing=1
fi
elif sctl is-active chronyd >/dev/null 2>&1; then
- # Both the main file and any drop-in: the IP-addressed source belongs in a
- # drop-in, so reading only chrony.conf would miss every correct machine.
- ntp_sources=$(cat /etc/chrony.conf /etc/chrony.d/*.conf 2>/dev/null \
+ # The main file, plus any drop-in directory chrony.conf actually names.
+ #
+ # The confdir read is the load-bearing part. A drop-in is inert unless
+ # chrony.conf points at its directory, and Arch's stock chrony.conf points
+ # at none -- so globbing /etc/chrony.d unconditionally would find the
+ # IP-addressed source, report the machine healthy, and be describing a file
+ # chrony never opens. That is a false pass on exactly the misconfiguration
+ # this check exists to catch, so the sources are read only from files
+ # chrony is actually told to read.
+ ntp_conf_files=$CHRONY_CONF
+ for ntp_dir in $(awk '$1 == "confdir" || $1 == "sourcedir" { print $2 }' \
+ "$CHRONY_CONF" 2>/dev/null); do
+ for ntp_f in "$ntp_dir"/*.conf "$ntp_dir"/*.sources; do
+ [ -f "$ntp_f" ] && ntp_conf_files="$ntp_conf_files $ntp_f"
+ done
+ done
+ # Unquoted on purpose: the accumulated list is several paths, and none of
+ # this script's own paths contain spaces.
+ ntp_sources=$(cat $ntp_conf_files 2>/dev/null \
| awk '$1 == "server" || $1 == "pool" { print $2 }')
elif sctl is-active systemd-timesyncd >/dev/null 2>&1; then
ntp_sources=$(awk -F= '/^[[:space:]]*NTP=/ { print $2 }' \