Public Access
bd5f676e0a
Platform: moko-platform CI / Gate 2: Unit Tests (8.1) (push) Has been cancelled
Platform: moko-platform CI / Gate 2: Unit Tests (8.2) (push) Has been cancelled
Platform: moko-platform CI / Gate 2: Unit Tests (8.3) (push) Has been cancelled
Platform: moko-platform CI / Gate 3: Self-Health Check (push) Has been cancelled
Platform: moko-platform CI / Gate 4: Governance (push) Has been cancelled
Platform: moko-platform CI / Gate 5: Template Integrity (push) Has been cancelled
Platform: moko-platform CI / CI Summary (push) Has been cancelled
Generic: Repo Health / Scripts governance (push) Has been cancelled
Generic: Repo Health / Repository health (push) Has been cancelled
Generic: Repo Health / Report Issues (push) Has been cancelled
Generic: Repo Health / Site Health (push) Has been cancelled
Generic: Repo Health / Access control (push) Has been cancelled
Platform: moko-platform CI / Gate 1: Code Quality (push) Has been cancelled
# Conflicts: # cli/manifest_licensing.php
555 lines
18 KiB
Bash
555 lines
18 KiB
Bash
#!/bin/bash
|
|
# Interactive menu library for ssh-manager CLI
|
|
|
|
# Display main menu
|
|
show_main_menu() {
|
|
clear
|
|
print_header "SSH Manager CLI v$VERSION"
|
|
echo
|
|
echo -e " ${CYAN}1)${NC} ${SERVER} Server Management"
|
|
echo " Add, list, test, and manage SSH servers"
|
|
echo
|
|
echo -e " ${CYAN}2)${NC} ${SESSION} Quick Connect"
|
|
echo " Connect to a server via SSH"
|
|
echo
|
|
echo -e " ${CYAN}3)${NC} ${SYNC} File Synchronization"
|
|
echo " Push/pull files with rsync"
|
|
echo
|
|
echo -e " ${CYAN}4)${NC} ${TUNNEL} SSH Tunnels"
|
|
echo " Create and manage SSH tunnels"
|
|
echo
|
|
echo -e " ${CYAN}5)${NC} ${MONITOR} System Monitoring"
|
|
echo " Monitor server resources"
|
|
echo
|
|
echo -e " ${CYAN}6)${NC} ${ROCKET} Execute Commands"
|
|
echo " Run commands on servers"
|
|
echo
|
|
echo -e " ${CYAN}7)${NC} ${GEAR} Configuration"
|
|
echo " Edit settings and preferences"
|
|
echo
|
|
echo -e " ${CYAN}8)${NC} ${INFO} Help & Documentation"
|
|
echo " View help and examples"
|
|
echo
|
|
echo -e " ${CYAN}0)${NC} Exit"
|
|
echo
|
|
echo -e "${GRAY}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
|
|
echo -n "Choose an option [0-8]: "
|
|
}
|
|
|
|
# Server management submenu
|
|
show_server_menu() {
|
|
clear
|
|
print_header "Server Management"
|
|
echo
|
|
echo -e " ${CYAN}1)${NC} ${CHECK} Add New Server"
|
|
echo " Configure a new SSH server"
|
|
echo
|
|
echo -e " ${CYAN}2)${NC} ${CLIPBOARD} List All Servers"
|
|
echo " Show configured servers"
|
|
echo
|
|
echo -e " ${CYAN}3)${NC} ${WRENCH} Test Connection"
|
|
echo " Test server connectivity"
|
|
echo
|
|
echo -e " ${CYAN}4)${NC} ${INFO} Show Server Details"
|
|
echo " Display server configuration"
|
|
echo
|
|
echo -e " ${CYAN}5)${NC} ${PENCIL} Edit Server"
|
|
echo " Modify server settings"
|
|
echo
|
|
echo -e " ${CYAN}6)${NC} ${CROSS} Remove Server"
|
|
echo " Delete server configuration"
|
|
echo
|
|
echo -e " ${CYAN}7)${NC} ${NOTE} Edit Config File"
|
|
echo " Directly edit .env file"
|
|
echo
|
|
echo -e " ${CYAN}0)${NC} ← Back to Main Menu"
|
|
echo
|
|
echo -e "${GRAY}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
|
|
echo -n "Choose an option [0-7]: "
|
|
}
|
|
|
|
# Enhanced server add wizard
|
|
wizard_add_server() {
|
|
clear
|
|
print_header "Add New SSH Server - Setup Wizard"
|
|
echo
|
|
print_info "This wizard will guide you through adding a new SSH server."
|
|
print_info "Press Ctrl+C at any time to cancel."
|
|
echo
|
|
|
|
# Step 1: Server name
|
|
print_subheader "Step 1: Server Identification"
|
|
echo "Choose a short, memorable name for this server."
|
|
echo "Letters, digits and underscore only — no hyphens (POSIX env var rule)."
|
|
echo "Examples: prod1, web_server, database, staging"
|
|
echo
|
|
|
|
local server_name
|
|
while true; do
|
|
prompt_input "Server name" "" "server_name"
|
|
if validate_server_name "$server_name"; then
|
|
# Check if already exists
|
|
if get_server_config "$server_name" "HOST" >/dev/null 2>&1; then
|
|
print_error "Server '$server_name' already exists!"
|
|
if prompt_yes_no "Choose a different name?" "y"; then
|
|
continue
|
|
else
|
|
return 1
|
|
fi
|
|
fi
|
|
break
|
|
fi
|
|
done
|
|
|
|
# Step 2: Connection details
|
|
echo
|
|
print_subheader "Step 2: Connection Details"
|
|
|
|
local host
|
|
echo "Enter the server's hostname or IP address."
|
|
echo "Examples: 192.168.1.100, example.com, server.local"
|
|
prompt_input "Host/IP" "" "host"
|
|
|
|
local user
|
|
echo
|
|
echo "Enter the username for SSH connection."
|
|
echo "Common choices: root, ubuntu, admin, deploy"
|
|
prompt_input "Username" "${USER}" "user"
|
|
|
|
local port
|
|
echo
|
|
echo "Enter the SSH port (standard is 22)."
|
|
prompt_input "SSH Port" "22" "port"
|
|
|
|
# Step 3: Authentication
|
|
echo
|
|
print_subheader "Step 3: Authentication Method"
|
|
echo "How do you want to authenticate?"
|
|
echo
|
|
echo -e " ${CYAN}1)${NC} ${KEY} SSH Key (Recommended)"
|
|
echo " More secure, no password needed"
|
|
echo
|
|
echo -e " ${CYAN}2)${NC} ${LOCK} Password"
|
|
echo " Less secure, password required each time"
|
|
echo
|
|
read -p "Choose [1-2]: " auth_choice
|
|
|
|
local auth_type auth_value
|
|
case "$auth_choice" in
|
|
2)
|
|
auth_type="password"
|
|
echo
|
|
print_warning "Password authentication is less secure than SSH keys."
|
|
prompt_password "Enter password" "auth_value"
|
|
;;
|
|
*)
|
|
auth_type="key"
|
|
echo
|
|
echo "Enter the path to your SSH private key."
|
|
echo "Common locations:"
|
|
echo " • ~/.ssh/id_rsa (default RSA key)"
|
|
echo " • ~/.ssh/id_ed25519 (modern ED25519 key)"
|
|
echo " • ~/.ssh/custom_key (custom key)"
|
|
prompt_input "SSH key path" "$HOME/.ssh/id_rsa" "auth_value"
|
|
auth_value="${auth_value/#\~/$HOME}"
|
|
|
|
# Check if key exists
|
|
if [ ! -f "$auth_value" ]; then
|
|
print_warning "Key file not found: $auth_value"
|
|
if ! prompt_yes_no "Continue anyway?" "n"; then
|
|
return 1
|
|
fi
|
|
fi
|
|
;;
|
|
esac
|
|
|
|
# Step 4: Optional settings
|
|
echo
|
|
print_subheader "Step 4: Optional Settings"
|
|
|
|
local description
|
|
echo "Add a description to help identify this server (optional)."
|
|
echo "Example: Production web server, Database backup, Test environment"
|
|
prompt_input "Description" "" "description"
|
|
|
|
local default_dir
|
|
echo
|
|
echo "Set a default directory for this server (optional)."
|
|
echo "Example: /var/www/html, /home/user/app, /opt/services"
|
|
prompt_input "Default directory" "" "default_dir"
|
|
|
|
# Step 5: Review
|
|
echo
|
|
print_subheader "Step 5: Review Configuration"
|
|
echo
|
|
print_table_row "Name:" "$server_name"
|
|
print_table_row "Host:" "$host"
|
|
print_table_row "User:" "$user"
|
|
print_table_row "Port:" "$port"
|
|
print_table_row "Auth:" "$auth_type"
|
|
if [ "$auth_type" = "key" ]; then
|
|
print_table_row "Key:" "$auth_value"
|
|
else
|
|
print_table_row "Password:" "********"
|
|
fi
|
|
if [ -n "$description" ]; then
|
|
print_table_row "Description:" "$description"
|
|
fi
|
|
if [ -n "$default_dir" ]; then
|
|
print_table_row "Default Dir:" "$default_dir"
|
|
fi
|
|
|
|
echo
|
|
if prompt_yes_no "Save this configuration?" "y"; then
|
|
# Save to .env
|
|
add_server_to_env "$server_name" "$host" "$user" "$auth_type" "$auth_value" "$port" "$description"
|
|
|
|
# Add default directory if specified
|
|
if [ -n "$default_dir" ]; then
|
|
local name_upper="$(echo "$server_name" | tr '[:lower:]' '[:upper:]')"
|
|
echo "SSH_SERVER_${name_upper}_DEFAULT_DIR=$default_dir" >> "$SSH_MANAGER_ENV"
|
|
fi
|
|
|
|
echo
|
|
print_success "Server '$server_name' added successfully!"
|
|
|
|
echo
|
|
if prompt_yes_no "Test connection now?" "y"; then
|
|
echo
|
|
test_ssh_connection "$server_name"
|
|
fi
|
|
|
|
echo
|
|
print_info "Quick commands for '$server_name':"
|
|
echo " • Connect: ssh-manager ssh $server_name"
|
|
echo " • Test: ssh-manager server test $server_name"
|
|
echo " • Execute: ssh-manager exec $server_name \"command\""
|
|
|
|
echo
|
|
read -p "Press Enter to continue..."
|
|
else
|
|
print_info "Configuration cancelled"
|
|
fi
|
|
}
|
|
|
|
# Edit server wizard
|
|
wizard_edit_server() {
|
|
# Select server to edit
|
|
if ! select_server_menu "Select Server to Edit"; then
|
|
return 1
|
|
fi
|
|
|
|
local server_name="$SELECTED_SERVER"
|
|
|
|
# Load existing configuration
|
|
local current_host=$(get_server_config "$server_name" "HOST")
|
|
local current_user=$(get_server_config "$server_name" "USER")
|
|
local current_port=$(get_server_config "$server_name" "PORT")
|
|
local current_keypath=$(get_server_config "$server_name" "KEYPATH")
|
|
local current_password=$(get_server_config "$server_name" "PASSWORD")
|
|
local current_description=$(get_server_config "$server_name" "DESCRIPTION")
|
|
local current_default_dir=$(get_server_config "$server_name" "DEFAULT_DIR")
|
|
|
|
current_port=${current_port:-22}
|
|
|
|
# Determine current auth type
|
|
local current_auth_type="key"
|
|
if [ -n "$current_password" ]; then
|
|
current_auth_type="password"
|
|
fi
|
|
|
|
clear
|
|
print_header "Edit Server - $server_name"
|
|
print_info "Press Enter to keep current value, or type new value"
|
|
echo
|
|
|
|
# Step 1: Connection Details
|
|
print_subheader "Step 1: Connection Details"
|
|
echo "----------------------------------------"
|
|
|
|
local host
|
|
prompt_input "Host/IP" "$current_host" "host"
|
|
|
|
local user
|
|
prompt_input "Username" "$current_user" "user"
|
|
|
|
local port
|
|
prompt_input "Port" "$current_port" "port"
|
|
|
|
# Step 2: Authentication Method
|
|
echo
|
|
print_subheader "Step 2: Authentication Method"
|
|
echo "----------------------------------------"
|
|
echo "Current method: $current_auth_type"
|
|
echo
|
|
echo " 1) 🔑 SSH Key (Recommended)"
|
|
echo " More secure, no password needed"
|
|
echo
|
|
echo " 2) 🔒 Password"
|
|
echo " Less secure, password required each time"
|
|
echo
|
|
read -p "Choose [1-2] or Enter to keep current: " auth_choice
|
|
|
|
local auth_type auth_value
|
|
if [ -z "$auth_choice" ]; then
|
|
# Keep current auth method
|
|
auth_type="$current_auth_type"
|
|
if [ "$auth_type" = "password" ]; then
|
|
auth_value="$current_password"
|
|
else
|
|
auth_value="$current_keypath"
|
|
fi
|
|
else
|
|
case "$auth_choice" in
|
|
2)
|
|
auth_type="password"
|
|
prompt_password "Password" "auth_value"
|
|
;;
|
|
*)
|
|
auth_type="key"
|
|
prompt_input "SSH key path" "${current_keypath:-$HOME/.ssh/id_rsa}" "auth_value"
|
|
# Expand ~ to home directory
|
|
auth_value="${auth_value/#\~/$HOME}"
|
|
;;
|
|
esac
|
|
fi
|
|
|
|
# Step 3: Optional Settings
|
|
echo
|
|
print_subheader "Step 3: Optional Settings"
|
|
echo "----------------------------------------"
|
|
|
|
local description
|
|
prompt_input "Description (optional)" "$current_description" "description"
|
|
|
|
local default_dir
|
|
prompt_input "Default directory (optional)" "$current_default_dir" "default_dir"
|
|
|
|
# Show summary
|
|
echo
|
|
print_subheader "Configuration Summary"
|
|
print_table_row "Name:" "$server_name"
|
|
print_table_row "Host:" "$host"
|
|
print_table_row "User:" "$user"
|
|
print_table_row "Port:" "$port"
|
|
print_table_row "Auth:" "$auth_type"
|
|
if [ "$auth_type" = "key" ]; then
|
|
print_table_row "Key:" "$auth_value"
|
|
fi
|
|
if [ -n "$description" ]; then
|
|
print_table_row "Description:" "$description"
|
|
fi
|
|
if [ -n "$default_dir" ]; then
|
|
print_table_row "Default Dir:" "$default_dir"
|
|
fi
|
|
|
|
echo
|
|
if prompt_yes_no "Save changes?" "y"; then
|
|
update_server_in_env "$server_name" "$host" "$user" "$auth_type" "$auth_value" "$port" "$description" "$default_dir"
|
|
|
|
echo
|
|
if prompt_yes_no "Test connection now?" "y"; then
|
|
test_ssh_connection "$server_name"
|
|
fi
|
|
else
|
|
print_info "Changes cancelled"
|
|
fi
|
|
}
|
|
|
|
# Server selection menu
|
|
select_server_menu() {
|
|
local prompt_text="${1:-Select a server}"
|
|
local servers=($(load_servers))
|
|
|
|
if [ ${#servers[@]} -eq 0 ]; then
|
|
print_warning "No servers configured"
|
|
print_info "Use 'Add New Server' to configure one"
|
|
read -p "Press Enter to continue..."
|
|
return 1
|
|
fi
|
|
|
|
clear
|
|
print_header "$prompt_text"
|
|
echo
|
|
|
|
local i=1
|
|
for server in "${servers[@]}"; do
|
|
local host=$(get_server_config "$server" "HOST")
|
|
local user=$(get_server_config "$server" "USER")
|
|
local desc=$(get_server_config "$server" "DESCRIPTION")
|
|
|
|
echo -e " ${CYAN}$i)${NC} ${SERVER}$server"
|
|
echo " $user@$host"
|
|
if [ -n "$desc" ]; then
|
|
echo " ${GRAY}$desc${NC}"
|
|
fi
|
|
echo
|
|
((i++))
|
|
done
|
|
|
|
echo -e " ${CYAN}0)${NC} Cancel"
|
|
echo
|
|
echo -e "${GRAY}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
|
|
echo -n "Choose server [0-${#servers[@]}]: "
|
|
|
|
read choice
|
|
if [[ "$choice" =~ ^[0-9]+$ ]] && [ "$choice" -ge 1 ] && [ "$choice" -le ${#servers[@]} ]; then
|
|
selected_server="${servers[$((choice-1))]}"
|
|
return 0
|
|
else
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
# File sync menu
|
|
show_sync_menu() {
|
|
clear
|
|
print_header "File Synchronization"
|
|
|
|
if ! select_server_menu "Select server for file sync"; then
|
|
return
|
|
fi
|
|
|
|
local server="$selected_server"
|
|
|
|
echo
|
|
print_subheader "Sync Direction"
|
|
echo -e " ${CYAN}1)${NC} ${ARROW} Push (Local → Remote)"
|
|
echo " Upload files to $server"
|
|
echo
|
|
echo -e " ${CYAN}2)${NC} ${ARROW} Pull (Remote → Local)"
|
|
echo " Download files from $server"
|
|
echo
|
|
echo -e " ${CYAN}0)${NC} Cancel"
|
|
echo
|
|
read -p "Choose direction [0-2]: " direction
|
|
|
|
case "$direction" in
|
|
1)
|
|
echo
|
|
local source dest
|
|
prompt_input "Local source path" "." "source"
|
|
prompt_input "Remote destination path" "/tmp/" "dest"
|
|
|
|
echo
|
|
if prompt_yes_no "Dry run first?" "y"; then
|
|
cmd_sync push "$server" "$source" "$dest" --dry-run
|
|
echo
|
|
if prompt_yes_no "Proceed with actual sync?" "y"; then
|
|
cmd_sync push "$server" "$source" "$dest"
|
|
fi
|
|
else
|
|
cmd_sync push "$server" "$source" "$dest"
|
|
fi
|
|
;;
|
|
2)
|
|
echo
|
|
local source dest
|
|
prompt_input "Remote source path" "/tmp/" "source"
|
|
prompt_input "Local destination path" "." "dest"
|
|
|
|
echo
|
|
if prompt_yes_no "Dry run first?" "y"; then
|
|
cmd_sync pull "$server" "$source" "$dest" --dry-run
|
|
echo
|
|
if prompt_yes_no "Proceed with actual sync?" "y"; then
|
|
cmd_sync pull "$server" "$source" "$dest"
|
|
fi
|
|
else
|
|
cmd_sync pull "$server" "$source" "$dest"
|
|
fi
|
|
;;
|
|
esac
|
|
|
|
echo
|
|
read -p "Press Enter to continue..."
|
|
}
|
|
|
|
# Tunnel creation wizard
|
|
wizard_create_tunnel() {
|
|
clear
|
|
print_header "SSH Tunnel Creation Wizard"
|
|
|
|
if ! select_server_menu "Select server for tunnel"; then
|
|
return
|
|
fi
|
|
|
|
local server="$selected_server"
|
|
|
|
echo
|
|
print_subheader "Tunnel Type"
|
|
echo -e " ${CYAN}1)${NC} Local Port Forwarding"
|
|
echo " Access remote service through local port"
|
|
echo " Example: Access remote MySQL on local port 3307"
|
|
echo
|
|
echo -e " ${CYAN}2)${NC} Remote Port Forwarding"
|
|
echo " Expose local service to remote server"
|
|
echo " Example: Let remote access your local web server"
|
|
echo
|
|
echo -e " ${CYAN}3)${NC} Dynamic (SOCKS Proxy)"
|
|
echo " Create SOCKS5 proxy for secure browsing"
|
|
echo " Example: Route browser through SSH server"
|
|
echo
|
|
echo -e " ${CYAN}0)${NC} Cancel"
|
|
echo
|
|
read -p "Choose type [0-3]: " tunnel_type
|
|
|
|
case "$tunnel_type" in
|
|
1)
|
|
echo
|
|
print_info "Local Port Forwarding Setup"
|
|
echo "Access a remote service as if it were local"
|
|
echo
|
|
local local_port remote_host remote_port
|
|
prompt_input "Local port to listen on" "8080" "local_port"
|
|
prompt_input "Remote host (usually localhost)" "localhost" "remote_host"
|
|
prompt_input "Remote port to forward to" "80" "remote_port"
|
|
|
|
echo
|
|
print_info "Creating tunnel: localhost:$local_port → $server → $remote_host:$remote_port"
|
|
cmd_tunnel create "$server" local "$local_port:$remote_host:$remote_port"
|
|
|
|
echo
|
|
print_success "Tunnel created! Access the service at: http://localhost:$local_port"
|
|
;;
|
|
2)
|
|
echo
|
|
print_info "Remote Port Forwarding Setup"
|
|
echo "Expose your local service to the remote server"
|
|
echo
|
|
local remote_port local_host local_port
|
|
prompt_input "Remote port to listen on" "8080" "remote_port"
|
|
prompt_input "Local host (usually localhost)" "localhost" "local_host"
|
|
prompt_input "Local port to forward" "3000" "local_port"
|
|
|
|
echo
|
|
print_info "Creating tunnel: $server:$remote_port → local → $local_host:$local_port"
|
|
cmd_tunnel create "$server" remote "$remote_port:$local_host:$local_port"
|
|
|
|
echo
|
|
print_success "Tunnel created! Remote can access at: $server:$remote_port"
|
|
;;
|
|
3)
|
|
echo
|
|
print_info "SOCKS Proxy Setup"
|
|
echo "Route all traffic through SSH server"
|
|
echo
|
|
local socks_port
|
|
prompt_input "Local SOCKS port" "1080" "socks_port"
|
|
|
|
echo
|
|
print_info "Creating SOCKS5 proxy on port $socks_port"
|
|
cmd_tunnel create "$server" dynamic "$socks_port"
|
|
|
|
echo
|
|
print_success "SOCKS proxy created!"
|
|
print_info "Configure your browser/app to use:"
|
|
echo " • SOCKS Host: localhost"
|
|
echo " • SOCKS Port: $socks_port"
|
|
echo " • SOCKS Type: SOCKS5"
|
|
;;
|
|
esac
|
|
|
|
echo
|
|
read -p "Press Enter to continue..."
|
|
} |