From 2b53da80d0f9bfdc1511bd917d0d6fdd28e39825 Mon Sep 17 00:00:00 2001 From: Cobra Date: Tue, 7 Apr 2026 14:17:01 -0400 Subject: [PATCH] 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 --- operator_setup.sh | 113 ++++++++++++++++++++++++++++------------------ 1 file changed, 69 insertions(+), 44 deletions(-) diff --git a/operator_setup.sh b/operator_setup.sh index a02a747..e7a4581 100755 --- a/operator_setup.sh +++ b/operator_setup.sh @@ -51,6 +51,19 @@ banner() { 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 # ══════════════════════════════════════════════════════════════════════════════ @@ -127,7 +140,12 @@ if [[ -z "$IMAGE" ]]; then IMAGE="${CACHE_DIR}/${IMAGE_FILENAME}" 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" else info "Image already cached: $IMAGE_FILENAME" @@ -150,16 +168,20 @@ section "Configuration Wizard" # WiFi (optional) step "WiFi Configuration" -echo -n -e "${CYAN}Configure WiFi? (y/n):${NC} " -read -r enable_wifi +prompt_default enable_wifi "Configure WiFi? (y/n)" "n" if [[ "$enable_wifi" =~ ^[yY]$ ]]; then - echo -n -e "${CYAN}WiFi SSID:${NC} " - read -r wifi_ssid - echo -n -e "${CYAN}WiFi Passphrase:${NC} " - read -s -r wifi_pass; echo - echo -n -e "${CYAN}Confirm Passphrase:${NC} " - read -s -r wifi_pass2; echo - [[ "$wifi_pass" == "$wifi_pass2" ]] || error "Passphrases do not match" + prompt_default wifi_ssid "WiFi SSID" "" + while true; do + echo -n -e "${CYAN}WiFi Passphrase${NC}: " + read -s -r wifi_pass; echo + echo -n -e "${CYAN}Confirm Passphrase${NC}: " + read -s -r wifi_pass2; echo + if [[ "$wifi_pass" == "$wifi_pass2" ]]; then + break + else + warn "Passphrases do not match. Try again." + fi + done WIFI_SSID="$wifi_ssid" WIFI_PASS="$wifi_pass" unset wifi_pass wifi_pass2 @@ -170,33 +192,29 @@ fi # Root password (required) step "Root Password" -while true; do - echo -n -e "${CYAN}Root password:${NC} " - read -s -r root_pass; echo - echo -n -e "${CYAN}Confirm:${NC} " - read -s -r root_pass2; echo - if [[ "$root_pass" == "$root_pass2" && -n "$root_pass" ]]; then - ROOT_PASS="$root_pass" - unset root_pass root_pass2 - break - else - warn "Passwords do not match or empty. Try again." - fi -done +DEFAULT_ROOT_PASS=$(openssl rand -base64 16 | tr -d '=+/') +ROOT_PASS_IS_AUTO=false +echo -e "${YELLOW}Auto-generated password: ${BOLD}${DEFAULT_ROOT_PASS}${NC}" +prompt_default root_pass "Enter custom password or press Enter to use auto-generated" "" +if [[ -z "$root_pass" ]]; then + ROOT_PASS="$DEFAULT_ROOT_PASS" + ROOT_PASS_IS_AUTO=true +else + ROOT_PASS="$root_pass" +fi +unset root_pass # SSH Key step "SSH Key Configuration" echo " [1] Generate new keypair (stored in Infisical)" echo " [2] Use existing public key file" -echo -n -e "${CYAN}SSH option (1-2):${NC} " -read -r ssh_opt +prompt_default ssh_opt "SSH option (1-2)" "1" if [[ "$ssh_opt" == "1" ]]; then SSH_MODE="generate" elif [[ "$ssh_opt" == "2" ]]; then SSH_MODE="existing" - echo -n -e "${CYAN}Path to public key file:${NC} " - read -r ssh_pubkey_path + prompt_default ssh_pubkey_path "Path to public key file" "" [[ -f "$ssh_pubkey_path" ]] || error "File not found: $ssh_pubkey_path" SSH_PUBKEY=$(cat "$ssh_pubkey_path") else @@ -205,18 +223,22 @@ fi # Device ID step "Device ID" -echo -n -e "${CYAN}Device label (e.g. bb-01):${NC} " -read -r device_id -[[ -n "$device_id" ]] || error "Device ID cannot be empty" +DEFAULT_DEVICE_ID="bb-$(cat /proc/sys/kernel/random/uuid | cut -c1-8)" +prompt_default device_id "Device label (e.g. bb-a3f2c1)" "$DEFAULT_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 step "Auto-start Mode on Boot" echo " [1] Passive only (capture + analysis, no active offense)" echo " [2] Full autonomous (all modules)" echo " [3] Manual (operator SSHs in to start)" -echo -n -e "${CYAN}Select mode (1-3):${NC} " -read -r mode_opt +prompt_default mode_opt "Select mode (1-3)" "1" if [[ "$mode_opt" == "1" ]]; then BB_MODE="passive" @@ -233,8 +255,7 @@ step "VPN Tunnel" echo " [1] None" echo " [2] Tailscale" echo " [3] WireGuard" -echo -n -e "${CYAN}Select VPN (1-3):${NC} " -read -r vpn_opt +prompt_default vpn_opt "Select VPN (1-3)" "1" BB_VPN="none" TAILSCALE_KEY="" @@ -244,13 +265,11 @@ if [[ "$vpn_opt" == "1" ]]; then BB_VPN="none" elif [[ "$vpn_opt" == "2" ]]; then BB_VPN="tailscale" - echo -n -e "${CYAN}Tailscale auth key:${NC} " - read -r tailscale_key + prompt_default tailscale_key "Tailscale auth key" "" TAILSCALE_KEY="$tailscale_key" elif [[ "$vpn_opt" == "3" ]]; then BB_VPN="wireguard" - echo -n -e "${CYAN}Path to WireGuard config (wg0.conf):${NC} " - read -r wg_config_path + prompt_default wg_config_path "Path to WireGuard config (wg0.conf)" "" [[ -f "$wg_config_path" ]] || error "File not found: $wg_config_path" WG_CONFIG=$(cat "$wg_config_path") else @@ -259,11 +278,9 @@ fi # Network alerter webhook step "Network Alerter" -echo -n -e "${CYAN}Enable alerter webhook? (y/n):${NC} " -read -r enable_alerter +prompt_default enable_alerter "Enable alerter webhook? (y/n)" "n" if [[ "$enable_alerter" =~ ^[yY]$ ]]; then - echo -n -e "${CYAN}Webhook URL (Slack/Discord/Matrix):${NC} " - read -r webhook_url + prompt_default webhook_url "Webhook URL (Slack/Discord/Matrix)" "" BB_ALERTER_WEBHOOK="$webhook_url" else BB_ALERTER_WEBHOOK="" @@ -275,11 +292,16 @@ fi section "Configuration Summary" echo "Device ID: ${BOLD}${DEVICE_ID}${NC}" +echo "Hostname: ${BOLD}${BB_HOSTNAME}${NC}" echo "Target: ${BOLD}/dev/${DEVICE}${NC}" echo "Image: ${BOLD}$(basename $IMAGE)${NC}" 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 "Root Pass: ${BOLD}[set]${NC}" echo "SSH Mode: ${BOLD}${SSH_MODE}${NC}" echo "Auto-start: ${BOLD}${BB_MODE}${NC}" echo "VPN: ${BOLD}${BB_VPN}${NC}" @@ -398,7 +420,10 @@ chmod 600 "${SSH_DIR}/authorized_keys" info "SSH authorized_keys configured" # 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 rm -f "${MOUNT_POINT}/root/.not_logged_in_yet"