Files
intrusion-detection/deploy/check_runtime_git.sh
T
zwitschi 5d81f617f0 feat(deploy): conflict-free 'git pull' update flow (D001/D004/D005)
- deploy.sh: clean-tree guard + git fetch && git pull --ff-only + optional
  dep reinstall + app.db --migrate + restart.
- restart-service.sh: supervisor-agnostic restart (systemd or fallback), waits
  for an in-flight scan.
- check_runtime_git.sh: proves no scan writes git-tracked runtime data.
- ids.service: systemd unit template.
- tests/test_deployment.py: stdlib unittest invariant tests for the deployment
  runtime-isolation guarantee.
2026-10-24 19:50:45 +02:00

67 lines
2.4 KiB
Bash

#!/usr/bin/env bash
#
# D001 — runtime write-path guard.
#
# Proves the deployment invariant: after running a scan, `git status` shows
# NO tracked file modified by the scan — every runtime write lands in a
# gitignored location (data/, reports/, *.db). This is what makes `git pull`
# conflict-free on a server where scans keep running.
#
# If this fails, a scan wrote into a git-tracked path and `git pull` on the
# server can conflict. Investigate the printed files before deploying.
#
# Usage:
# deploy/check_runtime_git.sh [--live]
# --live additionally run a real scan first (requires log sources) and
# then assert the tree is still clean. Without --live it only
# verifies that whatever runtime files already exist are untracked.
set -euo pipefail
cd "$(dirname "$0")/.."
if [[ "${1:-}" == "--live" ]]; then
echo "== Running a real scan to exercise every write path =="
python app.py scan --quiet --dry-run || true
fi
echo "== Checking that runtime data is gitignored / untracked =="
# Paths a scan writes to. Any of these being tracked OR showing as (non-ignored)
# untracked means the invariant is broken and a git pull could conflict.
RUNTIME_PATHS=(
"app/data"
"app/reports"
"app/data/ids.db"
"app/data/ids.db-wal"
"app/data/ids.db-shm"
)
fail=0
# 1) No runtime path may be TRACKED, except the single allowed read-only
# PaloAlto seed. `git ls-files` reflects the index (including staged
# changes), so unborn commits don't cause false failures.
allowed="app/data/paloalto/scanner-ips.txt"
tracked=$(git ls-files app/data app/reports)
problem=$(printf '%s\n' "$tracked" | grep -v '^'"/\$allowed"'$' || true)
if [[ -n "$problem" ]]; then
echo "FAIL: unexpected tracked files under runtime dirs:" >&2
echo "$problem" >&2
fail=1
fi
# 2) Nothing may show as untracked-but-not-ignored under the runtime dirs, i.e.
# a scan wrote a file git would happily add (and later conflict on).
for p in "${RUNTIME_PATHS[@]}"; do
dirty=$(git status --porcelain --untracked-files=all -- "$p" 2>/dev/null || true)
if [[ -n "$dirty" ]]; then
echo "FAIL: runtime path has changes git cares about:" >&2
echo "$dirty" >&2
fail=1
fi
done
if [[ "$fail" -eq 0 ]]; then
echo "OK: no tracked runtime data; git pull will not conflict with scan writes."
else
echo "BROKEN: a scan wrote into git-tracked paths — fix before deploying." >&2
exit 1
fi