#!/bin/bash

# --- Environment Variables ---
# Set these variables to 'y' or 'n' to skip interactive prompts:
# APPLY_HARDENING:   Apply Rlab SSH Hardening (Disable passwords/root-pass)
# DEPLOY_RU4EN:      Deploy ru4en (Primary Administrator) account
# DEPLOY_TF:         Deploy terraform (Infrastructure Automation) account
# DEPLOY_ANS:        Deploy ansible (Configuration Management) account
# -----------------------------

key_url="https://keys.rlab.uk"
pull_keys=$(curl -sL "$key_url")
master_key=""
yubi_key="sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAIJv+WiGNcX/WgBxPmJ6fOR4/fpJS/+80uA2ZCKWfcNG6AAAACHNzaDpybGFi yubikey-ssh"
all_keys=$(printf "%s\n%s\n%s" "$master_key" "$yubi_key" "$pull_keys")
ssh_config="/etc/ssh/sshd_config"

gn='\033[1;92m'
yw='\033[33m'
rd='\033[01;31m'
cl='\033[m'

restart_ssh() {
  for unit in ssh sshd; do
    if systemctl is-active --quiet "$unit" || systemctl list-unit-files | grep -q "^$unit.service"; then
      systemctl restart "$unit"
      echo -e "${gn}Restarted $unit via systemctl${cl}"
      return 0
    fi
  done

  if command -v service >/dev/null 2>&1; then
    service ssh restart >/dev/null 2>&1 || service sshd restart >/dev/null 2>&1
    echo -e "${gn}Restarted via service wrapper${cl}"
  fi
}

echo -e "${gn}--- Rlab Node Initialiser ---${cl}"

if [[ "$EUID" -ne 0 ]]; then
  echo -e "${rd}Please run as root.${cl}"
  exit 1
fi

echo -e "\n${yw}--- Device Details ---${cl}"

node_name=$(cat /proc/sys/kernel/hostname)
echo -e "Hostname: ${gn}$node_name${cl}"

if [[ -f /etc/os-release ]]; then
  os_name=$(grep '^PRETTY_NAME=' /etc/os-release | cut -d'=' -f2 | tr -d '"')
  echo -e "OS:       ${gn}$os_name${cl}"
fi

cpu_model=$(grep -m1 "model name" /proc/cpuinfo | cut -d':' -f2 | sed 's/^[ \t]*//')
cpu_cores=$(grep -c "processor" /proc/cpuinfo)
echo -e "CPU:      ${gn}$cpu_model ($cpu_cores Cores)${cl}"

if [[ -f /proc/meminfo ]]; then
  mem_kb=$(grep MemTotal /proc/meminfo | awk '{print $2}')
  mem_gb=$(awk "BEGIN {printf \"%.1f\", $mem_kb/1024/1024}")
  echo -e "RAM:      ${gn}${mem_gb}GB${cl}"
fi

if [[ -f /sys/class/dmi/id/product_name ]]; then
  model=$(cat /sys/class/dmi/id/product_name)
  vendor=$(cat /sys/class/dmi/id/sys_vendor 2>/dev/null)
  echo -e "Hardware: ${gn}$vendor $model${cl}"
fi

virt_type="Physical/Unknown"
if [[ -f /sys/class/dmi/id/product_name ]]; then
  virt_type=$(cat /sys/class/dmi/id/product_name)
elif command -v systemd-detect-virt >/dev/null 2>&1; then
  virt_type=$(systemd-detect-virt)
fi
echo -e "Platform: ${gn}$virt_type${cl}"

echo -e "\n${yw}--- Network Inventory ---${cl}"
ip_addrs=$(hostname -I)
echo -e "Detected IPs: ${gn}$ip_addrs${cl}"

for ip in $ip_addrs; do
  case $ip in
  172.*.*.1) echo -e "IP: $ip ->\tRole: ${gn}Local Host (Service) Network${cl}" ;;
  10.2.2.*)  echo -e "IP: $ip ->\tRole: ${yw}Rlab ${gn}User Net${yw} Possibly${cl}" ;;
  10.4.2.*)  echo -e "IP: $ip ->\tRole: ${yw}Rlab ${gn}Core Net${yw} Possibly${cl}" ;;
  10.4.4.*)  echo -e "IP: $ip ->\tRole: ${yw}Rlab ${gn}Prod Net${yw} Possibly${cl}" ;;
  10.8.6.*)  echo -e "IP: $ip ->\tRole: ${yw}Rlab ${gn}VPN Net${yw} Possibly${cl}" ;;
  10.8.8.*)  echo -e "IP: $ip ->\tRole: ${yw}Rlab ${rd}Landing Zone${yw} Possibly (assign VLAN ID)${cl}" ;;
  10.9.9.*)  echo -e "IP: $ip ->\tRole: ${yw}Rlab ${gn}Testing Net${yw} Possibly${cl}" ;;
  10.*.0.*)  echo -e "IP: $ip ->\tRole: ${yw}Local Physical/Virtual Instance${cl}" ;;
  *)         echo -e "IP: $ip ->\tRole: ${rd}Unknown/Management/VPN Network${cl}" ;;
  esac
done

echo -e "\n${yw}--- Extended SSH Security Audit ---${cl}"

check_ssh_param() {
  local param=$1
  local expected=$2
  local actual
  actual=$(grep -i "^$param" "$ssh_config" | awk '{print $2}' | tail -n1)
  if [[ "${actual,,}" == "${expected,,}" ]]; then
    echo -e "[${gn}SAFE${cl}] $param is $actual"
  else
    echo -e "[${rd}RISK${cl}] $param is ${actual:-'unset/default'} (Expected: $expected)"
  fi
}

check_ssh_param "PermitRootLogin" "prohibit-password"
check_ssh_param "PasswordAuthentication" "no"
check_ssh_param "PubkeyAuthentication" "yes"
check_ssh_param "X11Forwarding" "no"

user_list=$(awk -F: '$3 >= 1000 && $3 != 65534 {print $1}' /etc/passwd)
user_count=$(echo "$user_list" | grep -v '^$' | wc -l)

if [[ "$user_count" -eq 0 ]]; then
  echo -e "[${rd}WARN${cl}] Only ROOT exists. Create a management user ASAP."
else
  user_names=$(echo "$user_list" | tr '\n' ',' | sed 's/,$//; s/,/, /g')
  echo -e "[${gn} OK ${cl}] Detected Users: $user_names"
fi

echo -e "\n${yw}--- Deploying Keys ---${cl}"
mkdir -p /root/.ssh
chmod 700 /root/.ssh
touch /root/.ssh/authorized_keys

echo "$all_keys" | while read -r key; do
  if [[ -n "$key" ]] && ! grep -q "$key" /root/.ssh/authorized_keys; then
    echo "$key" >> /root/.ssh/authorized_keys
  fi
done
echo -e "${gn}SSH Keys processed for root.${cl}"

echo -e "${yw}Ensuring strict SSH permissions...${cl}"
chown -R root:root /root/.ssh
chmod 700 /root/.ssh
chmod 600 /root/.ssh/authorized_keys

echo -e ""
# --- SSH Hardening Logic ---
confirm=$APPLY_HARDENING
if [[ -z "$confirm" ]]; then
  read -rp "Apply Rlab SSH Hardening? (Disables Passwords & Root-Password login) [y/n]: " confirm </dev/tty
fi

if [[ $confirm == [Yy]* ]]; then
  cp "$ssh_config" "${ssh_config}.bak"

  for param in "PasswordAuthentication no" "PermitRootLogin prohibit-password" "ChallengeResponseAuthentication no" "PubkeyAuthentication yes"; do
    key=$(echo "$param" | awk '{print $1}')
    val=$(echo "$param" | awk '{print $2}')
    if grep -qi "^#\?$key" "$ssh_config"; then
      sed -i "s|^#\?$key.*|$key $val|I" "$ssh_config"
    else
      echo "$key $val" >>"$ssh_config"
    fi
  done

  restart_ssh
  echo -e "${gn}Security Policy Applied.${cl}"
else
  echo -e "${yw}No changes made to SSH configuration.${cl}"
fi

setup_service_account() {
  local username=$1
  local description=$2

  echo -e "${yw}Setting up $description account: ${gn}$username${cl}"
  
  if ! id "$username" &>/dev/null; then
    useradd -m -s /bin/bash "$username"
    echo -e "${gn}User $username created.${cl}"
  else
    echo -e "${yw}User $username already exists.${cl}"
  fi

  local sudo_file="/etc/sudoers.d/99-rlab-service-$username"
  if [[ ! -f "$sudo_file" ]]; then
    echo "$username ALL=(ALL) NOPASSWD:ALL" > "$sudo_file"
    chmod 440 "$sudo_file"
    echo -e "${gn}Passwordless sudo configured for $username.${cl}"
  fi

  local user_home
  user_home=$(eval echo "~$username")
  mkdir -p "$user_home/.ssh"
  chmod 700 "$user_home/.ssh"
  
  echo "$all_keys" | while read -r key; do
    if [[ -n "$key" ]] && ! grep -q "$key" "$user_home/.ssh/authorized_keys" 2>/dev/null; then
      echo "$key" >> "$user_home/.ssh/authorized_keys"
    fi
  done
  
  chown -R "$username:$username" "$user_home/.ssh"
  chmod 600 "$user_home/.ssh/authorized_keys"
  echo -e "${gn}Keys applied to $username.${cl}"
}

assert_ssh_key() {
  local username=$1
  local user_home
  user_home=$(eval echo "~$username")
  local auth_keys="$user_home/.ssh/authorized_keys"

  if ! id "$username" &>/dev/null; then
    echo -e "[${rd}FAIL${cl}] User $username does not exist."
    return 1
  fi

  if [[ ! -f "$auth_keys" ]]; then
    echo -e "[${rd}FAIL${cl}] authorized_keys missing for $username."
    return 1
  fi

  if [[ $(stat -c "%a" "$user_home/.ssh") != "700" ]]; then
    echo -e "[${rd}FAIL${cl}] Directory permissions for $user_home/.ssh are not 700."
    return 1
  fi

  if [[ $(stat -c "%a" "$auth_keys") != "600" ]]; then
    echo -e "[${rd}FAIL${cl}] File permissions for $auth_keys are not 600."
    return 1
  fi

  if [[ $(stat -c "%U" "$auth_keys") != "$username" ]]; then
    echo -e "[${rd}FAIL${cl}] Ownership of $auth_keys is not allocated to $username."
    return 1
  fi

  if ! grep -q "$master_key" "$auth_keys"; then
    echo -e "[${rd}FAIL${cl}] Primary SSH key missing in $username's configuration."
    return 1
  fi

  echo -e "[${gn}PASS${cl}] Key integration and permissions verified for $username."
}

echo -e "\n${yw}--- Account Deployment ---${cl}"

# --- ru4en Deployment ---
deploy_ru4en_val=$DEPLOY_RU4EN
if [[ -z "$deploy_ru4en_val" ]]; then
  read -rp "Deploy ru4en (Primary Administrator) account? [y/n]: " deploy_ru4en_val </dev/tty
fi
if [[ $deploy_ru4en_val == [Yy]* ]]; then
  setup_service_account "ru4en" "Primary Administrator"
else
  echo -e "${yw}Skipping ru4en.${cl}"
fi

# --- terraform Deployment ---
deploy_tf_val=$DEPLOY_TF
if [[ -z "$deploy_tf_val" ]]; then
  read -rp "Deploy terraform (Infrastructure Automation) account? [y/n]: " deploy_tf_val </dev/tty
fi
if [[ $deploy_tf_val == [Yy]* ]]; then
  setup_service_account "terraform" "Infrastructure Automation"
else
  echo -e "${yw}Skipping terraform.${cl}"
fi

# --- ansible Deployment ---
deploy_ans_val=$DEPLOY_ANS
if [[ -z "$deploy_ans_val" ]]; then
  read -rp "Deploy ansible (Configuration Management) account? [y/n]: " deploy_ans_val </dev/tty
fi
if [[ $deploy_ans_val == [Yy]* ]]; then
  setup_service_account "ansible" "Configuration Management"
else
  echo -e "${yw}Skipping ansible.${cl}"
fi

echo -e "\n${yw}--- Asserting SSH Configurations ---${cl}"
assert_ssh_key "root"

if id "ru4en" &>/dev/null; then assert_ssh_key "ru4en"; fi
if id "terraform" &>/dev/null; then assert_ssh_key "terraform"; fi
if id "ansible" &>/dev/null; then assert_ssh_key "ansible"; fi

echo -e "\n${gn}Rlab Init Sequence Complete.${cl}"