#!/bin/bash

# 0023

RED='\033[0;31m'
GREEN='\033[0;32m'
BLUE='\033[0;34m'
CYAN='\033[0;36m'
YELLOW='\033[0;33m'
NC='\033[0m'

clear

animate_text() {
    text=$1
    for ((i = 0; i < ${#text}; i++)); do
        echo -n "${text:$i:1}"
        sleep 0.03
    done
    echo
}

malwation_ascii() {
    echo -e "${BLUE}
 __  __    _    _     __        ___  _____ ___ ___  _   _
|  \\/  |  / \\  | |    \\ \\      / / \\|_   _|_ _/ _ \\| \\ | |
| |\\/| | / _ \\ | |     \\ \\ /\\ / / _ \\ | |  | | | | |  \\| |
| |  | |/ ___ \\| |___   \\ V  V / ___ \\| |  | | |_| | |\\  |
|_|  |_/_/   \\_\\_____|   \\_/\\_/_/   \\_\\_| |___\\___/|_| \\_|
${NC}"
}

loading() {
    local pid=$1
    local delay=0.1
    local spinstr='|/-\'
    while [ "$(ps a | awk '{print $1}' | grep $pid)" ]; do
        local temp=${spinstr#?}
        printf " [%c]  " "$spinstr"
        local spinstr=$temp${spinstr%"$temp"}
        sleep $delay
        printf "\b\b\b\b\b\b"
    done
    printf "    \b\b\b\b"
}

print_result() {
    echo -e "\n${CYAN}$1${NC}"
    if [ "$2" = "true" ]; then
        echo -e "${GREEN}✓ Requirement met${NC}"
        echo -e "  $3"
    else
        echo -e "${RED}✗ Requirement not met${NC}"
        echo -e "  $4"
    fi
    echo -e "${BLUE}$(printf '=%.0s' {1..50})${NC}"
}

print_header() {
    echo -e "\n${YELLOW}$1${NC}"
    echo -e "${YELLOW}$(printf '=%.0s' {1..50})${NC}"
}

malwation_ascii
animate_text "Welcome! Initializing Malwation script..."

if [ "$EUID" -ne 0 ]; then
    echo -e "${YELLOW}This script requires sudo privileges. Please enter your password when prompted.${NC}"
    sudo -v || {
        echo -e "${RED}Failed to obtain sudo privileges. Exiting.${NC}"
        exit 1
    }
fi

echo -e "${YELLOW}Checking pre requirements...${NC}"

sleep 1 &
loading $!

echo -e "\n${YELLOW}Registry Credentials${NC}"
while true; do
    read -p "Account Username: " REGISTRY_USER
    read -sp "Account Password (Characters you type will not be visible): " REGISTRY_PASSWORD
    echo

    if [[ -z "$REGISTRY_USER" ]] || [[ -z "$REGISTRY_PASSWORD" ]]; then
        echo -e "${RED}Error: Username and password cannot be empty!${NC}"
        continue
    fi

    break
done

echo -e "${GREEN}Pre requirements check completed!${NC}"

animate_text "Script is ready to run!"

sleep 1 &
loading $!

clear
malwation_ascii

echo -e "${BLUE}System Requirements and Technologies Used${NC}"
echo -e "${BLUE}$(printf '=%.0s' {1..50})${NC}"

print_header "Minimum Hardware Requirements"
echo "• CPU    : 4 Core"
echo "• RAM    : 16 GB DDR4"
echo "• Disk   : 200 GB SSD"
echo "• Note   : The disk mounted on '/' need to be at least 200 GB"

print_header "OS Requirements"
echo "• Ubuntu 22.04.1 LTS"

print_header "Access Requirements"
echo "• hub.malwation.com outbound access on 443 port"
echo "• Inbound access on 443 port for MTA server"
echo "• Inbound access on 443 port for all computers that runs agent"
echo "• Inbound access on 443 port to access web"
echo "• Inbound access on 443 port for file sharing systems (FileOrbis, DivyDrive)"
echo "• Inbound access on 443 port for ICAP source"

print_header "Technologies we Are Using"
echo "• Kubernetes     • K3S"
echo "• Containerd     • Traefik"
echo "• MongoDB        • Redis"
echo "• RabbitMQ       • Loki"
echo "• Prometheus     • Grafana"
echo "• Promtail       • Apache Tika Server"
echo "• MinIO"

echo -e "\n${YELLOW}Press any key to continue...${NC}"
read -n 1 -s -r

echo -e "\n${BLUE}Starting System Requirements Check...${NC}"
echo -e "${BLUE}$(printf '=%.0s' {1..50})${NC}"

os_version=$(lsb_release -d | cut -f2)
os_check=$(echo $os_version | grep -q "Ubuntu 22.04" && echo "true" || echo "false")
os_message_success="Your system is running $os_version, which meets the requirement."
os_message_fail="Your system is running $os_version. Ubuntu 22.04.1 LTS is required."

print_result "Operating System Check" "$os_check" "$os_message_success" "$os_message_fail"

ROOT_REQUIRED=200
VAR_REQUIRED=200
HOOKMESH_REQUIRED=200

check_mount_point() {
    local mount_point=$1
    local required_space=$2
    local df_output=$(df -h "$mount_point" | tail -n 1)
    local available_space=$(echo "$df_output" | awk '{print $4}')
    local total_space=$(echo "$df_output" | awk '{print $2}')

    local total_unit=${total_space: -1}
    local total_number=${total_space::-1}
    local available_unit=${available_space: -1}
    local available_number=${available_space::-1}

    local total_space_with_b="${total_space}B"
    local available_space_with_b="${available_space}B"

    local is_sufficient="false"
    case $total_unit in
    T) is_sufficient="true" ;;
    G) is_sufficient=$([ $(echo "$total_number >= $required_space" | bc -l) -eq 1 ] && echo "true" || echo "false") ;;
    *) is_sufficient="false" ;;
    esac

    echo "$mount_point:$total_space_with_b:$available_space_with_b:$is_sufficient"
}

root_info=$(check_mount_point "/" $ROOT_REQUIRED)
root_total=$(echo "$root_info" | cut -d':' -f2)
root_available=$(echo "$root_info" | cut -d':' -f3)
root_sufficient=$(echo "$root_info" | cut -d':' -f4)

if df -h | grep -q " /var$"; then
    var_info=$(check_mount_point "/var" $VAR_REQUIRED)
    var_total=$(echo "$var_info" | cut -d':' -f2)
    var_available=$(echo "$var_info" | cut -d':' -f3)
    var_sufficient=$(echo "$var_info" | cut -d':' -f4)
else
    var_total=$root_total
    var_available=$root_available
    var_sufficient=$root_sufficient
fi

if df -h | grep -q " /hookmesh$"; then
    hookmesh_info=$(check_mount_point "/hookmesh" $HOOKMESH_REQUIRED)
    hookmesh_total=$(echo "$hookmesh_info" | cut -d':' -f2)
    hookmesh_available=$(echo "$hookmesh_info" | cut -d':' -f3)
    hookmesh_sufficient=$(echo "$hookmesh_info" | cut -d':' -f4)
else
    hookmesh_total=$root_total
    hookmesh_available=$root_available
    hookmesh_sufficient=$root_sufficient
fi

space_check="true"
space_message=""

if [ "$root_sufficient" = "false" ]; then
    space_check="false"
    space_message+="  • '/' directory requires ${ROOT_REQUIRED}GB, but only has ${root_total} total space (${root_available} available)\n"
fi

if [ "$var_sufficient" = "false" ]; then
    space_check="false"
    space_message+="  • '/var' directory requires ${VAR_REQUIRED}GB, but only has ${var_total} total space (${var_available} available)\n"
fi

if [ "$hookmesh_sufficient" = "false" ]; then
    space_check="false"
    space_message+="  • '/hookmesh' directory requires ${HOOKMESH_REQUIRED}GB, but only has ${hookmesh_total} total space (${hookmesh_available} available)\n"
fi

if [ "$space_check" = "true" ]; then
    space_message="All storage requirements are met:\n"
    space_message+="  • '/' directory: ${root_total} total (${root_available} available)\n"

    if df -h | grep -q " /var$"; then
        space_message+="  • '/var' directory: ${var_total} total (${var_available} available)\n"
    fi

    if df -h | grep -q " /hookmesh$"; then
        space_message+="  • '/hookmesh' directory: ${hookmesh_total} total (${hookmesh_available} available)\n"
    fi
fi

print_result "Storage Requirements Check" "$space_check" "$space_message" "$space_message"

cpu_cores=$(nproc)
cpu_check=$([ $cpu_cores -ge 4 ] && echo "true" || echo "false")
cpu_message_success="Your system has $cpu_cores CPU core(s), which meets the minimum requirement."
cpu_message_fail="Your system has $cpu_cores CPU core(s). Minimum 4 CPU cores are required."

print_result "CPU Core Check" "$cpu_check" "$cpu_message_success" "$cpu_message_fail"

ufw_status=$(ufw status | grep "Status:" | awk '{print $2}')
if [ "$ufw_status" = "inactive" ]; then
    ufw_check="true"
    ufw_message_success="UFW is inactive, which meets the requirement."
else
    ufw_check="false"
    ufw_message_fail="UFW is active. Please disable UFW using the following command:\n    sudo ufw disable ${YELLOW}(Note: System reboot is required after disabling UFW)${NC}"
fi

print_result "Firewall Check" "$ufw_check" "$ufw_message_success" "$ufw_message_fail"

total_ram=$(grep MemTotal /proc/meminfo | awk '{print $2}')
total_ram_gb=$(awk "BEGIN {printf \"%.1f\", ${total_ram}/1024/1024}")

if (($(echo "${total_ram_gb} >= 15.5" | bc -l))); then
    ram_check="true"
    ram_message="Your system has ${total_ram_gb} GB of RAM, which meets the minimum requirement of 16 GB."
elif (($(echo "${total_ram_gb} >= 14.5" | bc -l))); then
    ram_check="true"
    ram_message="Your system has ${total_ram_gb} GB of RAM, which is close to the minimum requirement of 16 GB. This might be sufficient, but could potentially cause performance issues."
else
    ram_check="false"
    ram_message="Your system has ${total_ram_gb} GB of RAM. Minimum 16 GB of RAM is required."
fi

print_result "RAM Check" "$ram_check" "$ram_message" "$ram_message"

required_url="hub.malwation.com"
port=443
timeout=5

url_status=$(curl -s --connect-timeout $timeout -o /dev/null -w "%{http_code}" "https://$required_url:$port")
url_check=$([ "$url_status" = "200" ] || [ "$url_status" = "301" ] && echo "true" || echo "false")

if [ "$url_check" = "true" ]; then
    if [ "$url_status" = "200" ]; then
        url_message_success="Connection to $required_url:$port is successful! (HTTP 201 OK)"
    else
        url_message_success="Connection to $required_url:$port is successful! (HTTP 301 Redirect)"
    fi
else
    url_message_fail="Cannot connect to $required_url:$port! (HTTP Status: $url_status)"
fi

print_result "Outbound Access Check" "$url_check" "$url_message_success" "$url_message_fail"

REGISTRY="hub.malwation.com"

AUTH_STRING=$(printf '%s:%s' "${REGISTRY_USER}" "${REGISTRY_PASSWORD}" | base64 | tr -d '\n' | tr -d ' ')

response=$(curl -s -w "\n%{http_code}" \
    -X GET \
    "https://${REGISTRY}/api/v2.0/robots?page=1&page_size=10" \
    -H "accept: application/json" \
    -H "authorization: Basic ${AUTH_STRING}")

http_body=$(echo "$response" | sed '$d')
http_status=$(echo "$response" | tail -n1)

case "$http_status" in
401)
    api_check="false"
    api_message="Authentication failed! Invalid account credentials, please check your credentials and try again."
    ;;
403)
    api_check="true"
    api_message="Authentication successful! Account exists but has limited permissions."
    ;;
200)
    api_check="true"
    api_message="Authentication successful! Account has full access."
    ;;
*)
    api_check="false"
    api_message="Unexpected error occurred! (HTTP Status: $http_status)"
    ;;
esac

print_result "Registry Access Check" "$api_check" "$api_message" "$api_message"

echo -e "\n${BLUE}Check completed.${NC}"

all_requirements_met=$([ "$os_check" = "true" ] && [ "$space_check" = "true" ] && [ "$cpu_check" = "true" ] && [ "$ufw_check" = "true" ] && [ "$ram_check" = "true" ] && [ "$url_check" = "true" ] && [ "$api_check" = "true" ] && echo "true" || echo "false")

if [ "$all_requirements_met" = "false" ]; then
    echo -e "\n${YELLOW}Your system does not meet all the requirements. The following requirements are not met:${NC}"

    [ "$os_check" = "false" ] && echo -e "${RED}• Operating System:${NC} $os_message_fail"
    if [ "$space_check" = "false" ]; then
        echo -e "\n${RED}• Storage Requirements:${NC}"
        if [ "$root_sufficient" = "false" ]; then
            echo -e "    '/' directory requires ${ROOT_REQUIRED}GB, but only has ${root_total} total space (${root_available} available)"
        fi
        if [ "$var_sufficient" = "false" ] && df -h | grep -q " /var$"; then
            echo -e "    '/var' directory requires ${VAR_REQUIRED}GB, but only has ${var_total} total space (${var_available} available)"
        fi
        if [ "$hookmesh_sufficient" = "false" ] && df -h | grep -q " /hookmesh$"; then
            echo -e "    '/hookmesh' directory requires ${HOOKMESH_REQUIRED}GB, but only has ${hookmesh_total} total space (${hookmesh_available} available)"
        fi
    fi
    [ "$cpu_check" = "false" ] && echo -e "\n${RED}• CPU Cores:${NC} $cpu_message_fail"
    [ "$ufw_check" = "false" ] && echo -e "\n${RED}• Firewall:${NC} UFW service is active or enabled. Please disable UFW using the following command:\n    sudo ufw disable ${YELLOW}(Note: System reboot is required after disabling UFW)${NC}"
    [ "$ram_check" = "false" ] && echo -e "\n${RED}• RAM:${NC} $ram_message"
    [ "$url_check" = "false" ] && echo -e "\n${RED}• Outbound Access:${NC} $url_message_fail"
    [ "$api_check" = "false" ] && echo -e "\n${RED}• Registry Access:${NC} $api_message"

    echo -e "\n${YELLOW}Please address these issues and run the script again. Goodbye!${NC}"
else
    echo -e "\n${GREEN}Your system meets all the requirements. Goodbye!${NC}"
fi
