#!/usr/bin/env bash
# tests/creds-audit/run-tests.sh
#
# Harness for scripts/creds-audit.sh. Offline: builds synthetic creds folders +
# manifests under a tmp CREDS_ROOT and asserts the audit's verdict. Touches no real
# secret and no real home dir (CREDS_ROOT / MANIFEST_DIR are redirected to tmp).
set -uo pipefail
HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
REPO="$(cd "$HERE/../.." && pwd)"
AUDIT="$REPO/scripts/creds-audit.sh"
P=0; F=0
ok() { echo "  [PASS] $1"; P=$((P+1)); }
no() { echo "  [FAIL] $1"; F=$((F+1)); }

[ -f "$AUDIT" ] || { echo "FAIL: $AUDIT not found"; exit 1; }

# fresh synthetic environment: CREDS_ROOT/<site>-creds + MANIFEST_DIR/<site>.manifest
SITE=testsite
mkenv() {  # mkenv -> echoes the tmp root; caller sets CREDS_ROOT/MANIFEST_DIR to it
  local root; root="$(mktemp -d)"
  mkdir -p "$root/${SITE}-creds" "$root/manifests"
  chmod 700 "$root/${SITE}-creds"
  printf 'a_secret 600 local\nb_key.pub 644 local\nc.env 600 somevm:/root/x.token\n' \
    > "$root/manifests/${SITE}.manifest"
  printf 'secret\n' > "$root/${SITE}-creds/a_secret"; chmod 600 "$root/${SITE}-creds/a_secret"
  printf 'pub\n'    > "$root/${SITE}-creds/b_key.pub"; chmod 644 "$root/${SITE}-creds/b_key.pub"
  printf 'tok\n'    > "$root/${SITE}-creds/c.env";     chmod 600 "$root/${SITE}-creds/c.env"
  echo "$root"
}
run() { CREDS_ROOT="$1" MANIFEST_DIR="$1/manifests" bash "$AUDIT" "$SITE" >"$1/out" 2>&1; echo $?; }

echo "=== creds-audit ==="

# T1: a complete, correct, non-sprawled folder -> CLEAN, exit 0
R="$(mkenv)"; rc=$(run "$R")
[ "$rc" = 0 ] && grep -q "CLEAN" "$R/out" && ok "T1 complete + correct folder -> CLEAN, exit 0" \
              || { no "T1 a correct folder should pass (rc=$rc)"; sed 's/^/       /' "$R/out"; }
rm -rf "$R"

# T2: a manifest-required file MISSING (the SEC-009 gap: a VM secret never pulled in)
R="$(mkenv)"; rm -f "$R/${SITE}-creds/c.env"; rc=$(run "$R")
[ "$rc" = 1 ] && grep -q "MISSING: c.env" "$R/out" && ok "T2 a manifested (VM-sourced) secret absent -> MISSING, exit 1" \
              || { no "T2 a missing manifest entry should fail (rc=$rc)"; sed 's/^/       /' "$R/out"; }
rm -rf "$R"

# T3: wrong permissions on a secret -> FAIL
R="$(mkenv)"; chmod 644 "$R/${SITE}-creds/a_secret"; rc=$(run "$R")
[ "$rc" = 1 ] && grep -q "a_secret mode 644" "$R/out" && ok "T3 a secret with loose mode (644) -> caught, exit 1" \
              || { no "T3 wrong mode should fail (rc=$rc)"; sed 's/^/       /' "$R/out"; }
rm -rf "$R"

# T4: an UNDECLARED file in the folder -> FAIL (spread: a secret nobody declared)
R="$(mkenv)"; printf 'x\n' > "$R/${SITE}-creds/stray.env"; chmod 600 "$R/${SITE}-creds/stray.env"; rc=$(run "$R")
[ "$rc" = 1 ] && grep -q "UNDECLARED file in folder: stray.env" "$R/out" && ok "T4 an undeclared file in the folder -> caught, exit 1" \
              || { no "T4 an undeclared file should fail (rc=$rc)"; sed 's/^/       /' "$R/out"; }
rm -rf "$R"

# T5: SPRAWL -- a sensitive file loose in CREDS_ROOT, outside any *-creds/ folder
R="$(mkenv)"; printf 'x\n' > "$R/loose.env"; chmod 600 "$R/loose.env"; rc=$(run "$R")
[ "$rc" = 1 ] && grep -q "SPRAWL: sensitive file loose" "$R/out" && ok "T5 a loose .env in the home root -> SPRAWL, exit 1" \
              || { no "T5 sprawl in the home root should fail (rc=$rc)"; sed 's/^/       /' "$R/out"; }
rm -rf "$R"

# T6: the folder itself not 0700 -> FAIL
R="$(mkenv)"; chmod 755 "$R/${SITE}-creds"; rc=$(run "$R")
[ "$rc" = 1 ] && grep -q "folder mode 755" "$R/out" && ok "T6 a world-listable creds folder (0755) -> caught, exit 1" \
              || { no "T6 a non-0700 folder should fail (rc=$rc)"; sed 's/^/       /' "$R/out"; }
rm -rf "$R"

# T7: the audit reads NO secret content -- no content-reading verbs in the script
grep -qE '\b(cat|head|tail|less|more|od|xxd|hexdump)\b' "$AUDIT" \
  && no "T7 the audit contains a content-reading verb -- it must inspect metadata only" \
  || ok "T7 metadata-only: no cat/head/tail/od/xxd in the audit"

echo
if [ "$F" = 0 ]; then echo "creds-audit: $P/$P PASS"; exit 0; fi
echo "creds-audit: FAILURES: $F (passed $P)"; exit 1
