Fix wizard: defaults for all prompts, random hostname/device-id, download robustness

- Add prompt_default() helper: shows defaults, accepts Enter to use them
- WiFi: default=n (skip), keeps passphrase prompt loop
- Root password: auto-generate with openssl, show in summary if used, operator can override
- SSH key: default=1 (generate new)
- Device ID: auto-generate bb-<8-char-uuid>
- Boot mode: default=1 (passive)
- VPN: default=1 (none)
- Hostname: NEW section with auto-generated node-<6-char-uuid> default
- Alerter: default=n (disabled)
- Download: use curl -L (no -f), verify file exists and >50MB
- Config summary: show hostname, mask password (show auto-generated clearly)
- Apply config: write BB_HOSTNAME to /etc/hostname and /etc/hosts
- No eval with user input: use printf -v for variable assignment
This commit is contained in:
Cobra
2026-04-07 14:17:01 -04:00
parent ae35f3f7b8
commit 2b53da80d0
+66 -41
View File
@@ -51,6 +51,19 @@ banner() {
echo "" echo ""
} }
prompt_default() {
local var="$1" prompt="$2" default="$3"
echo -n -e "${CYAN}${prompt}${NC}"
[[ -n "$default" ]] && echo -n -e " ${BOLD}[${default}]${NC}"
echo -n ": "
read -r input
if [[ -z "$input" ]]; then
printf -v "$var" '%s' "$default"
else
printf -v "$var" '%s' "$input"
fi
}
# ══════════════════════════════════════════════════════════════════════════════ # ══════════════════════════════════════════════════════════════════════════════
# PREFLIGHT # PREFLIGHT
# ══════════════════════════════════════════════════════════════════════════════ # ══════════════════════════════════════════════════════════════════════════════
@@ -127,7 +140,12 @@ if [[ -z "$IMAGE" ]]; then
IMAGE="${CACHE_DIR}/${IMAGE_FILENAME}" IMAGE="${CACHE_DIR}/${IMAGE_FILENAME}"
if [[ ! -f "$IMAGE" ]]; then if [[ ! -f "$IMAGE" ]]; then
curl -fL --progress-bar "$IMAGE_URL" -o "$IMAGE" || error "Failed to download image" curl -L --progress-bar "$IMAGE_URL" -o "$IMAGE" || error "Failed to download image"
# Verify download: file exists and is > 50MB
if [[ ! -s "$IMAGE" ]] || [[ $(stat -c%s "$IMAGE" 2>/dev/null || echo 0) -lt 52428800 ]]; then
rm -f "$IMAGE"
error "Download failed or file too small (expected > 50MB)"
fi
info "Image downloaded: $IMAGE_FILENAME" info "Image downloaded: $IMAGE_FILENAME"
else else
info "Image already cached: $IMAGE_FILENAME" info "Image already cached: $IMAGE_FILENAME"
@@ -150,16 +168,20 @@ section "Configuration Wizard"
# WiFi (optional) # WiFi (optional)
step "WiFi Configuration" step "WiFi Configuration"
echo -n -e "${CYAN}Configure WiFi? (y/n):${NC} " prompt_default enable_wifi "Configure WiFi? (y/n)" "n"
read -r enable_wifi
if [[ "$enable_wifi" =~ ^[yY]$ ]]; then if [[ "$enable_wifi" =~ ^[yY]$ ]]; then
echo -n -e "${CYAN}WiFi SSID:${NC} " prompt_default wifi_ssid "WiFi SSID" ""
read -r wifi_ssid while true; do
echo -n -e "${CYAN}WiFi Passphrase:${NC} " echo -n -e "${CYAN}WiFi Passphrase${NC}: "
read -s -r wifi_pass; echo read -s -r wifi_pass; echo
echo -n -e "${CYAN}Confirm Passphrase:${NC} " echo -n -e "${CYAN}Confirm Passphrase${NC}: "
read -s -r wifi_pass2; echo read -s -r wifi_pass2; echo
[[ "$wifi_pass" == "$wifi_pass2" ]] || error "Passphrases do not match" if [[ "$wifi_pass" == "$wifi_pass2" ]]; then
break
else
warn "Passphrases do not match. Try again."
fi
done
WIFI_SSID="$wifi_ssid" WIFI_SSID="$wifi_ssid"
WIFI_PASS="$wifi_pass" WIFI_PASS="$wifi_pass"
unset wifi_pass wifi_pass2 unset wifi_pass wifi_pass2
@@ -170,33 +192,29 @@ fi
# Root password (required) # Root password (required)
step "Root Password" step "Root Password"
while true; do DEFAULT_ROOT_PASS=$(openssl rand -base64 16 | tr -d '=+/')
echo -n -e "${CYAN}Root password:${NC} " ROOT_PASS_IS_AUTO=false
read -s -r root_pass; echo echo -e "${YELLOW}Auto-generated password: ${BOLD}${DEFAULT_ROOT_PASS}${NC}"
echo -n -e "${CYAN}Confirm:${NC} " prompt_default root_pass "Enter custom password or press Enter to use auto-generated" ""
read -s -r root_pass2; echo if [[ -z "$root_pass" ]]; then
if [[ "$root_pass" == "$root_pass2" && -n "$root_pass" ]]; then ROOT_PASS="$DEFAULT_ROOT_PASS"
ROOT_PASS_IS_AUTO=true
else
ROOT_PASS="$root_pass" ROOT_PASS="$root_pass"
unset root_pass root_pass2 fi
break unset root_pass
else
warn "Passwords do not match or empty. Try again."
fi
done
# SSH Key # SSH Key
step "SSH Key Configuration" step "SSH Key Configuration"
echo " [1] Generate new keypair (stored in Infisical)" echo " [1] Generate new keypair (stored in Infisical)"
echo " [2] Use existing public key file" echo " [2] Use existing public key file"
echo -n -e "${CYAN}SSH option (1-2):${NC} " prompt_default ssh_opt "SSH option (1-2)" "1"
read -r ssh_opt
if [[ "$ssh_opt" == "1" ]]; then if [[ "$ssh_opt" == "1" ]]; then
SSH_MODE="generate" SSH_MODE="generate"
elif [[ "$ssh_opt" == "2" ]]; then elif [[ "$ssh_opt" == "2" ]]; then
SSH_MODE="existing" SSH_MODE="existing"
echo -n -e "${CYAN}Path to public key file:${NC} " prompt_default ssh_pubkey_path "Path to public key file" ""
read -r ssh_pubkey_path
[[ -f "$ssh_pubkey_path" ]] || error "File not found: $ssh_pubkey_path" [[ -f "$ssh_pubkey_path" ]] || error "File not found: $ssh_pubkey_path"
SSH_PUBKEY=$(cat "$ssh_pubkey_path") SSH_PUBKEY=$(cat "$ssh_pubkey_path")
else else
@@ -205,18 +223,22 @@ fi
# Device ID # Device ID
step "Device ID" step "Device ID"
echo -n -e "${CYAN}Device label (e.g. bb-01):${NC} " DEFAULT_DEVICE_ID="bb-$(cat /proc/sys/kernel/random/uuid | cut -c1-8)"
read -r device_id prompt_default device_id "Device label (e.g. bb-a3f2c1)" "$DEFAULT_DEVICE_ID"
[[ -n "$device_id" ]] || error "Device ID cannot be empty"
DEVICE_ID="$device_id" DEVICE_ID="$device_id"
# Hostname
step "Hostname"
DEFAULT_HOSTNAME="node-$(cat /proc/sys/kernel/random/uuid | cut -c1-6)"
prompt_default bb_hostname "Hostname" "$DEFAULT_HOSTNAME"
BB_HOSTNAME="$bb_hostname"
# Auto-start mode # Auto-start mode
step "Auto-start Mode on Boot" step "Auto-start Mode on Boot"
echo " [1] Passive only (capture + analysis, no active offense)" echo " [1] Passive only (capture + analysis, no active offense)"
echo " [2] Full autonomous (all modules)" echo " [2] Full autonomous (all modules)"
echo " [3] Manual (operator SSHs in to start)" echo " [3] Manual (operator SSHs in to start)"
echo -n -e "${CYAN}Select mode (1-3):${NC} " prompt_default mode_opt "Select mode (1-3)" "1"
read -r mode_opt
if [[ "$mode_opt" == "1" ]]; then if [[ "$mode_opt" == "1" ]]; then
BB_MODE="passive" BB_MODE="passive"
@@ -233,8 +255,7 @@ step "VPN Tunnel"
echo " [1] None" echo " [1] None"
echo " [2] Tailscale" echo " [2] Tailscale"
echo " [3] WireGuard" echo " [3] WireGuard"
echo -n -e "${CYAN}Select VPN (1-3):${NC} " prompt_default vpn_opt "Select VPN (1-3)" "1"
read -r vpn_opt
BB_VPN="none" BB_VPN="none"
TAILSCALE_KEY="" TAILSCALE_KEY=""
@@ -244,13 +265,11 @@ if [[ "$vpn_opt" == "1" ]]; then
BB_VPN="none" BB_VPN="none"
elif [[ "$vpn_opt" == "2" ]]; then elif [[ "$vpn_opt" == "2" ]]; then
BB_VPN="tailscale" BB_VPN="tailscale"
echo -n -e "${CYAN}Tailscale auth key:${NC} " prompt_default tailscale_key "Tailscale auth key" ""
read -r tailscale_key
TAILSCALE_KEY="$tailscale_key" TAILSCALE_KEY="$tailscale_key"
elif [[ "$vpn_opt" == "3" ]]; then elif [[ "$vpn_opt" == "3" ]]; then
BB_VPN="wireguard" BB_VPN="wireguard"
echo -n -e "${CYAN}Path to WireGuard config (wg0.conf):${NC} " prompt_default wg_config_path "Path to WireGuard config (wg0.conf)" ""
read -r wg_config_path
[[ -f "$wg_config_path" ]] || error "File not found: $wg_config_path" [[ -f "$wg_config_path" ]] || error "File not found: $wg_config_path"
WG_CONFIG=$(cat "$wg_config_path") WG_CONFIG=$(cat "$wg_config_path")
else else
@@ -259,11 +278,9 @@ fi
# Network alerter webhook # Network alerter webhook
step "Network Alerter" step "Network Alerter"
echo -n -e "${CYAN}Enable alerter webhook? (y/n):${NC} " prompt_default enable_alerter "Enable alerter webhook? (y/n)" "n"
read -r enable_alerter
if [[ "$enable_alerter" =~ ^[yY]$ ]]; then if [[ "$enable_alerter" =~ ^[yY]$ ]]; then
echo -n -e "${CYAN}Webhook URL (Slack/Discord/Matrix):${NC} " prompt_default webhook_url "Webhook URL (Slack/Discord/Matrix)" ""
read -r webhook_url
BB_ALERTER_WEBHOOK="$webhook_url" BB_ALERTER_WEBHOOK="$webhook_url"
else else
BB_ALERTER_WEBHOOK="" BB_ALERTER_WEBHOOK=""
@@ -275,11 +292,16 @@ fi
section "Configuration Summary" section "Configuration Summary"
echo "Device ID: ${BOLD}${DEVICE_ID}${NC}" echo "Device ID: ${BOLD}${DEVICE_ID}${NC}"
echo "Hostname: ${BOLD}${BB_HOSTNAME}${NC}"
echo "Target: ${BOLD}/dev/${DEVICE}${NC}" echo "Target: ${BOLD}/dev/${DEVICE}${NC}"
echo "Image: ${BOLD}$(basename $IMAGE)${NC}" echo "Image: ${BOLD}$(basename $IMAGE)${NC}"
echo "" echo ""
if [[ "$ROOT_PASS_IS_AUTO" == true ]]; then
echo "Root Pass: ${BOLD}${RED}AUTO-GENERATED — RECORD THIS: ${DEFAULT_ROOT_PASS}${NC}"
else
echo "Root Pass: ${BOLD}[custom]${NC}"
fi
echo "WiFi: ${BOLD}$([ -n "$WIFI_SSID" ] && echo "$WIFI_SSID" || echo "disabled")${NC}" echo "WiFi: ${BOLD}$([ -n "$WIFI_SSID" ] && echo "$WIFI_SSID" || echo "disabled")${NC}"
echo "Root Pass: ${BOLD}[set]${NC}"
echo "SSH Mode: ${BOLD}${SSH_MODE}${NC}" echo "SSH Mode: ${BOLD}${SSH_MODE}${NC}"
echo "Auto-start: ${BOLD}${BB_MODE}${NC}" echo "Auto-start: ${BOLD}${BB_MODE}${NC}"
echo "VPN: ${BOLD}${BB_VPN}${NC}" echo "VPN: ${BOLD}${BB_VPN}${NC}"
@@ -398,7 +420,10 @@ chmod 600 "${SSH_DIR}/authorized_keys"
info "SSH authorized_keys configured" info "SSH authorized_keys configured"
# Hostname # Hostname
echo "orangepi" > "${MOUNT_POINT}/etc/hostname" step "Setting hostname..."
echo "$BB_HOSTNAME" > "${MOUNT_POINT}/etc/hostname"
sed -i "s/orangepi/$BB_HOSTNAME/g" "${MOUNT_POINT}/etc/hosts" 2>/dev/null || true
info "Hostname set to: $BB_HOSTNAME"
# Disable first-login wizard # Disable first-login wizard
rm -f "${MOUNT_POINT}/root/.not_logged_in_yet" rm -f "${MOUNT_POINT}/root/.not_logged_in_yet"