Fix deploy_agent.sh — stdin consumption in loop, base64 script delivery via su

This commit is contained in:
Semaphore
2026-03-12 12:02:16 -07:00
parent ddf49eec5e
commit 68c01ceafb

View File

@@ -366,6 +366,12 @@ fi
log_section "Processing Linux hosts"
# Write host list to temp file to prevent ssh/sshpass from consuming
# the while loop's stdin (classic bash gotcha with network commands in loops)
LINUX_HOSTS_FILE=$(mktemp)
echo "$LINUX_HOSTS" > "$LINUX_HOSTS_FILE"
trap 'rm -f "$LINUX_HOSTS_FILE"' EXIT
while IFS='|' read -r HOSTNAME HOST_IP; do
[[ -z "$HOSTNAME" ]] && continue
((HOSTS_TOTAL++)) || true
@@ -379,16 +385,16 @@ while IFS='|' read -r HOSTNAME HOST_IP; do
continue
fi
# Add host to known_hosts
# Add host to known_hosts — redirect stdin from /dev/null to prevent draining loop fd
log_info "Scanning host key..."
ssh-keyscan -T 10 "$HOST_IP" >> /root/.ssh/known_hosts 2>/dev/null || true
ssh-keyscan -T 10 "$HOST_IP" >> /root/.ssh/known_hosts 2>/dev/null < /dev/null || true
# Test native user SSH access
log_info "Testing SSH as $NATIVE_USER..."
if ! sshpass -p "$NATIVE_PASS" ssh -o StrictHostKeyChecking=no \
-o ConnectTimeout=10 \
-o PasswordAuthentication=yes \
"$NATIVE_USER@$HOST_IP" "echo connected" &>/dev/null; then
"$NATIVE_USER@$HOST_IP" "echo connected" < /dev/null &>/dev/null; then
log_error "Cannot SSH to $HOSTNAME ($HOST_IP) as $NATIVE_USER — skipping"
FAILED_HOSTS+=("$HOSTNAME ($HOST_IP) — SSH connection failed")
((HOSTS_FAILED++)) || true
@@ -403,6 +409,10 @@ while IFS='|' read -r HOSTNAME HOST_IP; do
"$AGENT_USER" \
"$SKIP_SSHD")
# Base64-encode the script so it can be passed cleanly through su - root -c
# su -c replaces stdin so 'bash -s' heredoc approach doesn't work
REMOTE_SCRIPT_B64=$(echo "$REMOTE_SCRIPT" | base64 -w 0)
# Execute via su - on remote host
log_info "Executing bootstrap via su - root..."
BOOTSTRAP_OUTPUT=$(sshpass -p "$NATIVE_PASS" ssh \
@@ -410,7 +420,8 @@ while IFS='|' read -r HOSTNAME HOST_IP; do
-o ConnectTimeout=10 \
-o PasswordAuthentication=yes \
"$NATIVE_USER@$HOST_IP" \
"echo '$ROOT_PASS' | su - root -c 'bash -s'" <<< "$REMOTE_SCRIPT" 2>&1) || {
"echo '$ROOT_PASS' | su - root -c 'echo $REMOTE_SCRIPT_B64 | base64 -d | bash'" \
< /dev/null 2>&1) || {
log_error "Bootstrap script failed on $HOSTNAME"
echo "$BOOTSTRAP_OUTPUT" | sed 's/^/ /'
FAILED_HOSTS+=("$HOSTNAME ($HOST_IP) — bootstrap script failed")
@@ -429,7 +440,8 @@ while IFS='|' read -r HOSTNAME HOST_IP; do
-o StrictHostKeyChecking=no \
-o ConnectTimeout=10 \
-o PasswordAuthentication=no \
"$AGENT_USER@$HOST_IP" "echo key-auth-ok" &>/dev/null; then
"$AGENT_USER@$HOST_IP" "echo key-auth-ok" \
< /dev/null &>/dev/null; then
log_ok "Key-based login verified for $AGENT_USER"
else
log_warn "Key-based login test failed for $AGENT_USER — check manually"
@@ -441,7 +453,7 @@ while IFS='|' read -r HOSTNAME HOST_IP; do
log_ok "Bootstrap complete: $HOSTNAME"
((HOSTS_OK++)) || true
done <<< "$LINUX_HOSTS"
done < "$LINUX_HOSTS_FILE"
# ─── Summary ─────────────────────────────────────────────────────────────────
echo ""
@@ -466,4 +478,3 @@ echo ""
if [[ $HOSTS_FAILED -gt 0 ]]; then
exit 1
fi