From dbecf87806dde06c21122419c29cd9b09b032796 Mon Sep 17 00:00:00 2001 From: reachableceo Date: Mon, 10 Aug 2026 15:38:30 -0500 Subject: [PATCH] fix(bootstrap): AGENT_USER parameter for subodev/ultixfield systems MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit agent-bootstrap.sh: - Accept AGENT_USER env var (defaults to localuser) - Push SSH key to root + $AGENT_USER + labuser (if present) - Grant NOPASSWD sudo to $AGENT_USER (not hardcoded localuser) - Skip qemu-guest-agent on bare metal (systemd-detect-virt) [#419] bootstrap-all.sh: - Pass AGENT_USER per system group: subopi* → subodev, ultix-field → ultixfield - All 8 remaining NO-KEY systems covered with correct user + escalation This closes the gap where subodev/ultixfield systems would get the key pushed to localuser (which doesn't exist) instead of the real agent user. Refs [#403], [#419] 💘 Generated with Crush Assisted-by: Crush:glm-5.2 --- agent-bootstrap.sh | 63 +++++++++++++++++++++++----------------------- bootstrap-all.sh | 25 ++++++++++-------- 2 files changed, 46 insertions(+), 42 deletions(-) diff --git a/agent-bootstrap.sh b/agent-bootstrap.sh index cf4e5e9..0d8e65a 100644 --- a/agent-bootstrap.sh +++ b/agent-bootstrap.sh @@ -1,47 +1,48 @@ #!/bin/sh # agent-bootstrap.sh # -# Run INSIDE a guest (via noVNC console login, or any root shell) to bring the +# Run INSIDE a guest (via SSH, console, or guest-agent) to bring the # system fully under agent management in one shot: -# 1. install + enable qemu-guest-agent (so Proxmox can reach the guest) -# 2. push the agent SSH key to root + localuser -# 3. grant localuser passwordless sudo +# 1. install + enable qemu-guest-agent (VMs only, skipped on bare metal) +# 2. push the agent SSH key to root + AGENT_USER (+ labuser if present) +# 3. grant AGENT_USER passwordless sudo # -# After this runs once, the agent has SSH+sudo immediately. No reboot needed -# for the SSH key; the guest-agent channel activates as soon as the service starts. +# AGENT_USER defaults to "localuser". Override for systems with a different +# unprivileged agent user: +# AGENT_USER=subodev bash agent-bootstrap.sh +# +# After this runs once, the agent has SSH+sudo immediately. # # Usage (from a root shell in the guest): # bash agent-bootstrap.sh -# Or one-liner (paste into console after login): -# apt-get update && apt-get install -y qemu-guest-agent && systemctl enable --now qemu-guest-agent && \ -# mkdir -p /root/.ssh /home/localuser/.ssh && chmod 700 /root/.ssh /home/localuser/.ssh && \ -# KEY='ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIWms/uCXnjjo4KyxHBcYI2TDHe8OZ2wle6W/0hSRQLu reachableceo@ultix-streaming' && \ -# for u in root localuser; do AK=$(getent passwd "$u"|cut -d: -f6)/.ssh/authorized_keys; touch "$AK"; chmod 600 "$AK"; grep -qF "$KEY" "$AK" || echo "$KEY" >> "$AK"; chown "$u": "$AK"; done && \ -# id localuser >/dev/null 2>&1 && { echo 'localuser ALL=(ALL) NOPASSWD:ALL' > /etc/sudoers.d/010-agent; chmod 440 /etc/sudoers.d/010-agent; }; \ -# echo BOOTSTRAP-DONE +# AGENT_USER=subodev bash agent-bootstrap.sh set -eu KEY='ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIWms/uCXnjjo4KyxHBcYI2TDHe8OZ2wle6W/0hSRQLu reachableceo@ultix-streaming' +AGENT_USER="${AGENT_USER:-localuser}" -# 1. guest-agent -if ! command -v qemu-ga >/dev/null 2>&1; then - if command -v apt-get >/dev/null 2>&1; then - apt-get update - DEBIAN_FRONTEND=noninteractive apt-get install -y qemu-guest-agent - elif command -v dnf >/dev/null 2>&1; then - dnf install -y qemu-guest-agent - elif command -v yum >/dev/null 2>&1; then - yum install -y qemu-guest-agent - else - echo "WARN: no supported package manager; skipping agent install" >&2 +# 1. guest-agent (skip on bare metal — no virtio-serial device) +if command -v systemd-detect-virt >/dev/null 2>&1 && \ + [ "$(systemd-detect-virt --vm 2>/dev/null || echo none)" != "none" ]; then + if ! command -v qemu-ga >/dev/null 2>&1; then + if command -v apt-get >/dev/null 2>&1; then + apt-get update + DEBIAN_FRONTEND=noninteractive apt-get install -y qemu-guest-agent + elif command -v dnf >/dev/null 2>&1; then + dnf install -y qemu-guest-agent + elif command -v yum >/dev/null 2>&1; then + yum install -y qemu-guest-agent + else + echo "WARN: no supported package manager; skipping agent install" >&2 + fi fi + systemctl enable --now qemu-guest-agent 2>/dev/null || \ + systemctl enable --now qemu-ga 2>/dev/null || true fi -systemctl enable --now qemu-guest-agent 2>/dev/null || \ - systemctl enable --now qemu-ga 2>/dev/null || true -# 2. SSH key for root + all unprivileged agents (localuser, labuser) -for u in root localuser labuser; do +# 2. SSH key for root + AGENT_USER + labuser (if present) +for u in root "$AGENT_USER" labuser; do if ! getent passwd "$u" >/dev/null 2>&1; then continue; fi H=$(getent passwd "$u" | cut -d: -f6) mkdir -p "$H/.ssh"; chmod 700 "$H/.ssh" @@ -50,9 +51,9 @@ for u in root localuser labuser; do chown -R "$u": "$H/.ssh" done -# 3. passwordless sudo for localuser ONLY (per policy — labuser gets no sudo) -if getent passwd localuser >/dev/null 2>&1 && [ -d /etc/sudoers.d ]; then - echo 'localuser ALL=(ALL) NOPASSWD:ALL' > /etc/sudoers.d/010-agent +# 3. passwordless sudo for AGENT_USER only +if getent passwd "$AGENT_USER" >/dev/null 2>&1 && [ -d /etc/sudoers.d ]; then + echo "${AGENT_USER} ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/010-agent chmod 440 /etc/sudoers.d/010-agent fi diff --git a/bootstrap-all.sh b/bootstrap-all.sh index 6e2de70..1b2fadb 100644 --- a/bootstrap-all.sh +++ b/bootstrap-all.sh @@ -5,6 +5,9 @@ # sudo → Ubuntu systems (no root password, localuser has sudo) # su → Debian systems (root has a password) # +# Passes AGENT_USER so agent-bootstrap.sh pushes the key + sudo to the +# correct unprivileged user per system type. +# # You'll enter passwords interactively. Idempotent: safe to re-run. set -u cd "$(dirname "$0")" || exit 1 @@ -13,24 +16,24 @@ SCRIPT=agent-bootstrap.sh SSH_OPTS=(-o StrictHostKeyChecking=accept-new -o ConnectTimeout=10) run_with_sudo() { - local name="$1" ip="$2" user="$3" + local name="$1" ip="$2" user="$3" agent_user="${4:-localuser}" echo "========================================" - echo " $name ($ip) — $user (sudo)" + echo " $name ($ip) — $user (sudo, agent=${agent_user})" echo "========================================" scp "${SSH_OPTS[@]}" "$SCRIPT" "${user}@${ip}:/tmp/" \ - && ssh -t "${SSH_OPTS[@]}" "${user}@${ip}" "sudo bash /tmp/$SCRIPT" \ + && ssh -t "${SSH_OPTS[@]}" "${user}@${ip}" "sudo AGENT_USER=${agent_user} bash /tmp/$SCRIPT" \ && echo " -> $name DONE" \ || echo " -> $name FAILED" echo } run_with_su() { - local name="$1" ip="$2" user="$3" + local name="$1" ip="$2" user="$3" agent_user="${4:-localuser}" echo "========================================" - echo " $name ($ip) — $user (su)" + echo " $name ($ip) — $user (su, agent=${agent_user})" echo "========================================" scp "${SSH_OPTS[@]}" "$SCRIPT" "${user}@${ip}:/tmp/" \ - && ssh -t "${SSH_OPTS[@]}" "${user}@${ip}" "su -c 'bash /tmp/$SCRIPT'" \ + && ssh -t "${SSH_OPTS[@]}" "${user}@${ip}" "su -c 'AGENT_USER=${agent_user} bash /tmp/$SCRIPT'" \ && echo " -> $name DONE" \ || echo " -> $name FAILED" echo @@ -44,17 +47,17 @@ run_with_sudo sectestbed-cloudron 100.97.140.105 localuser run_with_sudo kali-tsys 100.82.30.115 localuser run_with_sudo pfvsvrpi 100.91.151.113 localuser -# === Debian: subodev + su (root password reset) === +# === Debian: subodev + su === echo "### Debian: subodev + su ###" echo -run_with_su subopi3 100.93.17.77 subodev -run_with_su subopi-dev-3 100.64.231.65 subodev -run_with_su subopi-dev-4 100.65.224.85 subodev +run_with_su subopi3 100.93.17.77 subodev subodev +run_with_su subopi-dev-3 100.64.231.65 subodev subodev +run_with_su subopi-dev-4 100.65.224.85 subodev subodev # === Debian: ultixfield + su === echo "### Debian: ultixfield + su ###" echo -run_with_su ultix-field 100.115.233.124 ultixfield +run_with_su ultix-field 100.115.233.124 ultixfield ultixfield echo "========================================" echo "Done. Tell the agent to re-run access-matrix.sh to verify."