From 95ad74a068382c66852e0bded40441af3c318a73 Mon Sep 17 00:00:00 2001 From: reachableceo Date: Mon, 10 Aug 2026 14:16:19 -0500 Subject: [PATCH] fix(access-matrix): use correct user per system type + targeted sudo check MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace generic root→localuser fallback with explicit user mapping: - Proxmox hosts/appliances → root (no sudo check) - stlpc-* → labuser (no sudo) - subopi* → subodev (with sudo check) - everything else → localuser (with sudo check) Refs [#403] 💘 Generated with Crush Assisted-by: Crush:glm-5.2 --- access-matrix.sh | 62 ++++++++++++++++++++++++++++++------------------ 1 file changed, 39 insertions(+), 23 deletions(-) diff --git a/access-matrix.sh b/access-matrix.sh index 3c3821b..4226f64 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. -# For each node: try root SSH, then localuser SSH; report access level. +# Uses the correct SSH user 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,31 +8,47 @@ cd /home/reachableceo/projects/PFVCluster || exit 1 # Policy-excluded systems (never attempt access) EXCLUDE=':tsys-cloudron:pfv-bms:tsys-umbrel:stlpc-bizoffice:ultix-highside:' -printf '%-28s %-16s %-18s %s\n' "NAME" "TS-IP" "ACCESS" "SUDO" -printf '%-28s %-16s %-18s %s\n' "----" "-----" "------" "----" +# Determine the SSH user for a given hostname. +# Returns "user:sudo" where sudo is "yes" or "no". +user_for() { + local name="$1" + case "$name" in + pfv-tsys[0-9]) echo "root:no" ;; + *-proxmox-datacenter) echo "root:no" ;; + *-proxmox-pve) echo "root:no" ;; + *-proxmox-pbs) echo "root:no" ;; + *-proxmox-mailgw*) echo "root:no" ;; + *-proxmox-backup*) echo "root:no" ;; + stlpc-*) echo "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 '%-28s %-16s %-18s\n' "$name" "$ip" "EXCLUDED"; continue;; esac + case "$EXCLUDE" in *":$name:"*) printf '%-32s %-16s %-12s\n' "$name" "$ip" "EXCLUDED"; continue;; esac - # Try root - rout=$(VM_IP="$ip" VM_USER="root" bash tests/remote.sh vm 'echo OK; id -un' &1 | tr '\n' '/') - case "$rout" in - *OK/root*) sudo=$(VM_IP="$ip" VM_USER="root" bash tests/remote.sh vm 'sudo -n true 2>/dev/null && echo SUDOOK || echo SUDONO' &1 | tr -d '\n') - printf '%-28s %-16s %-18s %s\n' "$name" "$ip" "root-SSH" "${sudo:-?}"; continue;; - esac - # Try localuser - lout=$(VM_IP="$ip" VM_USER="localuser" bash tests/remote.sh vm 'echo OK; id -un' &1 | tr '\n' '/') - case "$lout" in - *OK/localuser*) sudo=$(VM_IP="$ip" VM_USER="localuser" bash tests/remote.sh vm 'sudo -n true 2>/dev/null && echo SUDOOK || echo SUDONO' &1 | tr -d '\n') - printf '%-28s %-16s %-18s %s\n' "$name" "$ip" "localuser-SSH" "${sudo:-?}"; continue;; - esac - # Neither — classify the failure - case "$rout" in - *Connection\ refused*) printf '%-28s %-16s %-18s\n' "$name" "$ip" "NO-SSH(port22)";; - *keyboard-interactive*) printf '%-28s %-16s %-18s\n' "$name" "$ip" "2FA-blocked";; - *Permission\ denied*) printf '%-28s %-16s %-18s\n' "$name" "$ip" "NO-KEY";; - *No\ route*) printf '%-28s %-16s %-18s\n' "$name" "$ip" "UNREACHABLE";; - *) printf '%-28s %-16s %-18s\n' "$name" "$ip" "NO-KEY";; + map=$(user_for "$name") + user="${map%%:*}"; expect_sudo="${map##*:}" + + 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:-?}" + else + printf '%-32s %-16s %-12s %-8s\n' "$name" "$ip" "${user}-SSH" "n/a" + 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" ;; esac done