SSH-Infrastructure / tools / migrate-modern-key.sh
1 contributor
99 lines | 2.949kb
#!/usr/bin/env bash
# Migrate legacy SSH key (id_rsa_old) to modern key (id_ed25519) on hosts
# Usage: ./tools/migrate-modern-key.sh [host-alias]
# If no host specified, migrates all legacy hosts

set -euo pipefail

project_root=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")/.." && pwd)
modern_key_file="$HOME/.ssh/id_ed25519.pub"
legacy_key_file="$HOME/.ssh/keys/id_rsa_old"

if [[ ! -f "$modern_key_file" ]]; then
    printf "Error: Modern key not found at %s\n" "$modern_key_file" >&2
    exit 1
fi

if [[ ! -f "$legacy_key_file" ]]; then
    printf "Error: Legacy key not found at %s\n" "$legacy_key_file" >&2
    exit 1
fi

modern_key=$(cat "$modern_key_file")

migrate_host() {
    local host=$1
    local ip
    local user

    # Get host config
    ip=$(ssh -G "$host" 2>/dev/null | grep "^hostname " | cut -d' ' -f2) || {
        printf "Error: Cannot resolve host %s\n" "$host" >&2
        return 1
    }

    user=$(ssh -G "$host" 2>/dev/null | grep "^user " | cut -d' ' -f2) || user="root"

    printf "Migrating %s (%s@%s)...\n" "$host" "$user" "$ip"

    # Try with modern key first (might already be migrated)
    if timeout 2 ssh -o BatchMode=yes -o ConnectTimeout=1 "$host" "true" 2>/dev/null; then
        printf "  ✓ Already using modern key\n"
        return 0
    fi

    # Try legacy key to install modern key
    if timeout 5 ssh -i "$legacy_key_file" -o StrictHostKeyChecking=accept-new \
        -o ConnectTimeout=2 "${user}@${ip}" \
        "mkdir -p ~/.ssh && \
         grep -q '$(printf '%s' "$modern_key" | sed 's/[&/\]/\\&/g')' ~/.ssh/authorized_keys 2>/dev/null || \
         echo '$modern_key' >> ~/.ssh/authorized_keys && \
         chmod 600 ~/.ssh/authorized_keys && \
         echo 'OK'" 2>/dev/null; then
        printf "  ✓ Modern key installed\n"

        # Verify
        sleep 1
        if timeout 2 ssh -o BatchMode=yes -o ConnectTimeout=1 "$host" "true" 2>/dev/null; then
            printf "  ✓ Verified\n"
            return 0
        else
            printf "  ⚠ Installation ok, verification pending\n"
            return 1
        fi
    else
        printf "  ✗ Legacy key access failed\n"
        return 1
    fi
}

if [[ $# -gt 0 ]]; then
    # Migrate specific host
    migrate_host "$1"
else
    # Migrate all legacy hosts
    printf "=== Migrating all legacy hosts to modern key ===\n\n"

    failed=()
    success=()

    while IFS= read -r host; do
        if migrate_host "$host"; then
            success+=("$host")
        else
            failed+=("$host")
        fi
        printf "\n"
    done < <(grep -E "^Host is-" "$project_root/inventory/hosts-local.yaml" \
        | grep -oE "is-[a-z0-9-]+" | sort -u)

    printf "\n=== Migration Summary ===\n"
    printf "Success: %d\n" "${#success[@]}"
    printf "Failed: %d\n" "${#failed[@]}"

    if [[ ${#failed[@]} -gt 0 ]]; then
        printf "\nFailed hosts:\n"
        printf "  %s\n" "${failed[@]}"
        exit 1
    fi
fi