feat(P10b): drift detection (R-018/R-019/R-020, REQ-103..113)
internal/drift/drift.go: Detector (Watch via iter.Seq2, Aggregate,
Remediate with cooldown-on-success, Acknowledge), Config with tiered
cadence (critical 5s + Path units, standard 30s, default 60s).
internal/cli/drift.go: orca drift {show,watch,acknowledge,remediate,
config}. internal/emitter/drift_path.go: systemd Path+service unit
emitter (User=orca, ProtectSystem=strict). scripts/orca-drift-notify.sh
(sha256 event JSON), orca-remediate.sh (cooldown-on-success, transient
retry). Pre-flight gate (R-020, --force + per-ns scoping). orca
system user (REQ-111), NFS detection (D-233), orca job restart for
EnvironmentFile drift (D-235).
---ci---
project: orca
phase: 10b
milestone: v0.11
status: execute
---/ci---
This commit is contained in:
Executable
+99
@@ -0,0 +1,99 @@
|
||||
#!/usr/bin/env bash
|
||||
# orca-drift-notify.sh — peer-side drift event recorder (P10b, REQ-106).
|
||||
#
|
||||
# Invoked by systemd Path units (orca-drift-<name>.service) when a
|
||||
# critical path changes. Receives the changed path as $1 (from systemd
|
||||
# %f). Computes sha256sum of the file (or "DELETED" if absent), reads
|
||||
# the latest applied txn from /etc/orca/state/latest-applied-txn, and
|
||||
# writes an event JSON to /etc/orca/state/drift-events/<event-id>.json.
|
||||
# Uses flock for serialization. R-001-clean: pure bash + sha256sum.
|
||||
#
|
||||
# Usage: orca-drift-notify.sh <path>
|
||||
#
|
||||
# Exit codes: 0 = event recorded; 1 = bad args / write failure.
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
# shellcheck source=lib/orca-log.sh
|
||||
. "$SCRIPT_DIR/lib/orca-log.sh"
|
||||
|
||||
ORCA_LOG_ACTOR="spiffe://orca/cli/drift-notify"
|
||||
|
||||
STATE_DIR="${ORCA_STATE_DIR:-/etc/orca/state}"
|
||||
EVENTS_DIR="$STATE_DIR/drift-events"
|
||||
LATEST_TXN_FILE="$STATE_DIR/latest-applied-txn"
|
||||
LOCK_FILE="$STATE_DIR/drift-events.lock"
|
||||
|
||||
if [ "$#" -lt 1 ]; then
|
||||
orca_log_error "drift-notify" "-" "failed" "missing path argument"
|
||||
echo "usage: orca-drift-notify.sh <path>" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
PATH_ARG="$1"
|
||||
|
||||
mkdir -p "$EVENTS_DIR"
|
||||
|
||||
compute_sha() {
|
||||
local p="$1"
|
||||
if [ ! -e "$p" ]; then
|
||||
echo "DELETED"
|
||||
return
|
||||
fi
|
||||
sha256sum "$p" 2>/dev/null | awk '{print $1}' || echo "ERROR"
|
||||
}
|
||||
|
||||
read_latest_txn() {
|
||||
if [ -f "$LATEST_TXN_FILE" ]; then
|
||||
cat "$LATEST_TXN_FILE" 2>/dev/null || true
|
||||
fi
|
||||
}
|
||||
|
||||
gen_event_id() {
|
||||
local ts_us random_suffix
|
||||
ts_us="$(date -u +%Y%m%d%H%M%S%6N)"
|
||||
random_suffix="$(head -c 4 /dev/urandom 2>/dev/null | od -An -tx1 | tr -d ' \n' || echo "0000")"
|
||||
echo "EVT-${ts_us}-${random_suffix}"
|
||||
}
|
||||
|
||||
NEW_SHA="$(compute_sha "$PATH_ARG")"
|
||||
LATEST_TXN="$(read_latest_txn || true)"
|
||||
EVENT_ID="$(gen_event_id)"
|
||||
TS="$(date -u +%Y-%m-%dT%H:%M:%S.%3NZ)"
|
||||
HOST="$(hostname 2>/dev/null || echo unknown)"
|
||||
|
||||
if [ "$NEW_SHA" = "DELETED" ]; then
|
||||
STATUS="deleted"
|
||||
elif [ ! -f "$PATH_ARG" ]; then
|
||||
STATUS="created"
|
||||
else
|
||||
STATUS="modified"
|
||||
fi
|
||||
|
||||
escape_json() {
|
||||
local s="$1"
|
||||
s="${s//\\/\\\\}"
|
||||
s="${s//\"/\\\"}"
|
||||
printf '%s' "$s"
|
||||
}
|
||||
|
||||
PATH_ESC="$(escape_json "$PATH_ARG")"
|
||||
HOST_ESC="$(escape_json "$HOST")"
|
||||
|
||||
EVENT_JSON=$(cat <<JSON
|
||||
{"event_id":"$EVENT_ID","ts":"$TS","host":"$HOST_ESC","path":"$PATH_ESC","status":"$STATUS","new_sha256":"$NEW_SHA","latest_txn":"$LATEST_TXN","drift_confirmed":false,"action":"reported","action_result":"skipped"}
|
||||
JSON
|
||||
)
|
||||
|
||||
EVENT_FILE="$EVENTS_DIR/${EVENT_ID}.json"
|
||||
|
||||
(
|
||||
flock 9 || { orca_log_error "drift-notify" "$PATH_ARG" "failed" "flock"; exit 1; }
|
||||
printf '%s\n' "$EVENT_JSON" >"$EVENT_FILE.tmp"
|
||||
mv "$EVENT_FILE.tmp" "$EVENT_FILE"
|
||||
) 9>"$LOCK_FILE"
|
||||
|
||||
orca_log_info "drift-notify" "$PATH_ARG" "ok" "event=$EVENT_ID status=$STATUS sha=$NEW_SHA"
|
||||
echo "event=$EVENT_ID"
|
||||
exit 0
|
||||
Reference in New Issue
Block a user