#!/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


# Блокировка 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 выполнен"
