Skip to content

Commit f851828

Browse files
fix(release): pre-release sweep, 9 findings from long-committed scripts
HIGH: demo.sh banner + generate_demo_guide.py both said v2.0; app is v1.0.0-rc1. Reworded version-neutral; Demo_Guide.pdf regenerated. MEDIUM: backup_data.sh excludes were incomplete (top-level _*.json runtime files, *.lock, .approval_queue.sig, .csv_expected_hashes.json, .fim_*.json, .presence.json all leaked into archive). Restoring on a different host would fail HMAC verification. Exclude list expanded. Inventory step counted only DR*.csv prefix; widened to count every customer whitelist. MEDIUM: test_backup_restore.sh only compared DR*-prefixed files (PASS despite 14-file archives). Now mirrors backup_data.sh exclude set so the smoke verifies full archive contents. MEDIUM: test_integration.sh save_csv test was stale (no expected_content_hash; mandatory since hardening round 6). Verified live: 11/11 PASS post-fix. MEDIUM: test_upgrade_path.sh removed entirely (targeted v2.0 to v3.0, neither valid; would have destroyed wl_manager_test container). LOW: auto-expire banner verified working at code + audit level (wl_save.js shows banner; auto_removed event fires). No code fix needed.
1 parent 301dcd5 commit f851828

7 files changed

Lines changed: 70 additions & 242 deletions

File tree

demo/Demo_Guide.pdf

0 Bytes
Binary file not shown.

demo/demo.sh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#!/usr/bin/env bash
22
#
33
# ═══════════════════════════════════════════════════════════════════════
4-
# Whitelist Manager v2.0 — Quick Demo
4+
# Whitelist Manager — Quick Demo
55
# ═══════════════════════════════════════════════════════════════════════
66
#
77
# Spins up a standalone Splunk instance in Docker, installs the
@@ -110,7 +110,7 @@ fi
110110

111111
echo ""
112112
echo "═══════════════════════════════════════════════════════════════"
113-
echo " Whitelist Manager v2.0 — Quick Demo"
113+
echo " Whitelist Manager — Quick Demo"
114114
echo "═══════════════════════════════════════════════════════════════"
115115
echo ""
116116

demo/generate_demo_guide.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -287,7 +287,7 @@ def build():
287287
# -- Approval Workflow --
288288
pdf.section("4", "Approval Workflow Demo")
289289
pdf.body(
290-
"One of the key v2.0 features is the approval workflow. "
290+
"Whitelist Manager enforces an approval workflow for high-impact changes. "
291291
"Bulk operations above configurable thresholds require admin approval."
292292
)
293293

scripts/backup_data.sh

Lines changed: 37 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,17 +12,24 @@
1212
# any host other than the original.
1313
#
1414
# What gets backed up:
15-
# - lookups/DR*.csv (active whitelist CSVs)
16-
# - lookups/rule_csv_map.csv (rule↔CSV mapping)
17-
# - lookups/_versions/*.csv (version snapshots)
18-
# - lookups/_versions/*_versions.json (version manifests)
15+
# - lookups/*.csv (every customer whitelist CSV,
16+
# regardless of naming convention)
17+
# - lookups/rule_csv_map.csv (rule↔CSV mapping)
18+
# - lookups/_versions/*.csv (version snapshots)
19+
# - lookups/_versions/*_versions.json (version manifests)
1920
#
2021
# What does NOT get backed up (rebuild on restore):
21-
# - HMAC-signed state (`_action_cooldowns.json`, `wl_cooldowns` KV)
22+
# - Top-level runtime JSON state (_approval_queue.json, _daily_limits.json,
23+
# _notifications.json, _emergency_lockdown.json, _trash_config.json,
24+
# _action_cooldowns.json, _fim_deploy_window.json, _detection_rules.json,
25+
# _limit_config.json) — HMAC-signed and/or transient
26+
# - Atomic-RMW lock artifacts (*.lock)
27+
# - HMAC signatures and host-bound state (.approval_queue.sig,
28+
# .csv_expected_hashes.json, .fim_*.json, .presence.json)
29+
# - HMAC-signed cooldown state (`wl_cooldowns` KV)
2230
# - FIM baselines (`.fim_baseline.json`, `wl_fim_baseline` KV)
23-
# - Hash registry (`.csv_expected_hashes.json`) — re-bootstrap
24-
# - Lockdown / presence / deploy-window files
25-
# - Recovery log (it's append-only; archive separately if needed)
31+
# - Recovery log (`_recovery_log.jsonl` — append-only; archive separately
32+
# if you need its history)
2633
#
2734
# What this script does NOT capture (out of scope):
2835
# - The `wl_audit` Splunk index — back up via Splunk's standard
@@ -67,16 +74,30 @@ fi
6774
mkdir -p "$OUTPUT_DIR"
6875

6976
# ── Step 1: Inventory ─────────────────────────────────────────────────
77+
# Count every customer-meaningful CSV (any name, not just DR*). Exclude
78+
# rule_csv_map.csv from this count so the "Mapping file:" line below
79+
# is unambiguous, and exclude any *.lock files (RMW lock artifacts).
7080
echo "Step 1/4: Inventorying lookups..."
7181
CSV_COUNT=$(MSYS_NO_PATHCONV=1 docker exec -u 0 "$CONTAINER" \
72-
sh -c "ls $APP_PATH/lookups/DR*.csv 2>/dev/null | wc -l" | tr -d '\r')
82+
sh -c "find $APP_PATH/lookups -maxdepth 1 -type f -name '*.csv' ! -name 'rule_csv_map.csv' 2>/dev/null | wc -l" | tr -d '\r')
7383
VERSION_COUNT=$(MSYS_NO_PATHCONV=1 docker exec -u 0 "$CONTAINER" \
7484
sh -c "ls $APP_PATH/lookups/_versions/*.csv 2>/dev/null | wc -l" | tr -d '\r')
7585
echo " CSVs: $CSV_COUNT"
7686
echo " Version snapshots: $VERSION_COUNT"
7787
echo " Mapping file: rule_csv_map.csv"
7888

7989
# ── Step 2: Tar inside the container ─────────────────────────────────
90+
# Excludes cover both runtime state and the HMAC-signed snapshots that
91+
# would fail signature verification when restored on a different host:
92+
# - _versions/_*.json|jsonl — runtime state inside _versions/
93+
# - _*.json|jsonl — top-level runtime state (approval queue,
94+
# daily limits, notifications, etc.)
95+
# - *.lock — atomic-RMW lock artifacts (transient)
96+
# - .approval_queue.sig — HMAC signature, host-bound
97+
# - .csv_expected_hashes.json — HMAC-signed registry, host-bound
98+
# - .fim_*.json — FIM baseline / alert state, host-bound
99+
# - .presence.json — runtime presence cache
100+
# - *.bak — editor backups
80101
echo ""
81102
echo "Step 2/4: Creating archive inside container..."
82103
TMP_INSIDE="/tmp/${BACKUP_NAME}.tar.gz"
@@ -86,6 +107,13 @@ MSYS_NO_PATHCONV=1 docker exec -u 0 "$CONTAINER" \
86107
--exclude='_versions/.*' \
87108
--exclude='_versions/_*.json' \
88109
--exclude='_versions/_*.jsonl' \
110+
--exclude='_*.json' \
111+
--exclude='_*.jsonl' \
112+
--exclude='*.lock' \
113+
--exclude='.approval_queue.sig' \
114+
--exclude='.csv_expected_hashes.json' \
115+
--exclude='.fim_*.json' \
116+
--exclude='.presence.json' \
89117
--exclude='*.bak' \
90118
.
91119

scripts/test_backup_restore.sh

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,10 +62,22 @@ mkdir -p "$TMPDIR_LIVE"
6262
TMPDIR_RESTORE=""
6363
trap 'rm -rf "$TMPDIR_LIVE" "$TMPDIR_RESTORE"' EXIT
6464

65+
# Inventory every customer-meaningful CSV under lookups/, regardless of
66+
# naming convention. Excludes match the backup_data.sh exclude list so
67+
# the comparison only spans files the archive is expected to contain.
6568
LIVE_INVENTORY="$TMPDIR_LIVE/live_inventory.txt"
6669
MSYS_NO_PATHCONV=1 docker exec -u 0 "$CONTAINER" sh -c \
6770
"cd $APP_PATH/lookups && \
68-
find . -type f \\( -name 'DR*.csv' -o -name 'rule_csv_map.csv' \\) | sort" \
71+
find . -type f \
72+
! -name '_*.json' ! -name '_*.jsonl' \
73+
! -name '*.lock' ! -name '*.bak' \
74+
! -name '.approval_queue.sig' \
75+
! -name '.csv_expected_hashes.json' \
76+
! -name '.fim_*.json' \
77+
! -name '.presence.json' \
78+
! -path './_versions/_*.json' ! -path './_versions/_*.jsonl' \
79+
! -path './_versions/.*' \
80+
| sort" \
6981
> "$LIVE_INVENTORY"
7082

7183
LIVE_FILE_COUNT=$(wc -l < "$LIVE_INVENTORY" | tr -d ' ')
@@ -124,7 +136,16 @@ mkdir -p "$TMPDIR_RESTORE"
124136
tar -xzf "$ARCHIVE" -C "$TMPDIR_RESTORE"
125137

126138
RESTORED_INVENTORY="$TMPDIR_LIVE/restored_inventory.txt"
127-
(cd "$TMPDIR_RESTORE" && find . -type f \( -name 'DR*.csv' -o -name 'rule_csv_map.csv' \) | sort) \
139+
(cd "$TMPDIR_RESTORE" && find . -type f \
140+
! -name '_*.json' ! -name '_*.jsonl' \
141+
! -name '*.lock' ! -name '*.bak' \
142+
! -name '.approval_queue.sig' \
143+
! -name '.csv_expected_hashes.json' \
144+
! -name '.fim_*.json' \
145+
! -name '.presence.json' \
146+
! -path './_versions/_*.json' ! -path './_versions/_*.jsonl' \
147+
! -path './_versions/.*' \
148+
| sort) \
128149
> "$RESTORED_INVENTORY"
129150

130151
if ! diff -q "$LIVE_INVENTORY" "$RESTORED_INVENTORY" >/dev/null 2>&1; then

scripts/test_integration.sh

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,12 @@ echo "── REST Endpoint — POST (save + audit) ──"
159159
echo " (Setting up test CSV in container...)"
160160
MSYS_NO_PATHCONV=1 docker exec -u splunk wl_manager_test bash -c 'printf "host,user,CommandLine,Comment\nWKSTN-001,bob,whoami,Legacy entry\nWKSTN-042,alice,net use,Approved\n" > /opt/splunk/etc/apps/wl_manager/lookups/TEST_whitelist.csv' 2>/dev/null || true
161161

162+
# Fetch the current content_hash — save_csv enforces optimistic locking
163+
# (a security control added in hardening round 6). Without expected_content_hash
164+
# the save returns HTTP 409 Conflict.
165+
EXPECTED_HASH=$(splunk_custom GET -d "action=get_csv_content&csv_file=TEST_whitelist.csv" 2>/dev/null \
166+
| python3 -c "import sys,json; print(json.load(sys.stdin).get('content_hash',''))" 2>/dev/null)
167+
162168
run_test "POST save_csv writes CSV and returns diff"
163169
SAVE_BODY=$(splunk_custom POST \
164170
-H "Content-Type: application/json" \
@@ -167,6 +173,7 @@ SAVE_BODY=$(splunk_custom POST \
167173
"csv_file": "TEST_whitelist.csv",
168174
"app_context": "",
169175
"detection_rule": "TEST_rule",
176+
"expected_content_hash": "'"$EXPECTED_HASH"'",
170177
"headers": ["host","user","CommandLine","Comment"],
171178
"rows": [
172179
{"host":"WKSTN-042","user":"alice","CommandLine":"net use","Comment":"Approved"},

scripts/test_upgrade_path.sh

Lines changed: 0 additions & 228 deletions
This file was deleted.

0 commit comments

Comments
 (0)