diff --git a/access-matrix.sh b/access-matrix.sh index 4226f64..b780552 100644 --- a/access-matrix.sh +++ b/access-matrix.sh @@ -1,6 +1,6 @@ #!/usr/bin/bash -# access-matrix.sh — definitive access verification across all online Linux Tailscale nodes. -# Uses the correct SSH user per system type, checks sudo where applicable. +# access-matrix.sh — definitive access verification across all Linux Tailscale nodes. +# Uses the correct SSH user(s) per system type, checks sudo where applicable. # Routes through remote.sh (the only allowed ssh path). set -u cd /home/reachableceo/projects/PFVCluster || exit 1 @@ -8,9 +8,9 @@ cd /home/reachableceo/projects/PFVCluster || exit 1 # Policy-excluded systems (never attempt access) EXCLUDE=':tsys-cloudron:pfv-bms:tsys-umbrel:stlpc-bizoffice:ultix-highside:' -# Determine the SSH user for a given hostname. -# Returns "user:sudo" where sudo is "yes" or "no". -user_for() { +# Determine the SSH user(s) for a given hostname and whether sudo is expected. +# Returns "user1:user2:...:sudoflag" where sudoflag is "yes" or "no". +users_for() { local name="$1" case "$name" in pfv-tsys[0-9]) echo "root:no" ;; @@ -19,36 +19,47 @@ user_for() { *-proxmox-pbs) echo "root:no" ;; *-proxmox-mailgw*) echo "root:no" ;; *-proxmox-backup*) echo "root:no" ;; - stlpc-*) echo "labuser:no" ;; + ultix-streaming) echo "root:no" ;; + stlpc-*) echo "root:labuser:no" ;; subopi*) echo "subodev:yes" ;; *) echo "localuser:yes" ;; esac } -printf '%-32s %-16s %-12s %-8s\n' "NAME" "TS-IP" "ACCESS" "SUDO" -printf '%-32s %-16s %-12s %-8s\n' "----" "-----" "------" "----" - -tailscale status 2>/dev/null | awk '$4=="linux" && $0 !~ /offline/ {print $2, $1}' | sort | while read -r name ip; do - [ -n "$name" ] || continue - case "$EXCLUDE" in *":$name:"*) printf '%-32s %-16s %-12s\n' "$name" "$ip" "EXCLUDED"; continue;; esac - - map=$(user_for "$name") - user="${map%%:*}"; expect_sudo="${map##*:}" - +check_user() { + local ip="$1" user="$2" expect_sudo="$3" + local out sudo out=$(VM_IP="$ip" VM_USER="$user" bash tests/remote.sh vm 'echo SSHOK; id -un' &1 | tr '\n' '/') case "$out" in *SSHOK*) if [ "$expect_sudo" = "yes" ]; then sudo=$(VM_IP="$ip" VM_USER="$user" bash tests/remote.sh vm 'sudo -n true 2>/dev/null && echo SUDOOK || echo SUDONO' &1 | tr -d '\n') - printf '%-32s %-16s %-12s %-8s\n' "$name" "$ip" "${user}-SSH" "${sudo:-?}" + printf '%s(%s)' "$user" "${sudo:-?}" else - printf '%-32s %-16s %-12s %-8s\n' "$name" "$ip" "${user}-SSH" "n/a" + printf '%s(ok)' "$user" fi ;; - *keyboard-interactive*) printf '%-32s %-16s %-12s\n' "$name" "$ip" "2FA-blocked" ;; - *Connection\ refused*) printf '%-32s %-16s %-12s\n' "$name" "$ip" "NO-SSH(22)" ;; - *Permission\ denied*) printf '%-32s %-16s %-12s\n' "$name" "$ip" "NO-KEY" ;; - *No\ route*) printf '%-32s %-16s %-12s\n' "$name" "$ip" "UNREACHABLE" ;; - *) printf '%-32s %-16s %-12s\n' "$name" "$ip" "NO-KEY" ;; + *keyboard-interactive*) printf '%s(2FA)' "$user" ;; + *Connection\ refused*) printf '%s(NOSSH)' "$user" ;; + *) printf '%s(NOKEY)' "$user" ;; esac +} + +printf '%-32s %-16s %s\n' "NAME" "TS-IP" "ACCESS" +printf '%-32s %-16s %s\n' "----" "-----" "------" + +tailscale status 2>/dev/null | awk '$4=="linux" {print $2, $1}' | sort | while read -r name ip; do + [ -n "$name" ] || continue + case "$EXCLUDE" in *":$name:"*) printf '%-32s %-16s %s\n' "$name" "$ip" "EXCLUDED"; continue;; esac + + map=$(users_for "$name") + expect_sudo="${map##*:}" + users="${map%:*}" + result="" + IFS=':' read -ra user_list <<< "$users" + for u in "${user_list[@]}"; do + r=$(check_user "$ip" "$u" "$expect_sudo") + [ -z "$result" ] && result="$r" || result="$result $r" + done + printf '%-32s %-16s %s\n' "$name" "$ip" "$result" done diff --git a/bootstrap-all.sh b/bootstrap-all.sh index 9bd7cd1..84d072b 100644 --- a/bootstrap-all.sh +++ b/bootstrap-all.sh @@ -2,9 +2,9 @@ # bootstrap-all.sh — push agent key + sudo to every remaining NO-KEY system. # # Groups (user determined by system type): -# 1. labuser → stlpc-* systems -# 2. subodev → subopi* systems -# 3. localuser → everything else (kali, cloudron, siem, ubuntu server, etc.) +# 1. labuser+root → stlpc-* systems (key to both, no sudo for labuser) +# 2. subodev → subopi* systems +# 3. localuser → everything else (cloudron, siem, ubuntu server, kali, etc.) # # You'll enter passwords interactively. Idempotent: safe to re-run. set -u @@ -32,7 +32,7 @@ run_as_user() { echo } -# === Group 1: labuser (stlpc-*) === +# === Group 1: labuser (stlpc-* — agent-bootstrap pushes keys to root+labuser) === echo "########################################" echo "# Group 1: labuser (stlpc-*)" echo "########################################" @@ -53,8 +53,8 @@ echo "########################################" echo "# Group 3: localuser (standard systems)" echo "########################################" echo -run_as_user kali-tsys 100.82.30.115 localuser run_as_user devbox-cloudron 100.119.72.25 localuser +run_as_user kali-tsys 100.82.30.115 localuser run_as_user pfv-jetson-nano-1 100.82.230.119 localuser run_as_user pfvsvrpi 100.91.151.113 localuser run_as_user preprod-cloudron 100.95.69.89 localuser @@ -72,4 +72,7 @@ echo "========================================" echo "Still 2FA-blocked (need policy decision):" echo " sectestbed-sandbox, tsys-ucs-01, tsys-ucs-02" echo "========================================" +echo "Unknown user (not in bootstrap):" +echo " stlp-3dscanner (100.125.14.37) — need user clarification" +echo "========================================" echo "Tell the agent to re-run access-matrix.sh to verify."