See More

#!/bin/sh #================================================================# # GitSSH SETUP MODULE # Interactive SSH key setup for GitHub and GitLab #================================================================# # Configuration SSH_CONFIG_FILE="$HOME/.ssh/config" SSH_DIR="$HOME/.ssh" #================================================================# # MAIN SETUP COMMANDS #================================================================# # Setup GitHub SSH key setup_github() { if ! _check_setup_dependencies; then return 1 fi printf "\n" _print_color blue "==========================================" printf "\n" _print_color blue " GitHub SSH Key Setup Wizard" printf "\n" _print_color blue "==========================================" printf "\n\n" _print_info "This wizard will help you set up SSH authentication for GitHub" printf "We'll guide you through each step with explanations.\n\n" # Step 1: Gather user information if ! _gather_github_info; then return 1 fi # Step 2: Check existing SSH setup if ! _check_existing_ssh_setup "github"; then return 1 fi # Step 3: Generate SSH key if needed if [ "$GENERATE_NEW_KEY" = "true" ]; then if ! _generate_ssh_key "github"; then return 1 fi fi # Step 4: Configure SSH if ! _setup_ssh_config "github"; then return 1 fi # Step 5: Add to SSH agent if ! _add_to_ssh_agent "github"; then return 1 fi # Step 6: Display public key and guide user if ! _guide_github_key_addition; then return 1 fi # Step 7: Test connection if ! _test_github_connection; then return 1 fi # Step 8: Integration with GitSSH Session Manager _integrate_with_session_manager "github" _print_success "GitHub SSH setup completed successfully!" printf "\n" _print_info "You can now use the GitSSH Session Manager:" printf " • Run 'gitssh session set' to configure your identity for repositories\n" printf " • Use 'gitssh clone', 'gitssh push', etc. for enhanced Git operations\n" printf " • Run 'gitssh remote convert' to convert HTTPS repositories to SSH\n" printf "\n" } # Setup GitLab SSH key setup_gitlab() { if ! _check_setup_dependencies; then return 1 fi printf "\n" _print_color blue "==========================================" printf "\n" _print_color blue " GitLab SSH Key Setup Wizard" printf "\n" _print_color blue "==========================================" printf "\n\n" _print_info "This wizard will help you set up SSH authentication for GitLab" printf "We'll guide you through each step with explanations.\n\n" # Step 1: Gather user information if ! _gather_gitlab_info; then return 1 fi # Step 2: Check existing SSH setup if ! _check_existing_ssh_setup "gitlab"; then return 1 fi # Step 3: Generate SSH key if needed if [ "$GENERATE_NEW_KEY" = "true" ]; then if ! _generate_ssh_key "gitlab"; then return 1 fi fi # Step 4: Configure SSH if ! _setup_ssh_config "gitlab"; then return 1 fi # Step 5: Add to SSH agent if ! _add_to_ssh_agent "gitlab"; then return 1 fi # Step 6: Display public key and guide user if ! _guide_gitlab_key_addition; then return 1 fi # Step 7: Test connection if ! _test_gitlab_connection; then return 1 fi # Step 8: Integration with GitSSH Session Manager _integrate_with_session_manager "gitlab" _print_success "GitLab SSH setup completed successfully!" printf "\n" _print_info "You can now use the GitSSH Session Manager:" printf " • Run 'gitssh session set' to configure your identity for repositories\n" printf " • Use 'gitssh clone', 'gitssh push', etc. for enhanced Git operations\n" printf " • Run 'gitssh remote convert' to convert HTTPS repositories to SSH\n" printf "\n" } # Show SSH setup status ssh_status() { printf "\n" _print_color blue "==========================================" printf "\n" _print_color blue " SSH Setup Status" printf "\n" _print_color blue "==========================================" printf "\n\n" # Check SSH directory printf "SSH Directory Status:\n" if [ -d "$SSH_DIR" ]; then _print_success "SSH directory exists: $SSH_DIR" printf " Permissions: %s\n" "$(ls -ld "$SSH_DIR" | awk '{print $1}')" else _print_warning "SSH directory not found: $SSH_DIR" fi printf "\n" # Check SSH keys printf "SSH Keys:\n" key_count=0 for key_type in ed25519 rsa ecdsa dsa; do if [ -f "$SSH_DIR/id_$key_type" ]; then _print_success "Found $key_type key: id_$key_type" key_count=$((key_count + 1)) fi done # Check for custom GitHub/GitLab keys for service in github gitlab; do for key_type in ed25519 rsa; do if [ -f "$SSH_DIR/${service}_$key_type" ]; then _print_success "Found $service $key_type key: ${service}_$key_type" key_count=$((key_count + 1)) fi done done if [ "$key_count" -eq 0 ]; then _print_warning "No SSH keys found" printf " Run 'gitssh setup github' or 'gitssh setup gitlab' to create keys\n" fi printf "\n" # Check SSH agent printf "SSH Agent Status:\n" if _is_ssh_agent_running; then _print_success "SSH Agent is running" printf "Loaded keys:\n" _get_loaded_ssh_keys | sed 's/^/ /' else _print_warning "SSH Agent not running" printf " Start with: eval \$(ssh-agent -s)\n" fi printf "\n" # Check SSH config printf "SSH Configuration:\n" if [ -f "$SSH_CONFIG_FILE" ]; then _print_success "SSH config exists: $SSH_CONFIG_FILE" # Check for GitHub/GitLab hosts github_hosts=$(grep '^Host github-' "$SSH_CONFIG_FILE" 2>/dev/null | wc -l) gitlab_hosts=$(grep '^Host gitlab-' "$SSH_CONFIG_FILE" 2>/dev/null | wc -l) printf " GitHub hosts configured: %s\n" "$github_hosts" printf " GitLab hosts configured: %s\n" "$gitlab_hosts" else _print_warning "SSH config not found" printf " Will be created during setup\n" fi printf "\n" # Test connections printf "Connection Tests:\n" _test_service_connections printf "\n" _print_color blue "==========================================" printf "\n" } # Test SSH ssh_test() { if [ $# -eq 0 ]; then printf "Usage: gitssh ssh test [timeout]\n" printf "Example: gitssh ssh test github-work 10\n" return 1 fi hostname="$1" timeout="${2:-5}" printf "Testing SSH connection to %s...\n" "$hostname" if _test_ssh_connection "$hostname" "$timeout"; then _print_success "SSH connection to $hostname successful!" # Try to get more details test_output=$(ssh -o ConnectTimeout="$timeout" -T "git@$hostname" 2>&1) if printf "%s" "$test_output" | grep -q "successfully authenticated\|Welcome to GitLab"; then printf "Authentication details:\n" printf "%s\n" "$test_output" | head -3 fi else _print_error "SSH connection to $hostname failed" printf "Troubleshooting:\n" printf " 1. Check if SSH host exists: grep 'Host %s' ~/.ssh/config\n" "$hostname" printf " 2. Test SSH agent: ssh-add -l\n" printf " 3. Run diagnostics: gitssh ssh doctor\n" return 1 fi } #================================================================# # INFORMATION GATHERING #================================================================# # Gather GitHub user information _gather_github_info() { printf "Step 1: GitHub Account Information\n" printf "===================================\n" printf "GitHub username: " read -r GITHUB_USERNAME if _is_empty "$GITHUB_USERNAME"; then _print_error "GitHub username cannot be empty" return 1 fi if ! _validate_username "$GITHUB_USERNAME"; then _print_error "Invalid GitHub username format" return 1 fi printf "Email address (for Git commits): " read -r USER_EMAIL if _is_empty "$USER_EMAIL"; then _print_error "Email address cannot be empty" return 1 fi if ! _validate_email "$USER_EMAIL"; then _print_error "Invalid email format" return 1 fi printf "Display name [%s]: " "$GITHUB_USERNAME" read -r USER_NAME USER_NAME=${USER_NAME:-$GITHUB_USERNAME} USER_NAME=$(_trim "$USER_NAME") # Set SSH host name SSH_HOST="github-$GITHUB_USERNAME" KEY_COMMENT="$USER_EMAIL" printf "\n" _print_success "Account information collected:" printf " Username: %s\n" "$GITHUB_USERNAME" printf " Name: %s\n" "$USER_NAME" printf " Email: %s\n" "$USER_EMAIL" printf " SSH Host: %s\n" "$SSH_HOST" printf "\n" return 0 } # Gather GitLab user information _gather_gitlab_info() { printf "Step 1: GitLab Account Information\n" printf "===================================\n" printf "GitLab instance URL [gitlab.com]: " read -r GITLAB_URL GITLAB_URL=${GITLAB_URL:-gitlab.com} GITLAB_URL=$(_trim "$GITLAB_URL") # Remove protocol if provided GITLAB_URL=$(printf "%s" "$GITLAB_URL" | sed 's|^https\?://||') printf "GitLab username: " read -r GITLAB_USERNAME if _is_empty "$GITLAB_USERNAME"; then _print_error "GitLab username cannot be empty" return 1 fi if ! _validate_username "$GITLAB_USERNAME"; then _print_error "Invalid GitLab username format" return 1 fi printf "Email address (for Git commits): " read -r USER_EMAIL if _is_empty "$USER_EMAIL"; then _print_error "Email address cannot be empty" return 1 fi if ! _validate_email "$USER_EMAIL"; then _print_error "Invalid email format" return 1 fi printf "Display name [%s]: " "$GITLAB_USERNAME" read -r USER_NAME USER_NAME=${USER_NAME:-$GITLAB_USERNAME} USER_NAME=$(_trim "$USER_NAME") # Set SSH host name if [ "$GITLAB_URL" = "gitlab.com" ]; then SSH_HOST="gitlab-$GITLAB_USERNAME" else # For custom GitLab instances, include domain sanitized_domain=$(printf "%s" "$GITLAB_URL" | sed 's/[^a-zA-Z0-9]/-/g') SSH_HOST="gitlab-$sanitized_domain-$GITLAB_USERNAME" fi KEY_COMMENT="$USER_EMAIL" printf "\n" _print_success "Account information collected:" printf " GitLab URL: %s\n" "$GITLAB_URL" printf " Username: %s\n" "$GITLAB_USERNAME" printf " Name: %s\n" "$USER_NAME" printf " Email: %s\n" "$USER_EMAIL" printf " SSH Host: %s\n" "$SSH_HOST" printf "\n" return 0 } #================================================================# # SSH KEY MANAGEMENT #================================================================# # Check existing SSH setup _check_existing_ssh_setup() { service="$1" # github or gitlab printf "Step 2: Checking Existing SSH Setup\n" printf "====================================\n" # Check SSH directory if [ ! -d "$SSH_DIR" ]; then printf "Creating SSH directory...\n" mkdir -p "$SSH_DIR" chmod 700 "$SSH_DIR" _print_success "Created $SSH_DIR with proper permissions" else _print_success "SSH directory exists: $SSH_DIR" fi # Check for existing keys existing_keys="" key_files="" # Check for service-specific keys first for key_type in ed25519 rsa; do key_name="${service}_${key_type}" if [ -f "$SSH_DIR/$key_name" ] && [ -f "$SSH_DIR/$key_name.pub" ]; then existing_keys="$existing_keys $key_name" key_files="$key_files $SSH_DIR/$key_name" fi done # Check for default keys for key_type in ed25519 rsa ecdsa dsa; do key_name="id_$key_type" if [ -f "$SSH_DIR/$key_name" ] && [ -f "$SSH_DIR/$key_name.pub" ]; then existing_keys="$existing_keys $key_name" key_files="$key_files $SSH_DIR/$key_name" fi done if [ -n "$existing_keys" ]; then _print_info "Found existing SSH keys:" for key in $existing_keys; do printf " • %s\n" "$key" done printf "\n" printf "Options:\n" printf " 1. Use existing key\n" printf " 2. Generate new key\n" printf " 3. Exit setup\n" printf "\n" while true; do printf "Choose option (1-3): " read -r choice case "$choice" in 1) GENERATE_NEW_KEY="false" if ! _select_existing_key; then return 1 fi break ;; 2) GENERATE_NEW_KEY="true" _generate_key_name "$service" break ;; 3) printf "Setup cancelled\n" return 1 ;; *) _print_warning "Invalid choice. Please enter 1, 2, or 3." ;; esac done else _print_info "No existing SSH keys found" GENERATE_NEW_KEY="true" _generate_key_name "$service" fi printf "\n" return 0 } # Select existing SSH key _select_existing_key() { printf "\nSelect SSH key to use:\n" i=1 key_list="" for key_type in ed25519 rsa ecdsa dsa; do for prefix in "${service}_" "id_"; do key_name="${prefix}${key_type}" if [ -f "$SSH_DIR/$key_name" ] && [ -f "$SSH_DIR/$key_name.pub" ]; then printf " %d. %s\n" "$i" "$key_name" key_list="$key_list $key_name" i=$((i + 1)) fi done done if [ "$i" -eq 1 ]; then _print_error "No valid key pairs found" return 1 fi while true; do printf "\nSelect key (1-%d): " "$((i-1))" read -r choice if [ "$choice" -ge 1 ] && [ "$choice" -le "$((i-1))" ] 2>/dev/null; then SELECTED_KEY=$(printf "%s" "$key_list" | awk "{print \$$choice}") KEY_PATH="$SSH_DIR/$SELECTED_KEY" _print_success "Selected: $SELECTED_KEY" break else _print_warning "Invalid choice" fi done return 0 } # Generate key name for new key _generate_key_name() { service="$1" # Use ed25519 as default for new keys (best practice) case "$service" in github) KEY_NAME="github_${GITHUB_USERNAME}_id_ed25519" ;; gitlab) if [ "$GITLAB_URL" = "gitlab.com" ]; then KEY_NAME="gitlab_${GITLAB_USERNAME}_id_ed25519" else sanitized_domain=$(printf "%s" "$GITLAB_URL" | sed 's/[^a-zA-Z0-9]/-/g') KEY_NAME="gitlab-${sanitized_domain}_id_ed25519" fi ;; esac KEY_PATH="$SSH_DIR/$KEY_NAME" _print_info "Will generate new key: $KEY_NAME" } # Generate SSH key with user guidance _generate_ssh_key() { service="$1" printf "Step 3: Generating SSH Key\n" printf "==========================\n" _print_info "About SSH Keys:" printf "SSH keys provide secure, passwordless authentication to Git services.\n" printf "We'll use Ed25519 encryption (recommended).\n\n" # Check if key already exists if [ -f "$KEY_PATH" ]; then _print_warning "Key file already exists: $KEY_PATH" printf "Overwrite existing key? (y/N): " read -r overwrite case "$overwrite" in [Yy]*) ;; *) _print_info "Using existing key" return 0 ;; esac fi printf "Generating SSH key...\n" printf "Key type: Ed25519 (recommended)\n" printf "Key file: %s\n" "$KEY_PATH" printf "Comment: %s\n\n" "$KEY_COMMENT" _print_info "About Passphrases:" printf "A passphrase adds extra security to your SSH key.\n" printf "Recommended: Use a strong passphrase\n" printf "Note: You can use ssh-agent to avoid entering it repeatedly\n\n" # Generate the key if ssh-keygen -t ed25519 -f "$KEY_PATH" -C "$KEY_COMMENT"; then _print_success "SSH key generated successfully!" # Set proper permissions chmod 600 "$KEY_PATH" chmod 644 "$KEY_PATH.pub" printf "\nKey details:\n" printf " Private key: %s (keep this secret!)\n" "$KEY_PATH" printf " Public key: %s (this will be added to $service)\n" "$KEY_PATH.pub" printf " Fingerprint: "gitssh ssh ssh-keygen -lf "$KEY_PATH.pub" 2>/dev/null | awk '{print $2}' else _print_error "Failed to generate SSH key" return 1 fi printf "\n" return 0 } # Setup SSH configuration _setup_ssh_config() { service="$1" printf "Step 4: Configuring SSH\n" printf "=======================\n" _print_info "About SSH Config:" printf "The SSH config file (~/.ssh/config) tells SSH how to connect to different hosts.\n" printf "This allows you to use custom hostnames like 'github-username'.\n\n" # Determine hostname and host entry case "$service" in github) REAL_HOSTNAME="github.com" HOST_ENTRY="Host $SSH_HOST HostName github.com User git IdentityFile $KEY_PATH IdentitiesOnly yes" ;; gitlab) REAL_HOSTNAME="$GITLAB_URL" HOST_ENTRY="Host $SSH_HOST HostName $GITLAB_URL User git IdentityFile $KEY_PATH IdentitiesOnly yes" ;; esac # Create SSH config if it doesn't exist if [ ! -f "$SSH_CONFIG_FILE" ]; then printf "Creating SSH config file...\n" touch "$SSH_CONFIG_FILE" chmod 600 "$SSH_CONFIG_FILE" _print_success "Created $SSH_CONFIG_FILE" fi # Check if host entry already exists if grep -q "^Host $SSH_HOST$" "$SSH_CONFIG_FILE"; then _print_warning "SSH host '$SSH_HOST' already exists in config" printf "Update the existing entry? (Y/n): " read -r update_config case "$update_config" in [Nn]*) _print_info "Keeping existing SSH config" return 0 ;; esac # Remove existing entry _remove_ssh_host_entry "$SSH_HOST" fi # Add new host entry printf "Adding SSH host configuration...\n" printf "\n# %s SSH configuration\n%s\n\n" "$service" "$HOST_ENTRY" >> "$SSH_CONFIG_FILE" _print_success "Added SSH configuration for $SSH_HOST" printf " You can now use: git@%s:username/repository.git\n" "$SSH_HOST" printf "\n" return 0 } # Add key to SSH agent _add_to_ssh_agent() { service="$1" printf "Step 5: Adding Key to SSH Agent\n" printf "================================\n" _print_info "About SSH Agent:" printf "SSH Agent manages your SSH keys and handles authentication.\n" printf "This allows you to enter your passphrase once per session.\n\n" # Check if SSH agent is running if ! _is_ssh_agent_running; then printf "Starting SSH agent...\n" eval "$(ssh-agent -s)" >/dev/null if _is_ssh_agent_running; then _print_success "SSH agent started" else _print_error "Failed to start SSH agent" return 1 fi else _print_success "SSH agent is already running" fi # Add key to agent printf "Adding SSH key to agent...\n" if ssh-add "$KEY_PATH"; then _print_success "SSH key added to agent successfully!" # Show loaded keys printf "\nCurrently loaded keys:\n" _get_loaded_ssh_keys | sed 's/^/ /' else _print_error "Failed to add SSH key to agent" return 1 fi printf "\n" return 0 } #================================================================# # SERVICE-SPECIFIC GUIDES #================================================================# # Guide user through GitHub key addition _guide_github_key_addition() { printf "Step 6: Adding Key to GitHub\n" printf "============================\n" _print_info "Now you need to add your public key to GitHub:" printf "\n" # Display the public key printf "Your public key (copy this entire text):\n" printf "%s\n" "$(cat "$KEY_PATH.pub")" printf "%s\n" "$(printf '=%.0s' {1..60})" printf "\n" _print_info "GitHub Setup Steps:" printf "1. Go to https://github.com/settings/keys\n" printf "2. Click 'New SSH key'\n" printf "3. Give it a title (e.g., 'My Laptop - %s')\n" "$(date '+%Y-%m-%d')" printf "4. Paste the public key above into the 'Key' field\n" printf "5. Click 'Add SSH key'\n\n" # Auto-copy to clipboard if possible if command -v xclip >/dev/null 2>&1; then cat "$KEY_PATH.pub" | xclip -selection clipboard _print_success "Public key copied to clipboard!" elif command -v pbcopy >/dev/null 2>&1; then cat "$KEY_PATH.pub" | pbcopy _print_success "Public key copied to clipboard!" elif command -v wl-copy >/dev/null 2>&1; then cat "$KEY_PATH.pub" | wl-copy _print_success "Public key copied to clipboard!" else _print_info "Tip: Select and copy the public key above" fi printf "Press Enter after adding the key to GitHub..." read -r _ return 0 } # Guide user through GitLab key addition _guide_gitlab_key_addition() { printf "Step 6: Adding Key to GitLab\n" printf "============================\n" _print_info "Now you need to add your public key to GitLab:" printf "\n" # Display the public key printf "Your public key (copy this entire text):\n" printf "%s\n" "$(cat "$KEY_PATH.pub")" printf "%s\n" "$(printf '=%.0s' {1..60})" printf "\n" _print_info "GitLab Setup Steps:" if [ "$GITLAB_URL" = "gitlab.com" ]; then printf "1. Go to https://gitlab.com/-/user_settings/ssh_keys\n" else printf "1. Go to https://%s/-/user_settings/ssh_keys\n" "$GITLAB_URL" fi printf "2. Paste the public key above into the 'Key' field\n" printf "3. Give it a title (e.g., 'My Laptop - %s')\n" "$(date '+%Y-%m-%d')" printf "4. Set an expiration date (optional but recommended)\n" printf "5. Click 'Add key'\n\n" # Auto-copy to clipboard if possible if command -v xclip >/dev/null 2>&1; then cat "$KEY_PATH.pub" | xclip -selection clipboard _print_success "Public key copied to clipboard!" elif command -v pbcopy >/dev/null 2>&1; then cat "$KEY_PATH.pub" | pbcopy _print_success "Public key copied to clipboard!" elif command -v wl-copy >/dev/null 2>&1; then cat "$KEY_PATH.pub" | wl-copy _print_success "Public key copied to clipboard!" else _print_info "Tip: Select and copy the public key above" fi printf "Press Enter after adding the key to GitLab..." read -r _ return 0 } #================================================================# # CONNECTION TESTING #================================================================# # Test GitHub connection _test_github_connection() { printf "Step 7: Testing GitHub Connection\n" printf "==================================\n" _print_info "Testing SSH connection to GitHub..." printf "This verifies that your key was added correctly.\n\n" printf "Testing connection to %s...\n" "$SSH_HOST" # Test with timeout and capture output test_output=$(ssh -o ConnectTimeout=10 -T "git@$SSH_HOST" 2>&1) test_result=$? if printf "%s" "$test_output" | grep -q "successfully authenticated"; then _print_success "SSH connection successful!" # Extract username from GitHub response github_user=$(printf "%s" "$test_output" | sed -n 's/.*Hi \([^!]*\)!.*/\1/p') if [ -n "$github_user" ]; then printf "Authenticated as GitHub user: %s\n" "$github_user" if [ "$github_user" != "$GITHUB_USERNAME" ]; then _print_warning "Username mismatch!" printf " Expected: %s\n" "$GITHUB_USERNAME" printf " Actual: %s\n" "$github_user" printf "This might indicate a key conflict or wrong account.\n" fi fi else _print_error "SSH connection failed" printf "Error output:\n%s\n\n" "$test_output" _print_info "Troubleshooting tips:" printf "1. Make sure you added the public key to the correct GitHub account\n" printf "2. Check that the key was pasted completely without extra spaces\n" printf "3. Verify your SSH agent is running: ssh-add -l\n" printf "4. Try adding the key to SSH agent again: ssh-add %s\n" "$KEY_PATH" printf "\nWould you like to try again? (y/N): " read -r retry case "$retry" in [Yy]*) return _test_github_connection ;; *) return 1 ;; esac fi printf "\n" return 0 } # Test GitLab connection _test_gitlab_connection() { printf "Step 7: Testing GitLab Connection\n" printf "==================================\n" _print_info "Testing SSH connection to GitLab..." printf "This verifies that your key was added correctly.\n\n" printf "Testing connection to %s...\n" "$SSH_HOST" # Test with timeout and capture output test_output=$(ssh -o ConnectTimeout=10 -T "git@$SSH_HOST" 2>&1) test_result=$? if printf "%s" "$test_output" | grep -q "Welcome to GitLab"; then _print_success "SSH connection successful!" # Extract username from GitLab response if available gitlab_user=$(printf "%s" "$test_output" | sed -n 's/.*Welcome to GitLab, @\([^!]*\)!.*/\1/p') if [ -n "$gitlab_user" ]; then printf "Authenticated as GitLab user: %s\n" "$gitlab_user" if [ "$gitlab_user" != "$GITLAB_USERNAME" ]; then _print_warning "Username mismatch!" printf " Expected: %s\n" "$GITLAB_USERNAME" printf " Actual: %s\n" "$gitlab_user" printf "This might indicate a key conflict or wrong account.\n" fi fi else _print_error "SSH connection failed" printf "Error output:\n%s\n\n" "$test_output" _print_info "Troubleshooting tips:" printf "1. Make sure you added the public key to the correct GitLab account\n" printf "2. Check that the key was pasted completely without extra spaces\n" printf "3. Verify your SSH agent is running: ssh-add -l\n" printf "4. Try adding the key to SSH agent again: ssh-add %s\n" "$KEY_PATH" printf "\nWould you like to try again? (y/N): " read -r retry case "$retry" in [Yy]*) return _test_gitlab_connection ;; *) return 1 ;; esac fi printf "\n" return 0 } #================================================================# # INTEGRATION FUNCTIONS #================================================================# # Integrate with GitSSH Session Manager _integrate_with_session_manager() { service="$1" printf "Step 8: Integration with GitSSH Session Manager\n" printf "================================================\n" _print_info "About GitSSH Session Manager:" printf "This tool helps you manage multiple Git identities and SSH keys.\n" printf "It automatically configures the right user for each repository.\n\n" # Check if GitSSH Session Manager is available if ! _check_dependencies 2>/dev/null; then _print_warning "GitSSH Session Manager not fully configured" printf "Run 'gitssh init' to complete the setup\n\n" return 0 fi # Add user to session manager if not exists case "$service" in github) username="$GITHUB_USERNAME" ;; gitlab) username="$GITLAB_USERNAME" ;; esac if ! _user_exists "$username" 2>/dev/null; then printf "Adding user to GitSSH Session Manager...\n" # Add user to config if _add_user_to_config "$username" "$USER_NAME" "$USER_EMAIL" "$SSH_HOST"; then _print_success "Added '$username' to session manager" else _print_warning "Failed to add user to session manager" printf "You can add manually later with 'gitssh user add'\n" fi else _print_success "User '$username' already exists in session manager" fi printf "\n" return 0 } #================================================================# # UTILITY FUNCTIONS #================================================================# # Check setup dependencies _check_setup_dependencies() { missing_deps="" # Check for required commands for cmd in ssh-keygen ssh-add ssh git; do if ! command -v "$cmd" >/dev/null 2>&1; then missing_deps="$missing_deps $cmd" fi done if [ -n "$missing_deps" ]; then _print_error "Missing required dependencies:$missing_deps" printf "Please install them first:\n" os=$(_detect_os) case "$os" in linux) printf " Ubuntu/Debian: sudo apt install openssh-client git\n" printf " RHEL/CentOS: sudo yum install openssh-clients git\n" printf " Arch: sudo pacman -S openssh git\n" ;; macos) printf " macOS: git and ssh should be pre-installed\n" printf " If missing: xcode-select --install\n" ;; esac return 1 fi return 0 } # Remove existing SSH host entry _remove_ssh_host_entry() { host_name="$1" temp_file=$(_create_temp_file) # Remove the host block (Host line and all following indented lines) awk -v host="$host_name" ' BEGIN { skip = 0 } /^Host / { if ($2 == host) { skip = 1 } else { skip = 0 } } /^[[:space:]]/ && skip { next } /^[^[:space:]#]/ && !/^Host / { skip = 0 } !skip { print } ' "$SSH_CONFIG_FILE" > "$temp_file" _safe_file_replace "$temp_file" "$SSH_CONFIG_FILE" } # Test connections to all configured services _test_service_connections() { if [ -f "$SSH_CONFIG_FILE" ]; then # Test GitHub connections github_hosts=$(grep '^Host github-' "$SSH_CONFIG_FILE" 2>/dev/null | awk '{print $2}') if [ -n "$github_hosts" ]; then for host in $github_hosts; do printf " %s: " "$host" if _test_ssh_connection "$host" 3; then _print_color green "Connected" printf "\n" else _print_color red "Failed" printf "\n" fi done fi # Test GitLab connections gitlab_hosts=$(grep '^Host gitlab-' "$SSH_CONFIG_FILE" 2>/dev/null | awk '{print $2}') if [ -n "$gitlab_hosts" ]; then for host in $gitlab_hosts; do printf " %s: " "$host" if _test_ssh_connection "$host" 3; then _print_color green "Connected" printf "\n" else _print_color red "Failed" printf "\n" fi done fi if [ -z "$github_hosts" ] && [ -z "$gitlab_hosts" ]; then printf " No GitHub or GitLab hosts configured\n" fi else printf " No SSH config file found\n" fi } #================================================================# # ADVANCED SETUP FUNCTIONS #================================================================# # Setup multiple accounts for the same service setup_github_multi() { printf "\n" _print_color blue "==========================================" printf "\n" _print_color blue " GitHub Multiple Accounts Setup" printf "\n" _print_color blue "==========================================" printf "\n\n" _print_info "This wizard helps you set up multiple GitHub accounts" printf "Each account will have its own SSH key and host configuration.\n\n" # Ask how many accounts printf "How many GitHub accounts do you want to set up? (1-5): " read -r account_count # Fix: Proper regex pattern matching if ! printf "%s" "$account_count" | grep -q '^[1-5]$'; then _print_error "Please enter a number between 1 and 5" return 1 fi # Setup each account i=1 while [ "$i" -le "$account_count" ]; do printf "\n" _print_color yellow "Setting up GitHub account %d of %d" "$i" "$account_count" printf "\n" printf "%s\n" "$(printf '=%.0s' $(seq 1 40))" # Fix: Use seq instead of {1..40} # Override the github username for this iteration GITHUB_USERNAME="" if ! _gather_github_info; then printf "Skipping account %d\n" "$i" else _check_existing_ssh_setup "github" if [ "$GENERATE_NEW_KEY" = "true" ]; then # Generate unique key name for multiple accounts KEY_NAME="github_${GITHUB_USERNAME}_id_ed25519" KEY_PATH="$SSH_DIR/$KEY_NAME" _generate_ssh_key "github" fi _setup_ssh_config "github" _add_to_ssh_agent "github" _guide_github_key_addition _test_github_connection _integrate_with_session_manager "github" _print_success "Account %d (%s) setup completed!" "$i" "$GITHUB_USERNAME" fi i=$((i + 1)) done printf "\n" _print_success "Multiple GitHub accounts setup completed!" _print_info "Use 'gitssh ssh status' to see all configured connections" } # Quick SSH key generation (minimal prompts) quick_ssh_key() { if ! _check_setup_dependencies; then return 1 fi printf "Quick SSH Key Generator\n" printf "=======================\n" printf "Service (github/gitlab/custom): " read -r service service=$(_to_lower "$service") case "$service" in github|gitlab) printf "Username: " read -r username if _is_empty "$username"; then _print_error "Username cannot be empty" return 1 fi KEY_NAME="${service}_${username}_id_ed25519" ;; custom) printf "Key name: " read -r KEY_NAME if _is_empty "$KEY_NAME"; then _print_error "Key name cannot be empty" return 1 fi ;; *) _print_error "Invalid service. Use: github, gitlab, or custom" return 1 ;; esac printf "Email (for key comment): " read -r email if _is_empty "$email"; then email="$(whoami)@$(hostname)" printf "Using default: %s\n" "$email" fi KEY_PATH="$SSH_DIR/$KEY_NAME" # Generate key printf "\nGenerating SSH key...\n" if ssh-keygen -t ed25519 -f "$KEY_PATH" -C "$email"; then _print_success "SSH key generated: $KEY_NAME" # Set permissions chmod 600 "$KEY_PATH" chmod 644 "$KEY_PATH.pub" # Add to agent if _is_ssh_agent_running; then ssh-add "$KEY_PATH" _print_success "Added to SSH agent" else _print_info "Add to SSH agent with: ssh-add $KEY_PATH" fi # Show public key printf "\nYour public key:\n" printf "%s\n" "$(cat "$KEY_PATH.pub")" # Auto-copy if possible if command -v xclip >/dev/null 2>&1; then cat "$KEY_PATH.pub" | xclip -selection clipboard _print_success "Copied to clipboard!" elif command -v pbcopy >/dev/null 2>&1; then cat "$KEY_PATH.pub" | pbcopy _print_success "Copied to clipboard!" fi else _print_error "Failed to generate SSH key" return 1 fi } #================================================================# # DIAGNOSTIC AND REPAIR FUNCTIONS #================================================================# # Diagnose SSH issues ssh_doctor() { printf "\n" _print_color blue "==========================================" printf "\n" _print_color blue " SSH Connection Doctor" printf "\n" _print_color blue "==========================================" printf "\n\n" issues_found=0 # Check SSH directory and permissions printf "1. Checking SSH Directory:\n" if [ -d "$SSH_DIR" ]; then _print_success "SSH directory exists: $SSH_DIR" # Check permissions permissions=$(ls -ld "$SSH_DIR" | awk '{print $1}') if [ "$permissions" = "drwx------" ] || [ "$permissions" = "drwx------." ]; then _print_success "Directory permissions are correct (700)" else _print_warning "Directory permissions should be 700" printf " Current: %s\n" "$permissions" printf " Fix with: chmod 700 %s\n" "$SSH_DIR" issues_found=$((issues_found + 1)) fi else _print_error "SSH directory missing: $SSH_DIR" printf " Fix with: mkdir -p %s && chmod 700 %s\n" "$SSH_DIR" "$SSH_DIR" issues_found=$((issues_found + 1)) fi printf "\n" # Check SSH keys printf "2. Checking SSH Keys:\n" key_count=0 for key_file in "$SSH_DIR"/*; do [ ! -f "$key_file" ] && continue case "$(basename "$key_file")" in *.pub) continue # Skip public keys, we'll check them with private keys ;; *_ed25519|*_rsa|id_ed25519|id_rsa|id_ecdsa|id_dsa) key_name=$(basename "$key_file") public_key="${key_file}.pub" if [ -f "$public_key" ]; then _print_success "Valid key pair: $key_name" # Check permissions private_perms=$(ls -l "$key_file" | awk '{print $1}') public_perms=$(ls -l "$public_key" | awk '{print $1}') if [ "$private_perms" != "-rw-------" ] && [ "$private_perms" != "-rw-------." ]; then _print_warning " Private key permissions should be 600" printf " Fix with: chmod 600 %s\n" "$key_file" issues_found=$((issues_found + 1)) fi key_count=$((key_count + 1)) else _print_warning "Missing public key for: $key_name" printf " Expected: %s\n" "$public_key" issues_found=$((issues_found + 1)) fi ;; esac done if [ "$key_count" -eq 0 ]; then _print_warning "No SSH keys found" printf " Generate with: gitssh setup github or gitssh setup gitlab\n" issues_found=$((issues_found + 1)) fi printf "\n" # Check SSH agent printf "3. Checking SSH Agent:\n" if _is_ssh_agent_running; then _print_success "SSH Agent is running" loaded_keys=$(_get_loaded_ssh_keys) if [ -n "$loaded_keys" ]; then printf "Loaded keys:\n" printf "%s\n" "$loaded_keys" | sed 's/^/ /' else _print_warning "No keys loaded in SSH agent" printf " Load keys with: ssh-add ~/.ssh/your_key\n" issues_found=$((issues_found + 1)) fi else _print_warning "SSH Agent not running" printf " Start with: eval \$(ssh-agent -s)\n" printf " Then load keys with: ssh-add ~/.ssh/your_key\n" issues_found=$((issues_found + 1)) fi printf "\n" # Check SSH config printf "4. Checking SSH Configuration:\n" if [ -f "$SSH_CONFIG_FILE" ]; then _print_success "SSH config exists: $SSH_CONFIG_FILE" # Check for GitHub/GitLab entries github_entries=$(grep '^Host github-' "$SSH_CONFIG_FILE" 2>/dev/null | wc -l) gitlab_entries=$(grep '^Host gitlab-' "$SSH_CONFIG_FILE" 2>/dev/null | wc -l) printf " GitHub configurations: %s\n" "$github_entries" printf " GitLab configurations: %s\n" "$gitlab_entries" if [ "$github_entries" -eq 0 ] && [ "$gitlab_entries" -eq 0 ]; then _print_warning "No GitHub or GitLab SSH hosts configured" printf " Setup with: gitssh setup github or gitssh setup gitlab\n" issues_found=$((issues_found + 1)) fi else _print_warning "SSH config not found: $SSH_CONFIG_FILE" printf " Will be created during setup\n" issues_found=$((issues_found + 1)) fi printf "\n" # Test connections printf "5. Testing Connections:\n" connection_failures=0 if [ -f "$SSH_CONFIG_FILE" ]; then # Test GitHub hosts github_hosts=$(grep '^Host github-' "$SSH_CONFIG_FILE" 2>/dev/null | awk '{print $2}') for host in $github_hosts; do printf " Testing %s: " "$host" if _test_ssh_connection "$host" 5; then _print_color green "Success" printf "\n" else _print_color red "Failed" printf "\n" connection_failures=$((connection_failures + 1)) fi done # Test GitLab hosts gitlab_hosts=$(grep '^Host gitlab-' "$SSH_CONFIG_FILE" 2>/dev/null | awk '{print $2}') for host in $gitlab_hosts; do printf " Testing %s: " "$host" if _test_ssh_connection "$host" 5; then _print_color green "Success" printf "\n" else _print_color red "Failed" printf "\n" connection_failures=$((connection_failures + 1)) fi done if [ "$connection_failures" -gt 0 ]; then issues_found=$((issues_found + connection_failures)) fi fi printf "\n" # Summary printf "Diagnosis Summary:\n" printf "==================\n" if [ "$issues_found" -eq 0 ]; then _print_success "No issues found - SSH setup is working correctly!" else _print_warning "Found $issues_found issue(s) that need attention" printf "\nSuggested fixes:\n" printf " • For missing keys: run 'gitssh setup github' or 'gitssh setup gitlab'\n" printf " • For permission issues: chmod 700 ~/.ssh && chmod 600 ~/.ssh/id_*\n" printf " • For agent issues: eval \$(ssh-agent -s) && ssh-add ~/.ssh/your_key\n" printf " • For connection failures: check if keys are added to your account\n" fi printf "\n" return "$issues_found" } # Repair common SSH issues ssh_repair() { printf "\n" _print_color blue "==========================================" printf "\n" _print_color blue " SSH Repair Wizard" printf "\n" _print_color blue "==========================================" printf "\n\n" _print_info "This will attempt to fix common SSH configuration issues" printf "\n" repairs_made=0 # Fix SSH directory permissions printf "1. Fixing SSH directory permissions...\n" if [ -d "$SSH_DIR" ]; then chmod 700 "$SSH_DIR" _print_success "Set SSH directory permissions to 700" repairs_made=$((repairs_made + 1)) else mkdir -p "$SSH_DIR" chmod 700 "$SSH_DIR" _print_success "Created SSH directory with correct permissions" repairs_made=$((repairs_made + 1)) fi # Fix SSH key permissions printf "\n2. Fixing SSH key permissions...\n" key_files_fixed=0 for key_file in "$SSH_DIR"/*; do [ ! -f "$key_file" ] && continue case "$(basename "$key_file")" in *.pub) chmod 644 "$key_file" 2>/dev/null && key_files_fixed=$((key_files_fixed + 1)) ;; *_ed25519|*_rsa|id_ed25519|id_rsa|id_ecdsa|id_dsa) chmod 600 "$key_file" 2>/dev/null && key_files_fixed=$((key_files_fixed + 1)) ;; esac done if [ "$key_files_fixed" -gt 0 ]; then _print_success "Fixed permissions for $key_files_fixed key files" repairs_made=$((repairs_made + 1)) else _print_info "No key files found or permissions already correct" fi # Fix SSH config permissions printf "\n3. Fixing SSH config permissions...\n" if [ -f "$SSH_CONFIG_FILE" ]; then chmod 600 "$SSH_CONFIG_FILE" _print_success "Set SSH config permissions to 600" repairs_made=$((repairs_made + 1)) else _print_info "SSH config doesn't exist yet" fi # Start SSH agent if not running printf "\n4. Checking SSH agent...\n" if ! _is_ssh_agent_running; then printf "Starting SSH agent...\n" eval "$(ssh-agent -s)" >/dev/null if _is_ssh_agent_running; then _print_success "Started SSH agent" repairs_made=$((repairs_made + 1)) # Load existing keys printf "Loading SSH keys...\n" keys_loaded=0 for key_file in "$SSH_DIR"/*; do [ ! -f "$key_file" ] && continue case "$(basename "$key_file")" in *_ed25519|*_rsa|id_ed25519|id_rsa|id_ecdsa|id_dsa) if ssh-add "$key_file" 2>/dev/null; then keys_loaded=$((keys_loaded + 1)) fi ;; esac done if [ "$keys_loaded" -gt 0 ]; then _print_success "Loaded $keys_loaded SSH keys" repairs_made=$((repairs_made + 1)) fi else _print_warning "Failed to start SSH agent" fi else _print_success "SSH agent is already running" fi printf "\n" _print_color blue "==========================================" printf "\n" if [ "$repairs_made" -gt 0 ]; then _print_success "Completed $repairs_made repairs" printf "Run 'gitssh ssh status' to verify the fixes\n" else _print_info "No repairs needed - SSH setup appears correct" fi printf "\n" return 0 } #================================================================# # UNINSTALL AND CLEANUP #================================================================# # Remove SSH setup for a service remove_ssh_setup() { if [ $# -eq 0 ]; then printf "Usage: remove_ssh_setup \n" printf "Services: github, gitlab, or specific hostname\n" return 1 fi service="$1" printf "\n" _print_color yellow "==========================================" printf "\n" _print_color yellow " Remove SSH Setup for %s" "$service" printf "\n" _print_color yellow "==========================================" printf "\n\n" _print_warning "This will remove SSH keys and configuration for $service" printf "This action cannot be easily undone.\n\n" printf "Are you sure you want to continue? (y/N): " read -r confirm case "$confirm" in [Yy]*) ;; *) printf "Cancelled\n" return 0 ;; esac items_removed=0 # Remove SSH keys printf "\nRemoving SSH keys...\n" for key_pattern in "${service}_*" "id_${service}*"; do for key_file in "$SSH_DIR"/$key_pattern; do [ ! -f "$key_file" ] && continue key_name=$(basename "$key_file") printf "Remove %s? (y/N): " "$key_name" read -r remove_key case "$remove_key" in [Yy]*) rm -f "$key_file" "${key_file}.pub" _print_success "Removed $key_name" items_removed=$((items_removed + 1)) ;; esac done done # Remove SSH config entries printf "\nRemoving SSH config entries...\n" if [ -f "$SSH_CONFIG_FILE" ]; then case "$service" in github) hosts_to_remove=$(grep '^Host github-' "$SSH_CONFIG_FILE" | awk '{print $2}') ;; gitlab) hosts_to_remove=$(grep '^Host gitlab-' "$SSH_CONFIG_FILE" | awk '{print $2}') ;; *) hosts_to_remove="$service" ;; esac for host in $hosts_to_remove; do if grep -q "^Host $host$" "$SSH_CONFIG_FILE"; then printf "Remove SSH config for %s? (y/N): " "$host" read -r remove_config case "$remove_config" in [Yy]*) _remove_ssh_host_entry "$host" _print_success "Removed SSH config for $host" items_removed=$((items_removed + 1)) ;; esac fi done fi printf "\n" if [ "$items_removed" -gt 0 ]; then _print_success "Removed $items_removed items" _print_info "You may want to restart your SSH agent to clear cached keys" else _print_info "No items were removed" fi printf "\n" return 0 } #================================================================# # INTEGRATION WITH SESSION MANAGER #================================================================# # Integration helper - uses existing session manager functions if available _add_user_to_config() { username="$1" name="$2" email="$3" ssh_host="$4" # Check if session manager is available if command -v git_add_user >/dev/null 2>&1 && _check_dependencies 2>/dev/null; then # Use existing session manager function printf "Integrating with GitSSH Session Manager...\n" # Create temporary script to automate git_add_user temp_script=$(_create_temp_file) cat > "$temp_script" << EOF #!/bin/sh printf "%s\n%s\n%s\n%s\ny\n" "$username" "$name" "$email" "$ssh_host" EOF chmod +x "$temp_script" # Run git_add_user with automated input if "$temp_script" | git_add_user >/dev/null 2>&1; then rm -f "$temp_script" return 0 else rm -f "$temp_script" return 1 fi else # Session manager not available - just inform user printf "GitSSH Session Manager not available\n" printf "Run 'gitssh init' first to enable full integration\n" return 1 fi } # Check if user exists in session manager _user_exists() { username="$1" if _check_dependencies 2>/dev/null && [ -f "$GIT_SSH_USERS_FILE" ]; then user_details=$(jq -r --arg user "$username" '.users[$user] // empty' "$GIT_SSH_USERS_FILE" 2>/dev/null) [ -n "$user_details" ] && [ "$user_details" != "null" ] && [ "$user_details" != "empty" ] else return 1 fi } #================================================================# # EDUCATIONAL HELP FUNCTIONS #================================================================# # Show SSH learning guide ssh_learn() { printf "\n" _print_color blue "==========================================" printf "\n" _print_color blue " SSH & Git Learning Guide" printf "\n" _print_color blue "==========================================" printf "\n\n" printf "What is SSH?\n" printf "============\n" printf "SSH (Secure Shell) is a protocol for secure communication over networks.\n" printf "For Git, SSH provides passwordless authentication using key pairs.\n\n" printf "How SSH Keys Work:\n" printf "==================\n" printf "1. You generate a key pair (public + private key)\n" printf "2. Keep the private key secret on your computer\n" printf "3. Add the public key to your GitHub/GitLab account\n" printf "4. SSH uses these keys to authenticate you automatically\n\n" printf "Why Use SSH Instead of HTTPS?\n" printf "==============================\n" printf "• No password prompts for git push/pull\n" printf "• More secure than password authentication\n" printf "• Required for many advanced Git workflows\n" printf "• Better performance for frequent operations\n\n" printf "Key Types (Recommendations):\n" printf "==================================\n" printf "• Ed25519: Recommended - fast, secure, small keys\n" printf "• RSA 4096: Good alternative - widely supported\n" printf "• ECDSA: Secure but Ed25519 preferred\n" printf "• RSA 2048: Minimum, but Ed25519 better\n\n" printf "SSH Agent:\n" printf "===========\n" printf "Manages your SSH keys and remembers passphrases during your session.\n" printf "Start with: eval \$(ssh-agent -s)\n" printf "Add keys with: ssh-add ~/.ssh/your_key\n\n" printf "SSH Config File:\n" printf "================\n" printf "Location: ~/.ssh/config\n" printf "Purpose: Define custom hostnames and key mappings\n" printf "Allows using: git@github-username:repo/name.git\n\n" printf "Getting Started:\n" printf "================\n" printf "1. Run 'gitssh setup github' or 'gitssh setup gitlab' for guided setup\n" printf "2. Use 'gitssh ssh status' to check your configuration\n" printf "3. Use 'gitssh ssh doctor' if you have connection issues\n" printf "4. Use 'gitssh session set' to manage identities per repository\n\n" printf "Common Commands:\n" printf "================\n" printf "• gitsh ssh status - Check SSH setup status\n" printf "• gitsh ssh doctor - Diagnose SSH issues\n" printf "• gitsh ssh repair - Fix common problems\n" printf "• gitsh setup github - Setup GitHub SSH\n" printf "• gitsh setup gitlab - Setup GitLab SSH\n" printf "• quick_ssh_key - Generate key quickly\n" printf "• remove_ssh_setup - Clean removal\n\n" } # Show troubleshooting guide ssh_troubleshoot() { printf "\n" _print_color blue "==========================================" printf "\n" _print_color blue " SSH Troubleshooting Guide" printf "\n" _print_color blue "==========================================" printf "\n\n" printf "Common Issues and Solutions:\n" printf "============================\n\n" printf "1. 'Permission denied (publickey)'\n" printf " Causes:\n" printf " • SSH key not added to your account\n" printf " • Wrong key being used\n" printf " • SSH agent not running\n" printf " Solutions:\n" printf " • Verify key is added: gitssh ssh status\n" printf " • Check SSH agent: ssh-add -l\n" printf " • Test connection: ssh -T [email protected]\n" printf " • Try adding the key to SSH agent again: ssh-add %s\n" "$KEY_PATH" printf "\n" printf "2. 'Could not open a connection to your authentication agent'\n" printf " Solution:\n" printf " • Start SSH agent: eval \$(ssh-agent -s)\n" printf " • Add your key: ssh-add ~/.ssh/your_key\n\n" printf "3. 'Bad permissions' errors\n" printf " Solution:\n" printf " • Fix with gitssh ssh repair\n" printf " • Or manually: chmod 700 ~/.ssh && chmod 600 ~/.ssh/id_*\n\n" printf "4. Wrong user being detected\n" printf " Causes:\n" printf " • Multiple keys for same service\n" printf " • Wrong key loaded in agent\n" printf " Solutions:\n" printf " • Use IdentitiesOnly in SSH config\n" printf " • Clear agent: ssh-add -D, then add specific key\n\n" printf "5. 'Host key verification failed'\n" printf " Solution:\n" printf " • Remove old host key: ssh-keygen -R hostname\n" printf " • Accept new key when prompted\n\n" printf "6. Connection timeouts\n" printf " Causes:\n" printf " • Network issues\n" printf " • Firewall blocking SSH (port 22)\n" printf " Solutions:\n" printf " • Try HTTPS instead temporarily\n" printf " • Check firewall settings\n" printf " • Use SSH over HTTPS (port 443)\n\n" printf "Debugging Commands:\n" printf "===================\n" printf "• ssh -T [email protected] - Test GitHub connection\n" printf "• ssh -T [email protected] - Test GitLab connection\n" printf "• ssh -v [email protected] - Verbose connection test\n" printf "• ssh-add -l - List loaded keys\n" printf "• ssh-add -D - Remove all keys from agent\n" printf "• ssh-keygen -lf ~/.ssh/key.pub - Show key fingerprint\n\n" printf "Prevention Tips:\n" printf "================\n" printf "• Use different key files for different accounts\n" printf "• Keep backups of your SSH keys\n" printf "• Use descriptive key comments\n" printf "• Set up SSH config properly\n" printf "• Test connections after setup\n\n" } #================================================================# # BACKUP AND RECOVERY #================================================================# # Backup SSH configuration ssh_backup() { if [ ! -d "$SSH_DIR" ]; then _print_error "SSH directory not found: $SSH_DIR" return 1 fi backup_dir="$HOME/ssh-backup-$(date +%Y%m%d-%H%M%S)" printf "Creating SSH backup...\n" printf "Backup location: %s\n" "$backup_dir" if mkdir -p "$backup_dir"; then # Copy SSH directory contents if cp -r "$SSH_DIR"/* "$backup_dir/" 2>/dev/null; then _print_success "SSH configuration backed up successfully" # Create backup info file cat > "$backup_dir/backup-info.txt" << EOF SSH Backup Created: $(date) Original location: $SSH_DIR Hostname: $(hostname) User: $(whoami) Contents: $(ls -la "$backup_dir/") To restore: 1. Stop SSH agent: ssh-agent -k 2. Backup current: mv ~/.ssh ~/.ssh.old 3. Restore: cp -r $backup_dir ~/.ssh 4. Fix permissions: chmod 700 ~/.ssh && chmod 600 ~/.ssh/id_* ~/.ssh/*_ed25519 ~/.ssh/*_rsa 5. Start agent: eval \$(ssh-agent -s) 6. Load keys: ssh-add ~/.ssh/your_key EOF printf "Backup includes:\n" ls -la "$backup_dir/" | sed 's/^/ /' printf "\nBackup info saved to: %s/backup-info.txt\n" "$backup_dir" else _print_error "Failed to copy SSH files" rmdir "$backup_dir" 2>/dev/null return 1 fi else _print_error "Failed to create backup directory" return 1 fi } # Restore SSH configuration from backup ssh_restore() { if [ $# -eq 0 ]; then printf "Usage: ssh_restore \n" printf "Available backups in %s:\n" "$HOME" ls -d "$HOME"/ssh-backup-* 2>/dev/null | sed 's|.*/||' | sed 's/^/ /' || printf " (no backups found)\n" return 1 fi backup_dir="$1" # Handle relative paths case "$backup_dir" in /*) ;; # Absolute path *) backup_dir="$HOME/$backup_dir" ;; # Relative to home esac if [ ! -d "$backup_dir" ]; then _print_error "Backup directory not found: $backup_dir" return 1 fi printf "Restoring SSH configuration from backup...\n" printf "Backup: %s\n" "$backup_dir" printf "Target: %s\n" "$SSH_DIR" _print_warning "This will replace your current SSH configuration!" printf "Continue? (y/N): " read -r confirm case "$confirm" in [Yy]*) ;; *) printf "Cancelled\n" return 0 ;; esac # Backup current SSH config if [ -d "$SSH_DIR" ]; then current_backup="$HOME/ssh-current-backup-$(date +%Y%m%d-%H%M%S)" printf "Backing up current SSH config to: %s\n" "$current_backup" cp -r "$SSH_DIR" "$current_backup" fi # Restore from backup if cp -r "$backup_dir"/* "$SSH_DIR/" 2>/dev/null; then # Fix permissions chmod 700 "$SSH_DIR" chmod 600 "$SSH_DIR"/* 2>/dev/null chmod 644 "$SSH_DIR"/*.pub 2>/dev/null _print_success "SSH configuration restored successfully" # Restart SSH agent and load keys printf "Restarting SSH agent and loading keys...\n" ssh-agent -k 2>/dev/null eval "$(ssh-agent -s)" >/dev/null keys_loaded=0 for key_file in "$SSH_DIR"/*; do [ ! -f "$key_file" ] && continue case "$(basename "$key_file")" in *_ed25519|*_rsa|id_ed25519|id_rsa|id_ecdsa|id_dsa) if ssh-add "$key_file" 2>/dev/null; then keys_loaded=$((keys_loaded + 1)) fi ;; esac done if [ "$keys_loaded" -gt 0 ]; then _print_success "Loaded $keys_loaded SSH keys" fi printf "Run 'gitssh ssh status' to verify the restoration\n" else _print_error "Failed to restore SSH configuration" return 1 fi } #================================================================# # HELPER FUNCTIONS (using existing utility functions) #================================================================# # These functions should be available from gitssh-utils.sh # If not available, provide basic implementations # Basic implementation if utility functions not available _basic_print_color() { color="$1" text="$2" if [ -t 1 ]; then # Check if stdout is a terminal case "$color" in red) printf "\033[31m%s\033[0m" "$text" ;; green) printf "\033[32m%s\033[0m" "$text" ;; yellow) printf "\033[33m%s\033[0m" "$text" ;; blue) printf "\033[34m%s\033[0m" "$text" ;; *) printf "%s" "$text" ;; esac else printf "%s" "$text" fi } _basic_print_error() { _basic_print_color red "Error: $1" printf "\n" } _basic_print_success() { _basic_print_color green "$1" printf "\n" } _basic_print_warning() { _basic_print_color yellow "Warning: $1" printf "\n" } _basic_print_info() { _basic_print_color blue "$1" printf "\n" } # Fallback function definitions if main utilities not loaded if ! command -v _print_color >/dev/null 2>&1; then _print_color() { _basic_print_color "$@"; } _print_error() { _basic_print_error "$@"; } _print_success() { _basic_print_success "$@"; } _print_warning() { _basic_print_warning "$@"; } _print_info() { _basic_print_info "$@"; } _is_empty() { text="$1" trimmed=$(printf "%s" "$text" | sed 's/[[:space:]]//g') [ -z "$trimmed" ] } _trim() { printf "%s" "$1" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//' } _to_lower() { printf "%s" "$1" | tr '[:upper:]' '[:lower:]' } _validate_email() { case "$1" in *@*.*) return 0 ;; *) return 1 ;; esac } _validate_username() { case "$1" in *[!a-zA-Z0-9_-]*) return 1 ;; "") return 1 ;; *) return 0 ;; esac } _detect_os() { case "$(uname -s)" in Linux*) printf "linux" ;; Darwin*) printf "macos" ;; CYGWIN*) printf "windows" ;; MINGW*) printf "windows" ;; *) printf "unknown" ;; esac } _is_ssh_agent_running() { ssh-add -l >/dev/null 2>&1 } _get_loaded_ssh_keys() { if _is_ssh_agent_running; then ssh-add -l 2>/dev/null fi } _test_ssh_connection() { ssh_host="$1" timeout="${2:-3}" ssh -o ConnectTimeout="$timeout" -T "git@$ssh_host" 2>&1 | grep -q "successfully authenticated\|Welcome to GitLab" } _create_temp_file() { mktemp 2>/dev/null || printf "/tmp/ssh-setup-$" } _safe_file_replace() { if [ -f "$1" ]; then mv "$1" "$2" return $? fi return 1 } # Check for jq availability for session manager integration _check_dependencies() { command -v jq >/dev/null 2>&1 } fi #================================================================# # INITIALIZATION AND HELP #================================================================# # Show setup module help ssh_setup_help() { printf "\n" _print_color blue "==========================================" printf "\n" _print_color blue " GitSSH Setup Module Help" printf "\n" _print_color blue "==========================================" printf "\n\n" printf "SETUP COMMANDS:\n" printf "===============\n" printf "gitssh setup github - Interactive GitHub SSH setup wizard\n" printf "gitssh setupgitlab - Interactive GitLab SSH setup wizard\n" printf "setup_github_multi - Setup multiple GitHub accounts\n" printf "quick_ssh_key - Quick key generation\n\n" printf "STATUS & DIAGNOSTICS:\n" printf "=====================\n" printf "gitssh ssh status - Show complete SSH setup status\n" printf "gitssh ssh doctor - Diagnose SSH connection issues\n" printf "gitssh ssh repair - Fix common problems\n\n" printf "MANAGEMENT:\n" printf "===========\n" printf "gitssh ssh backup - Create backup of SSH configuration\n" printf "gitssh ssh restore

- Restore from backup\n" printf "remove_ssh_setup - Remove SSH setup for service\n\n" printf "LEARNING:\n" printf "=========\n" printf "gitssh ssh learn - Learn about SSH and Git\n" printf "ssh_troubleshoot - Troubleshooting guide\n" printf "ssh_setup_help - This help message\n\n" printf "GETTING STARTED:\n" printf "================\n" printf "1. Run 'gitssh setup github' for GitHub setup\n" printf "2. Or 'gitssh setup gitlab' for GitLab setup\n" printf "3. Use 'gitssh ssh status' to verify setup\n" printf "4. Run 'gitssh session set' to configure repository identity\n\n" printf "INTEGRATION:\n" printf "============\n" printf "This module integrates with the GitSSH Session Manager.\n" printf "After SSH setup, use these commands:\n" printf "• gitssh session set - Configure user identity per repository\n" printf "• gitssh commit - Enhanced commit with user verification\n" printf "• gitssh push - Enhanced push with connection testing\n" printf "• gitssh remote convert - Convert HTTPS repositories to SSH\n\n" printf "For more help: gitssh ssh learn\n" printf "\n" } # Show all available functions ssh_commands() { printf "\n" _print_color blue "Available SSH Setup Commands:" printf "\n" printf "========================================\n" # Core setup printf "\nSETUP:\n" printf " gitssh setup github - GitHub SSH setup wizard\n" printf " gitssh setup gitlab - GitLab SSH setup wizard\n" printf " setup_github_multi - Multiple GitHub accounts\n" printf " quick_ssh_key - Quick key generation\n" # Status and diagnostics printf "\nSTATUS:\n" printf " gitssh ssh status - Complete SSH status\n" printf " gitssh ssh doctor - Diagnose issues\n" printf " gitssh ssh repair - Fix common problems\n" # Management printf "\nMANAGEMENT:\n" printf " gitssh ssh backup - Backup configuration\n" printf " gitssh ssh restore - Restore from backup\n" printf " remove_ssh_setup - Remove service setup\n" # Help and learning printf "\nHELP:\n" printf " gitssh ssh learn - Learning guide\n" printf " ssh_troubleshoot - Troubleshooting\n" printf " ssh_setup_help - Detailed help\n" printf " ssh_commands - This command list\n" printf "\n" _print_info "Start with: gitssh setup github or gitssh setup gitlab" printf "\n" }