Let the audit emit its state, for a watcher that keeps the baseline elsewhere
`drift` compares against a baseline kept on this machine, and root here can rewrite that as easily as read it - which is the case being looked for. The program says so, and says the half that fixes it runs elsewhere. This is the interface that half needs: `drift --state` prints the collected state and compares nothing, so a watcher on another machine can keep the baseline and do the diff where the devbox cannot reach it. To stdout unconditionally, terminal or not, because this is data rather than a verdict. The partial-state refusal survives the emitter, and that is the point of one of the tests: a watcher diffing a partial state against a full baseline sees a list of removals and calls it an intruder deleting things. Exit 2 there, as everywhere else in this program, means could-not-determine. `bats test/` 161 passing, 3 new.
This commit is contained in:
+21
-3
@@ -675,9 +675,12 @@ drift_dpkg() {
|
||||
}
|
||||
|
||||
cmd_drift() {
|
||||
local accept=0 missing state work added removed rc=0 verdict unread
|
||||
local accept=0 emit=0 missing state work added removed rc=0 verdict unread
|
||||
|
||||
[ "${1:-}" = --accept ] && accept=1
|
||||
case "${1:-}" in
|
||||
--accept) accept=1 ;;
|
||||
--state) emit=1 ;;
|
||||
esac
|
||||
|
||||
missing=$(drift_missing)
|
||||
work=$(mktemp -d) || return 2
|
||||
@@ -700,6 +703,21 @@ cmd_drift() {
|
||||
return 2
|
||||
fi
|
||||
|
||||
# --state prints the state and compares nothing.
|
||||
#
|
||||
# It exists for a watcher on another machine, which keeps the baseline and
|
||||
# does the diff itself. That is the half this program cannot do: root here
|
||||
# can rewrite a baseline kept here, and root here is the case being looked
|
||||
# for. What it cannot do is alter what another machine recorded last week.
|
||||
#
|
||||
# To stdout unconditionally, terminal or not, because this is data rather
|
||||
# than a verdict. A caller asked for it.
|
||||
if [ "$emit" = 1 ]; then
|
||||
cat "$state"
|
||||
rm -rf "$work"
|
||||
return 0
|
||||
fi
|
||||
|
||||
if [ "$accept" = 1 ]; then
|
||||
install -m 0755 -d "$BASELINE_DIR"
|
||||
{
|
||||
@@ -824,7 +842,7 @@ main() {
|
||||
cmd_drift || rc=$?
|
||||
cmd_reach || rc=$?
|
||||
return $rc ;;
|
||||
*) say "usage: $PROG [reach|radius|drift [--accept]]"; return 64 ;;
|
||||
*) say "usage: $PROG [reach|radius|drift [--accept|--state]]"; return 64 ;;
|
||||
esac
|
||||
}
|
||||
|
||||
|
||||
@@ -176,6 +176,37 @@ stub_state() {
|
||||
[ -s "$DRIFT_ERRS" ]
|
||||
}
|
||||
|
||||
# --- the state emitter, which is what a watcher on another machine reads -----
|
||||
|
||||
@test "--state prints the state and compares nothing" {
|
||||
# No baseline needed and none consulted: the watcher keeps that, because a
|
||||
# baseline kept here is one root here can rewrite, and root here is the
|
||||
# case being looked for.
|
||||
stub_state "FILE aaa /etc/one" "UNIT foo.service"
|
||||
run cmd_drift --state
|
||||
[ "$status" -eq 0 ]
|
||||
[[ "$output" == *"FILE aaa /etc/one"* ]]
|
||||
[[ "$output" == *"UNIT foo.service"* ]]
|
||||
[[ "$output" != *CLEAN* ]]
|
||||
[[ "$output" != *INDETERMINATE* ]]
|
||||
}
|
||||
|
||||
@test "--state still refuses when the state would be partial" {
|
||||
# A watcher diffing a partial state against a full baseline sees a list of
|
||||
# removals and calls it an intruder. The refusal has to survive the emitter.
|
||||
stub_state "FILE aaa /etc/one"
|
||||
drift_state() { printf 'FILE aaa /etc/one\n'; echo "denied" >> "$DRIFT_ERRS"; }
|
||||
run cmd_drift --state
|
||||
[ "$status" -eq 2 ]
|
||||
[[ "$output" == *INDETERMINATE* ]]
|
||||
}
|
||||
|
||||
@test "--state does not write a baseline" {
|
||||
stub_state "FILE aaa /etc/one"
|
||||
run cmd_drift --state
|
||||
[ ! -e "$BASELINE" ]
|
||||
}
|
||||
|
||||
# --- exit status ------------------------------------------------------------
|
||||
|
||||
@test "all does not lose a drift finding behind a clean reach" {
|
||||
|
||||
Reference in New Issue
Block a user