#!/bin/bash
# 多节点互相同步SSH密钥脚本（支持从文件读取IP、指定用户和密码）

# ==================== 颜色与样式定义 ====================
GREEN="\033[32m"    # 成功/完成
YELLOW="\033[33m"   # 进行中/提示
RED="\033[31m"      # 错误/失败
BLUE="\033[34m"     # 标题/分隔线
CYAN="\033[36m"     # 信息/说明
NC="\033[0m"        # 重置颜色

# 打印分隔线
print_sep() {
    echo -e "${BLUE}------------------------------------------------${NC}"
}

# ==================== 参数解析与校验 ====================
# 解析命令行参数
while [[ $# -gt 0 ]]; do
    case "$1" in
        --file=*)
            IP_FILE="${1#*=}"
            shift
            ;;
        --user=*)
            SSH_USER="${1#*=}"
            shift
            ;;
        --passwd=*)
            SSH_PASSWD="${1#*=}"
            shift
            ;;
        *)
            echo -e "${RED}未知参数: $1${NC}"
            exit 1
            ;;
    esac
done

# 检查必要参数
if [ -z "$IP_FILE" ] || [ -z "$SSH_USER" ] || [ -z "$SSH_PASSWD" ]; then
    echo -e "\n${YELLOW}用法:${NC} --file=IP文件路径 --user=用户名 --passwd=密码"
    exit 1
fi

# 检查IP文件是否存在
if [ ! -f "$IP_FILE" ]; then
    echo -e "${RED}错误：IP文件 $IP_FILE 不存在${NC}"
    exit 1
fi

# 从文件读取IP列表（去重、过滤空行）
NODES=()
while IFS= read -r ip; do
    if [ -n "$ip" ] && ! [[ " ${NODES[@]} " =~ " $ip " ]]; then
        NODES+=("$ip")
    fi
done < "$IP_FILE"

if [ ${#NODES[@]} -eq 0 ]; then
    echo -e "${RED}错误：IP文件 $IP_FILE 中未找到有效IP${NC}"
    exit 1
fi

# ==================== 核心功能函数 ====================
# 安装sshpass（处理自动输入密码）
install_sshpass() {
    echo -e "\n${YELLOW}【步骤1/3】检查并安装sshpass工具...${NC}"
    if ! command -v sshpass &> /dev/null; then
        echo -e "  ${YELLOW}→ sshpass未安装，正在安装...${NC}"
        if command -v apt &> /dev/null; then
            apt update -y >/dev/null && apt install -y sshpass >/dev/null
        elif command -v yum &> /dev/null; then
            yum install -y sshpass >/dev/null
        else
            echo -e "  ${RED}✗ 未找到apt或yum，无法安装sshpass${NC}"
            exit 1
        fi
        # 验证安装结果
        if command -v sshpass &> /dev/null; then
            echo -e "  ${GREEN}✓ sshpass安装成功${NC}"
        else
            echo -e "  ${RED}✗ sshpass安装失败，请手动安装后重试${NC}"
            exit 1
        fi
    else
        echo -e "  ${GREEN}✓ sshpass已安装${NC}"
    fi
}

# 在目标节点生成SSH密钥（若不存在）
generate_key() {
    local node=$1
    echo -e "  ${YELLOW}→ 处理节点 $node...${NC}"
    # 远程生成密钥（静默模式）
    sshpass -p "$SSH_PASSWD" ssh -o StrictHostKeyChecking=no ${SSH_USER}@$node << EOF >/dev/null 2>&1
        if [ ! -f ~/.ssh/id_rsa ]; then
            ssh-keygen -t rsa -N "" -f ~/.ssh/id_rsa
        fi
EOF
    # 检查执行结果
    if [ $? -eq 0 ]; then
        echo -e "  ${GREEN}✓ 密钥生成完成（已存在则跳过）${NC}"
    else
        echo -e "  ${RED}✗ 生成失败（可能密码错误或节点不可达）${NC}"
        exit 1
    fi
}

# 获取目标节点的公钥
get_public_key() {
    local node=$1
    # 静默获取公钥，忽略错误输出
    sshpass -p "$SSH_PASSWD" ssh -o StrictHostKeyChecking=no ${SSH_USER}@$node "cat ~/.ssh/id_rsa.pub" 2>/dev/null
}

# 将公钥追加到目标节点的authorized_keys
append_public_key() {
    local pub_key="$1"
    local target_node=$2
    # 远程执行追加公钥操作
    sshpass -p "$SSH_PASSWD" ssh -o StrictHostKeyChecking=no ${SSH_USER}@$target_node << EOF >/dev/null 2>&1
        mkdir -p ~/.ssh
        chmod 700 ~/.ssh
        if ! grep -q "$pub_key" ~/.ssh/authorized_keys 2>/dev/null; then
            echo "$pub_key" >> ~/.ssh/authorized_keys
            chmod 600 ~/.ssh/authorized_keys
        fi
EOF
    # 反馈结果
    if [ $? -eq 0 ]; then
        echo -e "    ${GREEN}→ 同步成功${NC}"
    else
        echo -e "    ${RED}→ 同步失败${NC}"
        exit 1
    fi
}

# ==================== 主流程 ====================
main() {
    # 欢迎信息
    clear
    print_sep
    echo -e "${BLUE}          多节点SSH密钥互相同步工具          ${NC}"
    print_sep
    echo -e "  ${CYAN}节点列表:${NC} ${NODES[*]}"
    echo -e "  ${CYAN}操作用户:${NC} $SSH_USER"
    echo -e "  ${CYAN}开始时间:${NC} $(date +'%Y-%m-%d %H:%M:%S')"
    print_sep

    # 1. 安装依赖工具
    install_sshpass
    print_sep

    # 2. 为所有节点生成密钥
    node_count=${#NODES[@]}
    echo -e "\n${YELLOW}【步骤2/3】为所有节点生成SSH密钥（共 $node_count 个节点）...${NC}"
    for i in "${!NODES[@]}"; do
        echo -e "\n  节点 ${i+1}/$node_count: ${NODES[$i]}"
        generate_key ${NODES[$i]}
    done
    print_sep

    # 3. 收集公钥并互相同步
    echo -e "\n${YELLOW}【步骤3/3】公钥互相同步（共 $node_count 个节点）...${NC}"
    for i in "${!NODES[@]}"; do
        current_node=${NODES[$i]}
        echo -e "\n  处理第 ${i+1}/$node_count 个节点: $current_node"
        
        # 获取当前节点公钥
        echo -e "  ${YELLOW}→ 获取公钥...${NC}"
        pub_key=$(get_public_key $current_node)
        if [ -z "$pub_key" ]; then
            echo -e "  ${RED}✗ 无法获取 $current_node 的公钥${NC}"
            exit 1
        fi
        
        # 同步到所有节点
        echo -e "  ${YELLOW}→ 同步到所有节点...${NC}"
        for target in "${NODES[@]}"; do
            echo -e "    目标节点: $target"
            append_public_key "$pub_key" $target
        done
    done

    # 完成提示
    print_sep
    echo -e "\n${GREEN}=== 所有操作完成！===${NC}"
    echo -e "  ${CYAN}验证方法:${NC} 在任意节点执行 'ssh ${NODES[1]}' 测试免密登录"
    echo -e "  ${CYAN}结束时间:${NC} $(date +'%Y-%m-%d %H:%M:%S')"
    print_sep
}

# 执行主流程
main
