Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ Lists listener protocol, port, and bind scope (`loopback`, `specific-address`, o

### `update-posture.sh`

Counts updates visible in existing APT or DNF metadata and checks the reboot-required marker. It never refreshes metadata, lists package names, installs updates, or reboots.
Counts updates visible in existing APT or DNF metadata, reports deferred/kept-back APT candidates as a privacy-safe aggregate, and checks the reboot-required marker. It never refreshes metadata, lists package names, installs updates, or reboots.

```bash
./scripts/update-posture.sh
Expand Down
2 changes: 1 addition & 1 deletion SHA256SUMS
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ cf4606e3cd496dd9d8ca9db1281488507e3abeb2f45f460f1af070297a3fec22 scripts/exim-q
859fcefc6b631f9b63e28db8c2f58372e55adfe567e70c3d2317e609b5543d59 scripts/memory-pressure.sh
c35c04f1f5f54eb945b46cbd6ebecb05146f02baf8f7de5bbe967c494ec5bb56 scripts/service-health.sh
a12029e59604066a57edf0bd12668a34031779d59838957d7991973580ea8c2f scripts/listener-exposure.sh
7e04e99afcaad2d704e69f5efc5e4b1866804f451cf90e730f83419b42ff1da9 scripts/update-posture.sh
2bcf1ab868d6055c61b507407b424cd753894bc8d0b190e06c9a156281dbeb59 scripts/update-posture.sh
fe3e47781e5694ebcc2c260df97bb3421fa5e13fa353c0e25e00c9ecffaf2a8b scripts/backup-freshness.sh
46d3961f9364b9ccf7cda154dcef52810855aaf6040ac08a416d641b014e84fb scripts/endpoint-health.sh
ea624496235f3d78cd38be3173f6bb18d898d7cc25b71fe36d678459691b61f0 scripts/tls-expiry.sh
Expand Down
20 changes: 17 additions & 3 deletions scripts/update-posture.sh
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ fi
manager='none'
updates_total=0
updates_security=0
updates_deferred=0
APT_GET_BIN="${APT_GET_BIN:-$(command -v apt-get 2>/dev/null || true)}"
DNF_BIN="${DNF_BIN:-$(command -v dnf 2>/dev/null || true)}"
if [[ -n "$APT_GET_BIN" && -x "$APT_GET_BIN" ]]; then
Expand All @@ -41,7 +42,20 @@ if [[ -n "$APT_GET_BIN" && -x "$APT_GET_BIN" ]]; then
printf 'ERROR: apt update simulation failed\n' >&2
exit 1
fi
updates_total="$(awk '/^Inst /{count++} END{print count+0}' <<<"$raw")"
installable_count="$(awk '/^Inst /{count++} END{print count+0}' <<<"$raw")"
updates_deferred="$(awk '
{
for (i = 2; i < NF; i++) {
if ($i == "not" && $(i + 1) ~ /^upgraded[.]?$/ && $(i - 1) ~ /^[0-9]+$/) {
print $(i - 1)
found = 1
exit
}
}
}
END { if (!found) print 0 }
' <<<"$raw")"
updates_total=$((installable_count + updates_deferred))
updates_security="$(awk 'BEGIN{IGNORECASE=1} /^Inst / && /security/{count++} END{print count+0}' <<<"$raw")"
elif [[ -n "$DNF_BIN" && -x "$DNF_BIN" ]]; then
manager='dnf'
Expand Down Expand Up @@ -73,5 +87,5 @@ if ((updates_total > 0 || updates_security > 0)) || [[ "$reboot_required" == 'ye
status='warning'
fi

printf 'status=%s\nmanager=%s\nupdates_total=%d\nupdates_security=%d\nreboot_required=%s\n' \
"$status" "$manager" "$updates_total" "$updates_security" "$reboot_required"
printf 'status=%s\nmanager=%s\nupdates_total=%d\nupdates_security=%d\nupdates_deferred=%d\nreboot_required=%s\n' \
"$status" "$manager" "$updates_total" "$updates_security" "$updates_deferred" "$reboot_required"
20 changes: 20 additions & 0 deletions tests/test-linux-modules.sh
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,26 @@ assert_contains "update posture reports reboot marker" "$update_output" 'reboot_
assert_contains "update posture reports warning state" "$update_output" 'status=warning'
assert_not_contains "update posture omits package names" "$update_output" 'openssl'

cat >"$TMP/update bin/apt-get-deferred" <<'EOF'
#!/usr/bin/env bash
[[ "$*" == '-s upgrade' ]] || exit 2
printf '%s\n' \
'The following packages have been kept back:' \
' linux-generic openssl' \
'0 upgraded, 0 newly installed, 0 to remove and 2 not upgraded.'
EOF
chmod 700 "$TMP/update bin/apt-get-deferred"
if deferred_update_output="$(APT_GET_BIN="$TMP/update bin/apt-get-deferred" REBOOT_REQUIRED_FILE="$TMP/no-reboot" "$ROOT/scripts/update-posture.sh" 2>&1)"; then
deferred_update_status=0
else
deferred_update_status=$?
fi
assert_eq "update posture collects deferred APT updates" "0" "$deferred_update_status"
assert_contains "update posture counts deferred APT updates in total" "$deferred_update_output" 'updates_total=2'
assert_contains "update posture reports deferred APT count" "$deferred_update_output" 'updates_deferred=2'
assert_contains "update posture warns for deferred APT updates" "$deferred_update_output" 'status=warning'
assert_not_contains "update posture omits deferred APT package names" "$deferred_update_output" 'linux-generic'

cat >"$TMP/update bin/dnf" <<'EOF'
#!/usr/bin/env bash
case "$*" in
Expand Down
Loading