#!/usr/bin/env bash # Run the read-only audit over SSH. Does not leave a persistent agent. # Usage: bash estate-audit-fleet.sh hosts.txt # hosts.txt: one SSH target per line (user@host or ssh config alias) set -u LIST="${1:-hosts.txt}" SELF="$(cd "$(dirname "$0")" && pwd)" AUDIT="$SELF/estate-audit.sh" MERGE="$SELF/estate-audit-merge.sh" if [ ! -f "$LIST" ] || [ ! -f "$AUDIT" ]; then echo "Usage: bash estate-audit-fleet.sh hosts.txt" >&2 exit 2 fi STAMP="$(date -u +%Y%m%dT%H%M%SZ)" OUT="$SELF/reports-$STAMP" mkdir -p "$OUT" JSONS=() while IFS= read -r target || [ -n "$target" ]; do case "$target" in ''|'#'*) continue ;; esac safe="$(printf '%s' "$target" | tr -c 'A-Za-z0-9._@-' '_')" dest="$OUT/$safe" mkdir -p "$dest" echo "== $target ==" if ssh -o BatchMode=yes -o ConnectTimeout=12 "$target" 'sudo -n bash -s -- --quiet' < "$AUDIT" > "$dest/quote.txt" 2>"$dest/ssh.err"; then ssh -o BatchMode=yes "$target" 'ls -1d /tmp/cw-estate-audit-* 2>/dev/null | tail -1' > "$dest/remote-dir.txt" || true rdir="$(tr -d '\r' < "$dest/remote-dir.txt")" if [ -n "$rdir" ]; then scp -o BatchMode=yes "$target:$rdir/estate.json" "$dest/estate.json" 2>/dev/null || true fi else echo "FAILED $target — see $dest/ssh.err" >&2 cat "$dest/ssh.err" >&2 || true fi [ -f "$dest/estate.json" ] && JSONS+=("$dest/estate.json") done < "$LIST" if [ ${#JSONS[@]} -gt 0 ]; then echo bash "$MERGE" "${JSONS[@]}" | tee "$OUT/estate-quote.txt" echo "Reports in $OUT" else echo "No JSON collected." >&2 exit 1 fi