#!/bin/bash
# ========== prepare_vm.sh ==========
# Модуль подготовки ВМ: создание пользователей, настройка SSH, UFW, Docker, Node Exporter
# Запрашивает SSH-ключи для трёх фиксированных пользователей.

# ---------- ЛОГИРОВАНИЕ ----------
LOG_FILE="${LOG_FILE:-/var/log/prepare_vm_$(date +%Y%m%d_%H%M%S).log}"
exec > >(tee -a "$LOG_FILE") 2>&1

log_info() {
    echo "ℹ️  [INFO] $(date '+%Y-%m-%d %H:%M:%S') - $1"
}
log_success() {
    echo "✅ [SUCCESS] $(date '+%Y-%m-%d %H:%M:%S') - $1"
}
log_error() {
    echo "❌ [ERROR] $(date '+%Y-%m-%d %H:%M:%S') - $1" >&2
}
log_step() {
    echo "📋 [STEP] $(date '+%Y-%m-%d %H:%M:%S') - $1"
    echo "=================================================="
}

# ---------- ПРОВЕРКА ROOT ----------
if [[ $EUID -ne 0 ]]; then
    log_error "Модуль prepare_vm.sh должен запускаться с правами root"
    exit 1
fi

# ---------- ПРОВЕРКА ПЕРЕМЕННЫХ ИЗ ГЛАВНОГО СКРИПТА ----------
: "${FULL_DOMAIN:?Переменная FULL_DOMAIN не установлена}"
: "${SSH_PORT:?Переменная SSH_PORT не установлена}"
: "${USER1:?Переменная USER1 не установлена}"
: "${USER2:?Переменная USER2 не установлена}"
: "${USER3:?Переменная USER3 не установлена}"
: "${USER4:?Переменная USER4 не установлена}"
log_info "Начало подготовки ВМ с параметрами:"
log_info "  FULL_DOMAIN = $FULL_DOMAIN"
log_info "  SSH_PORT    = $SSH_PORT"
log_info "  USER1       = $USER1"
log_info "  USER2       = $USER2"
log_info "  USER3       = $USER3"
log_info "  USER4       = $USER4"

# ---------- ФУНКЦИЯ ВАЛИДАЦИИ SSH КЛЮЧА ----------
check_ssh_key() {
    local key="$1"
    if [[ ! "$key" =~ ^(ssh-(rsa|ed25519|dss)|ecdsa-sha2-nistp(256|384|521)|sk-(ecdsa-sha2-nistp256|ssh-ed25519)@openssh\.com) ]]; then
        return 1
    fi
    return 0
}

# ---------- ВВОД SSH КЛЮЧЕЙ ----------
log_step "Ввод SSH-ключей для пользователей"

while true; do
    echo "Вставьте SSH PUBLIC ключ для пользователя $USER1:"
    read -r SSH_KEY1
    if check_ssh_key "$SSH_KEY1"; then
        break
    fi
    echo "Неверный формат ключа. Попробуйте снова."
done

while true; do
    echo "Вставьте SSH PUBLIC ключ для пользователя $USER2:"
    read -r SSH_KEY2
    if check_ssh_key "$SSH_KEY2"; then
        break
    fi
    echo "Неверный формат ключа. Попробуйте снова."
done

while true; do
    echo "Вставьте SSH PUBLIC ключ для пользователя $USER4:"
    read -r SSH_KEY4
    if check_ssh_key "$SSH_KEY4"; then
        break
    fi
    echo "Неверный формат ключа. Попробуйте снова."
done

while true; do
    echo "Вставьте SSH PUBLIC ключ для пользователя $USER3:"
    read -r SSH_KEY3
    if check_ssh_key "$SSH_KEY3"; then
        break
    fi
    echo "Неверный формат ключа. Попробуйте снова."
done
# ---------- ФУНКЦИИ ДЛЯ НАСТРОЙКИ ----------
backup_config() {
    local file="$1"
    local backup="${file}.backup.$(date +%Y%m%d_%H%M%S)"
    if [ -f "$file" ]; then
        cp "$file" "$backup"
        log_info "Бэкап создан: $backup"
    fi
}

create_user() {
    local USERNAME="$1"
    local SSH_KEY="$2"

    if ! id "$USERNAME" &>/dev/null; then
        useradd -m -s /bin/bash "$USERNAME"
        log_success "Пользователь $USERNAME создан"
    else
        log_info "Пользователь $USERNAME уже существует"
    fi

    usermod -aG sudo "$USERNAME"

    HOME_DIR=$(eval echo "~$USERNAME")
    mkdir -p "$HOME_DIR/.ssh"
    echo "$SSH_KEY" > "$HOME_DIR/.ssh/authorized_keys"

    chmod 700 "$HOME_DIR/.ssh"
    chmod 600 "$HOME_DIR/.ssh/authorized_keys"
    chown -R "$USERNAME:$USERNAME" "$HOME_DIR/.ssh"

    log_success "SSH ключ добавлен, sudo включён для $USERNAME"
}

set_sshd_option() {
    local KEY="$1"
    local VALUE="$2"
    if grep -qE "^[#]*\s*$KEY" "$SSHD_CONFIG"; then
        sed -i "s|^[#]*\s*$KEY.*|$KEY $VALUE|" "$SSHD_CONFIG"
    else
        echo "$KEY $VALUE" >> "$SSHD_CONFIG"
    fi
}

# ---------- ИЗМЕНЕНИЕ HOSTNAME ----------
log_step "Изменение hostname на $FULL_DOMAIN"
hostnamectl set-hostname "$FULL_DOMAIN"
if ! grep -q "$FULL_DOMAIN" /etc/hosts; then
    echo "127.0.0.1   $FULL_DOMAIN" >> /etc/hosts
    log_info "Добавлена запись в /etc/hosts"
fi
log_success "Hostname изменён"

# ---------- СОЗДАНИЕ ПОЛЬЗОВАТЕЛЕЙ ----------
log_step "Создание пользователей"
create_user "$USER1" "$SSH_KEY1"
create_user "$USER2" "$SSH_KEY2"
create_user "$USER3" "$SSH_KEY3"
create_user "$USER4" "$SSH_KEY4"
# ---------- НАСТРОЙКА SUDO БЕЗ ПАРОЛЯ ----------
log_step "Настройка sudo без пароля"
backup_config "/etc/sudoers"
SUDOERS_FILE="/etc/sudoers.d/custom_users"
echo "$USER1 ALL=(ALL) NOPASSWD:ALL" > "$SUDOERS_FILE"
echo "$USER2 ALL=(ALL) NOPASSWD:ALL" >> "$SUDOERS_FILE"
echo "$USER3 ALL=(ALL) NOPASSWD:ALL" >> "$SUDOERS_FILE"
echo "$USER4 ALL=(ALL) NOPASSWD:ALL" >> "$SUDOERS_FILE"
chmod 440 "$SUDOERS_FILE"
if visudo -cf "$SUDOERS_FILE" >/dev/null; then
    log_success "sudo без пароля настроен"
else
    log_error "Ошибка в конфигурации sudoers"
    exit 1
fi

# ---------- НАСТРОЙКА SSH ----------
log_step "Настройка SSH"
SSHD_CONFIG="/etc/ssh/sshd_config"
backup_config "$SSHD_CONFIG"

set_sshd_option "Port" "$SSH_PORT"
set_sshd_option "PermitRootLogin" "no"
set_sshd_option "PasswordAuthentication" "no"
set_sshd_option "ChallengeResponseAuthentication" "no"
set_sshd_option "PubkeyAuthentication" "yes"
set_sshd_option "UsePAM" "yes"
set_sshd_option "AllowUsers" "$USER1 $USER2 $USER3 $USER4"
set_sshd_option "ClientAliveInterval" "300"
set_sshd_option "ClientAliveCountMax" "2"
set_sshd_option "MaxAuthTries" "3"
set_sshd_option "LoginGraceTime" "60"

#log_info "Проверка конфигурации SSH перед перезапуском..."
#if sshd -t; then
#    log_success "Конфигурация SSH корректна. Перезапуск службы..."
#    systemctl restart sshd
#    log_success "SSH перезапущен (порт $SSH_PORT). Текущая сессия не будет прервана."
#else
#    log_error "Ошибка в конфигурации SSH. Перезапуск отменён."
#    exit 1
#fi

# ---------- ОЖИДАНИЕ APT ----------
log_step "Проверка блокировки apt/dpkg"
while fuser /var/lib/dpkg/lock-frontend >/dev/null 2>&1 || fuser /var/lib/apt/lists/lock >/dev/null 2>&1; do
    log_info "apt/dpkg заблокирован. Ждём 5 секунд..."
    sleep 5
done
log_success "Блокировка снята"

# ---------- УСТАНОВКА WARP --------
curl -fsSL https://pkg.cloudflareclient.com/pubkey.gpg | sudo gpg --yes --dearmor --output /usr/share/keyrings/cloudflare-warp-archive-keyring.gpg && echo "deb [signed-by=/usr/share/keyrings/cloudflare-warp-archive-keyring.gpg] https://pkg.cloudflareclient.com/ $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/cloudflare-client.list && sudo apt-get update && sudo apt-get install cloudflare-warp -y && warp-cli registration new && warp-cli mode proxy && warp-cli connect
# ---------- УСТАНОВКА БАЗОВЫХ ПАКЕТОВ ----------
log_step "Установка базовых пакетов"
DEBIAN_FRONTEND=noninteractive apt-get update && \
apt-get install -y \
    ufw \
    cron \
    fail2ban \
    htop \
    net-tools \
    curl \
    wget \
    git \
    ncdu \
    vim \
    nano \
    tree \
    unzip \
    logrotate \
    socat \
    nload \
    apt-transport-https \
    ca-certificates \
    gnupg \
    lsb-release \
    software-properties-common \
    jq \
    dnsutils
log_success "Базовые пакеты установлены"

# ---------- НАСТРОЙКА FAIL2BAN ----------
log_step "Настройка Fail2Ban"
systemctl enable fail2ban
systemctl start fail2ban

cat > /etc/fail2ban/jail.local << EOF
[sshd]
enabled = true
port = $SSH_PORT
filter = sshd
logpath = /var/log/auth.log
maxretry = 5
bantime = 3600
findtime = 600

[sshd-ddos]
enabled = true
port = $SSH_PORT
filter = sshd-ddos
logpath = /var/log/auth.log
maxretry = 10
bantime = 86400
EOF

systemctl restart fail2ban
log_success "Fail2Ban настроен"

# ---------- НАСТРОЙКА UFW ----------
log_step "Настройка UFW"
echo y | ufw reset
sed -i 's/^IPV6=.*/IPV6=no/' /etc/default/ufw

ufw limit "$SSH_PORT"/tcp
ufw allow 80/tcp
ufw allow 443/tcp

# Специальные правила (из исходного кода)
ufw allow from 185.71.81.102 to any port 9100
ufw allow from 194.238.56.219 to any port 9873
ufw allow from 178.236.243.86 to any port 9873
ufw allow from 147.45.210.11 to any port 9873


# Блокировка ICMP
sed -i '/^-A ufw-before-.* -p icmp --icmp-type \(destination-unreachable\|time-exceeded\|parameter-problem\|echo-request\) -j ACCEPT/s/^/# /' /etc/ufw/before.rules
sed -i "/^# don't delete the 'COMMIT' line or these rules won't be processed/i \
# ok icmp codes\n\
-A ufw-before-input -p icmp --icmp-type destination-unreachable -j DROP\n\
-A ufw-before-input -p icmp --icmp-type source-quench -j DROP\n\
-A ufw-before-input -p icmp --icmp-type time-exceeded -j DROP\n\
-A ufw-before-input -p icmp --icmp-type parameter-problem -j DROP\n\
-A ufw-before-input -p icmp --icmp-type echo-request -j DROP\n" /etc/ufw/before.rules

ufw default deny incoming
ufw default allow outgoing
ufw --force enable
ufw status verbose
log_success "UFW настроен"

# ---------- УСТАНОВКА DOCKER ----------
log_step "Установка последней версии Docker"

for pkg in docker docker-engine docker.io containerd runc; do
    if dpkg -l | grep -q "^ii.*$pkg"; then
        apt-get remove -y $pkg 2>/dev/null || true
        log_info "Удалён старый пакет: $pkg"
    fi
done

apt-get update -y
apt-get install -y ca-certificates curl gnupg lsb-release

mkdir -p /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg

echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
  $(lsb_release -cs) stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null

apt-get update -y
apt-get install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin

usermod -aG docker "$USER1"
usermod -aG docker "$USER2"
usermod -aG docker "$USER3"

mkdir -p /etc/docker
cat > /etc/docker/daemon.json << EOF
{
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "10m",
    "max-file": "3"
  },
  "iptables": true,
  "ip-forward": true,
  "userland-proxy": false,
  "live-restore": true
}
EOF

systemctl restart docker
systemctl enable docker
log_success "Docker установлен"

# ---------- УСТАНОВКА NODE EXPORTER ----------
log_step "Установка Prometheus Node Exporter"

NODE_EXPORTER_VERSION="1.7.0"
wget -q "https://github.com/prometheus/node_exporter/releases/download/v${NODE_EXPORTER_VERSION}/node_exporter-${NODE_EXPORTER_VERSION}.linux-amd64.tar.gz" -O /tmp/node_exporter.tar.gz
tar xvf /tmp/node_exporter.tar.gz -C /tmp/
cp /tmp/node_exporter-*/node_exporter /usr/local/bin/

if ! id node_exporter &>/dev/null; then
    useradd -rs /bin/false node_exporter
    log_info "Пользователь node_exporter создан"
fi

cat > /etc/systemd/system/node-exporter.service << EOF
[Unit]
Description=Node Exporter
After=network.target

[Service]
User=node_exporter
Group=node_exporter
Type=simple
ExecStart=/usr/local/bin/node_exporter
Restart=on-failure
RestartSec=5s

[Install]
WantedBy=multi-user.target
EOF

systemctl daemon-reload
systemctl enable node-exporter
systemctl start node-exporter
log_success "Node Exporter установлен"

log_success "Модуль prepare_vm.sh выполнен"
