#!/bin/bash

## INSTALLATION SCRIPT FOR Linux operating systems with DEB or RPM packages
# Usage:
#
#   $ wget -q -O /tmp/install_script.sh https://scripts.download.strangebee.com/latest/sh/install_script.sh ; sudo -v ; bash /tmp/install_script.sh
#
#
# maintained by: ©StrangeBee - https://www.strangebee.com




#############
# VARIABLES #
#############

RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
CYAN='\033[1;36m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
LOGFILE="/tmp/install.log"
OSRPM=("fedora NOT_TESTED" "rhel ??.??" "rocky 9.4" "almalinux 9.6")
OSDEB=("ubuntu ??.04" "debian 11" "debian 12")
MINREQRAM="16000000"
MINREQCPU="4"
PROXYHOST=""
PROXYPORT=""
CACERT=""
THEHIVE_VERSION=5.5.3-1
CORTEX_VERSION=3.2.1-2
CASSANDRA_VERSION="4.1.x"
ELASTICSEARCH_VERSION="7.x"
BASE_URL=download.strangebee.com

HEADER="
TheHive & Cortex installation script, for Linux operating systems with DEB or RPM packages.
This script supports the installtion of TheHive on x86_64 and ARM servers, and Cortex on x86_64 only.

Following install options are available:
  - Configure proxy settings
  - Install TheHive ${THEHIVE_VERSION} (x86_64 or ARM)
  - Install Cortex (running Analyzers and Responders with Docker) (x86_64 only)
  - Install Cortex (running Analyzers and Responders on the host -- Not recommended, supported on Ubuntu and Debian ONLY) (x86_64 only)


This script has sucessfully been tested on freshly installed Operating Systems:
$(for I in "${OSRPM[@]}" "${OSDEB[@]}"; do grep -q NOT_TESTED <<< $I || echo "  - $I"; done)

Requirements:
  - ${MINREQCPU}vCPU
  - $((${MINREQRAM}/1000000)) GB of RAM

Usage:

   $ wget -q -O /tmp/install_script.sh https://scripts.download.strangebee.com/latest/sh/install_script.sh ; sudo -v ; bash /tmp/install_script.sh

Maintained by: ©StrangeBee - https://www.strangebee.com

---

"

THEHIVE="---
Following softwares are being installed & configured:
  - Cassandra ${CASSANDRA_VERSION}
  - Elasticsearch ${ELASTICSEARCH_VERSION}
  - TheHive ${THEHIVE_VERSION}
"

CORTEX="---
Following softwares are being installed & configured:
  - Elasticsearch ${ELASTICSEARCH_VERSION}
  - Cortex ${CORTEX_VERSION}
  - Docker engine (optional)
  - Cortex-Analyzers and their dependencies (optional)
"

############################
# MANAGE LOG FILE & OUTPUT #
############################

[[ -f ${LOGFILE} ]] && rm ${LOGFILE}
exec 3>$(tty)
exec &> ${LOGFILE}
POLICY_RCD_INSTALLED=false

function clean_up {
  [[ "${POLICY_RCD_INSTALLED}" == true ]] && rm -f /usr/sbin/policy-rc.d
  exit 0
}
trap clean_up EXIT

alias yum="yum -yq"
alias dnf="dnf -yq"

die() {
  [[ -n "$1" ]] && log error "$1"
  log error "Something went wrong. More information is available in ${LOGFILE} file."
  exit 1
}

# Ensure the script is not executed as root
deny_root_execution() {
  if [[ $(id -u) -eq 0 ]]; then
    die "This script must not be run as root. Please execute it as a non-privileged user ; refer to the documentation: https://docs.strangebee.com/thehive/installation/automated-installation-script/#using-the-installation-script"
    exit 1
  fi
}

IP=$(hostname -I | cut -d ' ' -f 1)

display-cortex-success() {
  log success "
  ---
  Cortex installation is complete!

  Connect to http://${IP}:9001 and start configuring the application. Create a global Admin account, and then Organisations and users ; then enable some Analyzers and Responders.


  Information:
  Cortex is installed with basic configuration parameters. It is configured to use:
  - local accounts for authentication
  - Docker to run Analyzers & Responders programs

  If proxy settings have been configured, the OS, Cortex and Docker (if installed) have been configured to use it. You will have to configure Analyzers & Responders with proxy settings if required.


  Warning :
  No specific security measures have been added. Xpack in Elasticsearch is disabled, and Cortex is accessing this service anonymously and using clear communication protocol. Please have a look at the documentation to secure the environment.


  Documentation:
  https://docs.strangebee.com


  Troublesoot:
  More information is available in /tmp/install.log file.\n
  "
}

display-thehive-success() {
  log success "
  ---
  TheHive installation is complete!

  Connect to http://${IP}:9000 and start configuring the application. Create a global Admin account, and then Organisations and users.


  Information:
  TheHive is installed with basic configuration parameters. It is configured to usel local accounts for authentication ;

  Default login/password is: admin/secret

  If proxy settings have been configured, the OS has been configured to use it.


  Warning :
  No specific security measures have been added. Xpack in Elasticsearch is disabled. TheHive is Cassandra and Elasticsearch services anonymously and using clear communication protocol. Please have a look at the documentation to secure the environment.


  Documentation:
  https://docs.strangebee.com


  Troublesoot:
  More information is available in /tmp/install.log file.\n
  "
}

log () {
  TYPE=$1
  MESSAGE=$2

  case $1 in
    "success" )
      echo -e "${MESSAGE}"
      echo -e "${WHITE}${MESSAGE}${NC}" >&3
      ;;
    "error" )
      echo -e "[ERROR]: ${MESSAGE}"
      echo -e "${RED}[ERROR]${NC} ${MESSAGE}" >&3
      ;;
    "info" )
      echo -e "[INFO]: ${MESSAGE}"
      echo -e "${BLUE}[INFO]${NC} ${MESSAGE}" >&3
      ;;
    "message" )
      echo -e "[INFO]: ${MESSAGE}"
      echo -e "${BLUE}[INFO]${NC} ${MESSAGE}" >&3
      ;;
    "warning" )
      echo -e "[WARNING]: ${MESSAGE}"
      echo -e "${YELLOW}[WARNING]${NC} ${MESSAGE}" >&3
      ;;
    "question" )
      echo -e "[ASK]: ${MESSAGE}"
      echo -ne "${CYAN}[ASK]${NC} ${MESSAGE}" >&3
      ;;
    "debug")
      echo -e "[DEBUG]: ${MESSAGE}"
      ;;
  esac
}

pkg-install() {
  PACKAGE_NAME=$@
  log debug "Installing ${PACKAGE_NAME}"
  if [[ "${PACKAGE_TYPE}" == "rpm" ]]; then
    $SUDO yum install -yq -e 0 ${PACKAGE_NAME}        || die
  elif [[ "${PACKAGE_TYPE}" == "deb" ]]; then
    case "${PACKAGE_NAME}" in
      http*)
        TEMP_DEB="$(mktemp)" &&
        wget -O "${TEMP_DEB}" "${PACKAGE_NAME}" &&
        $SUDO dpkg -i "${TEMP_DEB}"
        RET=$?
        rm -f "${TEMP_DEB}"
        [[ "${RET}" -ne 0 ]] && die "Unable to install package ${PACKAGE_NAME}"
        ;;
      *)
        $SUDO apt update -qq                           || die
        $SUDO apt install -yqq ${PACKAGE_NAME}         || die
        ;;
    esac
  fi
}

install-product() {
  PRODUCT="$1"

  case "${PRODUCT}" in
    thehive) PRODUCT_VERSION="${THEHIVE_VERSION}" ;;
    cortex)  PRODUCT_VERSION="${CORTEX_VERSION}"  ;;
    *)       die "Invalid product (${PRODUCT})"   ;;
  esac
  case "${PACKAGE_TYPE}" in
    deb) FILE_NAME="${PRODUCT}_${PRODUCT_VERSION}_all.${PACKAGE_TYPE}"    ;;
    rpm) FILE_NAME="${PRODUCT}-${PRODUCT_VERSION}.noarch.${PACKAGE_TYPE}" ;;
    *)       die "Invalid package type (${PACKAGE_TYPE})"                 ;;
  esac
  FILE_NAME=$(sed -e 's/\+/%2B/g' <<< ${FILE_NAME})

  MINOR_VERSION=$(awk -F. '{print $1"."$2}' <<< ${PRODUCT_VERSION})
  pkg-install "https://${PRODUCT}.${BASE_URL}/${MINOR_VERSION}/${PACKAGE_TYPE}/${FILE_NAME}"
}

# Start service, wait for it to be available and enable it
start-service() {
  SERVICENAME=$1

  log message "* Starting service ${SERVICENAME}"
  $SUDO systemctl is-active "${SERVICENAME}" && \
    $SUDO systemctl -q restart "${SERVICENAME}" || \
    $SUDO systemctl -q start "${SERVICENAME}"

  if [[ -n "$2" && -z "${DONT_CHECK_SERVICE_PORT}" ]]
  then
    SERVICEPORT=$2
    count=0
    while ! ss -antl | grep -q "LISTEN.*:${SERVICEPORT}[[:space:]]"
    do
      count=$((${count}+1))
      if [[ ${count} -eq 60 ]]
      then
        die " ${SERVICENAME} not started, exiting."
      else
        sleep 5
      fi
    done
  fi

  $SUDO systemctl -q enable "${SERVICENAME}" || die
}

## REQUIRED PACKAGES
install-required-packages() {
  log message "Installing required system packages"
  if [[ "${PACKAGE_TYPE}" == "rpm" ]]; then
    pkg-install gnupg chkconfig python3-pip git wget
  elif [[ "${PACKAGE_TYPE}" == "deb" ]]; then
    pkg-install wget gnupg apt-transport-https git \
      ca-certificates curl jq software-properties-common \
      lsb-release python3-pip python3-venv iproute2 wget
  fi
}

## INSTALL JAVA
install-java() {
  log message "Installing Java"
  if [[ "${PACKAGE_TYPE}" == "rpm" ]]; then
    $SUDO rpm --import https://yum.corretto.aws/corretto.key &> /dev/null || die
    wget -qO- https://yum.corretto.aws/corretto.repo | \
      $SUDO tee /etc/yum.repos.d/corretto.repo                            || die
    pkg-install java-11-amazon-corretto-devel &> /dev/null
    echo JAVA_HOME="/usr/lib/jvm/java-11-amazon-corretto" | \
      $SUDO tee -a /etc/environment                                       || die
    export JAVA_HOME="/usr/lib/jvm/java-11-amazon-corretto"
  elif [[ "${PACKAGE_TYPE}" == "deb" ]]; then
    [[ -e /usr/share/keyrings/corretto.gpg ]] || \
      wget -qO- https://apt.corretto.aws/corretto.key | \
      $SUDO gpg --dearmor -o /usr/share/keyrings/corretto.gpg             || die
    echo "deb [signed-by=/usr/share/keyrings/corretto.gpg] https://apt.corretto.aws stable main" | \
      $SUDO tee /etc/apt/sources.list.d/corretto.sources.list             || die
    pkg-install java-common java-11-amazon-corretto-jdk
    echo JAVA_HOME="/usr/lib/jvm/java-11-amazon-corretto" | \
      $SUDO tee -a /etc/environment                                       || die
    export JAVA_HOME="/usr/lib/jvm/java-11-amazon-corretto"
  fi
}

## CASSANDRA INSTALLATION
install-cassandra() {
  log message "Installing Cassandra"
  if [[ "${PACKAGE_TYPE}" == "rpm" ]]; then
    $SUDO rpm --import https://downloads.apache.org/cassandra/KEYS &> /dev/null || die
    cat <<EOF | $SUDO tee /etc/yum.repos.d/cassandra.repo > /dev/null           || die
[cassandra]
name=Apache Cassandra
baseurl=https://redhat.cassandra.apache.org/$(tr -d '\.' <<< ${CASSANDRA_VERSION})/
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://downloads.apache.org/cassandra/KEYS
EOF
  elif [[ "${PACKAGE_TYPE}" == "deb" ]]; then
    [[ -e /usr/share/keyrings/cassandra-archive.gpg ]] || \
      wget -qO - https://downloads.apache.org/cassandra/KEYS | \
      $SUDO gpg --dearmor -o /usr/share/keyrings/cassandra-archive.gpg         || die
    echo "deb [signed-by=/usr/share/keyrings/cassandra-archive.gpg] https://debian.cassandra.apache.org $(tr -d '\.' <<< ${CASSANDRA_VERSION}) main" | \
      $SUDO tee /etc/apt/sources.list.d/cassandra.sources.list                 || die
  fi
  pkg-install cassandra
}

# ## CQLSH
# install-cqlsh() {
#   if [[ "${PACKAGE_TYPE}" == "rpm" ]]; then
#     log message "Installing cqlsh"
#     $SUDO pip3 install -q cqlsh || die
#   fi      # Not needed for DEB packages, installed with Cassandra
# }

## CQLSH WITH VENV
install-cqlsh() {
  log message "Setting up virtualenv for cqlsh"

  # Define virtualenv directory
  VENV_DIR="${HOME}/cqlsh_env"

  # Create virtualenv if it doesn't exist
  if [[ ! -d "${VENV_DIR}" ]]; then
    # $SUDO python3 -m pip install --quiet virtualenv || die "Failed to install virtualenv"
    python3 -m venv "${VENV_DIR}" || die "Failed to create virtualenv for cqlsh"
  fi

  # Activate virtualenv and install cqlsh
  "${VENV_DIR}/bin/pip" install --quiet cqlsh || die "Failed to install cqlsh in virtualenv"

  log message "cqlsh installed in virtualenv: ${VENV_DIR}"
}


## CASSANDRA CONFIGURATION
configure-cassandra() {
  log message "Configuring cassandra"
  if [[ "${PACKAGE_TYPE}" == "rpm" ]]; then
    $SUDO sed -i "s/\(cluster_name:\ \).*/\1\'thp\'/g" /etc/cassandra/default.conf/cassandra.yaml || die
  elif [[ "${PACKAGE_TYPE}" == "deb" ]]; then
    $SUDO systemctl stop cassandra                                                                || die
    $SUDO rm -rf /var/lib/cassandra/*
    $SUDO sed -i "s/\(cluster_name:\ \).*/\1\'thp\'/g" /etc/cassandra/cassandra.yaml              || die
  fi
  $SUDO chown -R cassandra:cassandra /var/lib/cassandra                                           || die
}

## Remove tombstones (for standalone server ONLY)
remove-cassandra-tombstone() {
  log message "Removing tombstones in Cassandra"
  
  # Activate virtualenv
  VENV_DIR="${HOME}/cqlsh_env"
  if [[ -d "${VENV_DIR}" ]]; then
    CQLSH="${VENV_DIR}/bin/cqlsh"
  else
    die "Virtualenv for cqlsh not found. Run 'install-cqlsh' first."
  fi
  
  for TABLE in edgestore edgestore_lock_ graphindex graphindex_lock_ janusgraph_ids system_properties system_properties_lock_ systemlog txlog
  do
    "$CQLSH" -u cassandra -p cassandra -e "ALTER TABLE thehive.${TABLE} WITH gc_grace_seconds = 0;" || die
  done
  
  deactivate
}


## INSTALL ELASTICSEARCH
install-elasticsearch() {
  log message "Installing Elasticsearch"
  ESOPTS=""
  if [[ "${PACKAGE_TYPE}" == "rpm" ]]; then
    $SUDO rpm --import https://artifacts.elastic.co/GPG-KEY-elasticsearch &> /dev/null || die
    cat <<EOF | $SUDO tee /etc/yum.repos.d/elasticsearch.repo                          || die
[elasticsearch]
name=Elasticsearch repository for ${ELASTICSEARCH_VERSION} packages
baseurl=https://artifacts.elastic.co/packages/${ELASTICSEARCH_VERSION}/yum
gpgcheck=1
gpgkey=https://artifacts.elastic.co/GPG-KEY-elasticsearch
enabled=0
autorefresh=1
type=rpm-md
EOF
    ESOPTS="--enablerepo=elasticsearch"
  elif [[ "${PACKAGE_TYPE}" == "deb" ]]; then
    [[ -e /usr/share/keyrings/elasticsearch-keyring.gpg ]] || \
      wget -qO - https://artifacts.elastic.co/GPG-KEY-elasticsearch | \
      $SUDO gpg --dearmor -o /usr/share/keyrings/elasticsearch-keyring.gpg             || die
    echo "deb [signed-by=/usr/share/keyrings/elasticsearch-keyring.gpg] https://artifacts.elastic.co/packages/${ELASTICSEARCH_VERSION}/apt stable main" | \
      $SUDO tee /etc/apt/sources.list.d/elastic-${ELASTICSEARCH_VERSION}.list          || die
  fi
  pkg-install ${ESOPTS} elasticsearch
}

## ELASTICSEARCH CONFIGURATION
configure-elasticsearch() {
  log message "Configuring elasticsearch"
  if [[ "${PACKAGE_TYPE}" == "deb" ]]; then
    $SUDO systemctl stop elasticsearch                                   || die
    $SUDO rm -rf /var/lib/elasticsearch/*                                || die
  fi   # Not required for RPM packages
  cat << EOF | $SUDO tee /etc/elasticsearch/elasticsearch.yml            || die
http.host: 127.0.0.1
discovery.type: single-node
cluster.name: hive
thread_pool.search.queue_size: 100000
thread_pool.write.queue_size: 100000
bootstrap.memory_lock: true
path.logs: "/var/log/elasticsearch"
path.data: "/var/lib/elasticsearch"
xpack.security.enabled: false
script.allowed_types: "inline,stored"
EOF

  cat << EOF | $SUDO tee -a /etc/elasticsearch/jvm.options.d/jvm.options || die
-Dlog4j2.formatMsgNoLookups=true
-Xms4g
-Xmx4g
EOF
}

## CREATE THEHIVE FILE STORAGE
creating-thehive-file-storage() {
  log message "Configuring TheHive"
  $SUDO mkdir -p /opt/thp/thehive/files                 || die
  $SUDO chown -R thehive:thehive /opt/thp/thehive/files || die
}

## INSTALL DOCKER
install-docker() {
  log message "Installing Docker"
  if [[ "${PACKAGE_TYPE}" == "rpm" ]]; then
    $SUDO yum remove -yq docker \
                    docker-client \
                    docker-client-latest \
                    docker-common \
                    docker-latest \
                    docker-latest-logrotate \
                    docker-logrotate \
                    docker-engine
    pkg-install dnf-plugins-core
    OS=$(cat /etc/redhat-release | cut -d ' ' -f 1)
    if [[ ${OS} == 'Fedora' ]]; then
      $SUDO dnf config-manager \
        --add-repo \
        https://download.docker.com/linux/fedora/docker-ce.repo &> /dev/null || die
    else
      $SUDO dnf config-manager \
        --add-repo \
        https://download.docker.com/linux/centos/docker-ce.repo &> /dev/null || die
    fi
    pkg-install docker-ce docker-ce-cli containerd.io docker-compose-plugin
  elif [[ "${PACKAGE_TYPE}" == "deb" ]]
  then
    [[ -e /usr/share/keyrings/docker-archive-keyring.gpg ]] || \
      curl -fsSL https://download.docker.com/linux/debian/gpg | \
      $SUDO gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg   || die
    if [[ $(lsb_release -i | cut -d ':' -f 2) == 'Ubuntu' ]]; then
      DISTRIB=ubuntu
    else
      DISTRIB=debian
    fi
    echo \
      "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] \
      https://download.docker.com/linux/${DISTRIB} \
      $(lsb_release -cs) stable" | \
      $SUDO tee /etc/apt/sources.list.d/docker.list                           || die
    pkg-install docker-ce
  fi

  if [[ "${PROXYCONFIGURED}" == true ]]
  then
    $SUDO mkdir -p /etc/systemd/system/docker.service.d
    cat << EOF | $SUDO tee /etc/systemd/system/docker.service.d/http-proxy.conf
[Service]
Environment="HTTP_PROXY=${PROXYURL}"
Environment="HTTPS_PROXY=${PROXYURL}"
EOF
    $SUDO systemctl daemon-reload
    $SUDO systemctl restart docker
  fi
}

## Install PYTHON LIBS
install-python-libs() {
  log message "Installing python libs"
  $SUDO pip3 install --break-system-packages cortex4py cortexutils
}

## CONFIGURE CORTEX (using public neurons as Docker images)
configure-cortex() {
  log message "Configuring cortex"
  # DOCKER PERMISSIONS
  $SUDO usermod -G docker cortex                                                     || die
  $SUDO mkdir -p /opt/Custom-Analyzers/{analyzers,responders}                        || die
  $SUDO chown -R cortex:cortex /opt/Custom-Analyzers                                 || die

  $SUDO systemctl -q stop cortex
  if [[ ! -e /etc/cortex/secret.conf ]]; then
    key=$(dd if=/dev/urandom bs=1024 count=1 | tr -dc 'a-zA-Z0-9' | fold -w 64 | head -n 1)
    echo "play.http.secret.key=\"$key\"" | $SUDO tee /etc/cortex/secret.conf         || die
    $SUDO sed -i \
      -e 's_#play\.http\.secret\.key=.*$_include\ \"/etc/cortex/secret\.conf\"_' \
      -e 's/\(.*analyzers.json\"\)$/\1,/' \
      -e '/.*analyzers.json\",/a \\t\"/opt/Custom-Analyzers/analyzers\"' \
      -e 's/\(.*responders.json\"\)$/\1,/' \
      -e '/.*responders.json\",/a \\t\"/opt/Custom-Analyzers/responders\"' \
      /etc/cortex/application.conf                                                   || die
  fi

  ## Update configuration with proxy, if any
  if [[ "${PROXYCONFIGURED}" == true ]]; then
    log message "Updating Cortex configuration: proxy host & port settings"
    cat <<EOF | $SUDO tee -a /etc/cortex/application.conf                            || die
#
# Proxy configuration to retrieve catalogs
play.ws.proxy {
   host = "${PROXYHOST}"
   port = "${PROXYPORT}"
}
EOF
    if [[ -n "${PROXYCONFIGURED}" ]]; then
      cat <<EOF | $SUDO tee -a /etc/cortex/application.conf                          || die
play.ws.proxy {
  principal = "${PROXYUSERNAME}"
  password = "${PROXYPASSWORD}"
}
EOF
    fi
  else
    log message "Updating Cortex configuration: No proxy setting configured"
  fi
}

## CONFIGURE CORTEX (using public neurons as programs run locally)

configure-cortex-without-catalogs() {
  log message "Updating Cortex configuration: remove catalogs and add local path for public neurons"
  $SUDO sed -i \
    -e 's_\".*analyzers.json\",$_\"/opt/Cortex-Analyzers/analyzers\",_' \
    -e 's_\".*responders.json\",$_\"/opt/Cortex-Analzers/responders\",_' \
    /etc/cortex/application.conf || die
}


configure-proxy-git () {
  log message "Configuring git with proxy settings"
  $SUDO git config --global http.proxy "${PROXYURL}"  || die
  $SUDO git config --global https.proxy "${PROXYURL}" || die
}

## INSTALL PUBLIC ANALYZERS/RESPONDERS AND THEIR DEPENDENCIES

install-neurons() {
  log message "Installing public Cortex neurons in /opt/Cortex-Analyzers and their dependencies"
  PIPPROXY=""
  ## Configure proxy if any

  if [[ -n "${PROXYURL}" ]]; then
    log message "Adding proxy settings for pip command"
    PIPPROXY="--proxy ${PROXYURL}"
  fi
  ## Configure alternate CA bundle if any
  if [[ -n "${CACERT}" ]]; then
    PIPPROXY="${PIPPROXY} --cert ${CACERT}"
  fi

  ## Install required packages
  log message "Installing Cortex neurons system packages dependencies"
  if [[ "${PACKAGE_TYPE}" == "deb" ]]; then
    pkg-install unzip curl libimage-exiftool-perl wkhtmltopdf libboost-regex-dev \
    libboost-program-options-dev libboost-system-dev libboost-filesystem-dev \
     libssl-dev build-essential cmake libfuzzy-dev clamav clamav-daemon
  fi

  ### Install specific programs required by some analyzers
  curl -SL https://github.com/mandiant/flare-floss/releases/download/v2.0.0/floss-v2.0.0-linux.zip --output /tmp/floss.zip || die
  unzip /tmp/floss.zip -d /usr/bin                                                                                         || die

  log message "Installing Cortex neurons programs in /opt/Cortex-Analyzers"
  (cd /opt && $SUDO git clone https://github.com/TheHive-Project/Cortex-Analyzers.git)                                      || die
  $SUDO chown -R cortex:cortex /opt/Cortex-Analyzers                                                                        || die

  log message "Installing Cortex neurons dependencies"
  awk '{print $0}' /opt/Cortex-Analyzers/*/*/requirements.txt | \
    while read line ; do
      echo -e "$line\n" | \
        awk -F "[=]{2}|[<>~;]{1}" ' { print $1 } ' | \
        ## TODO: REMOVE AFTER Cortex-Analyzers 3.2 is released
        tr -d '\r'
    done | \
      grep -v -E "enum|future" | \
      ## TODO: REMOVE AFTER Cortex-Analyzers 3.2 is released
      grep -v "git+https://github.com/fireeye/stringsifter.git@python3.7#egg=stringsifter" | \
      sort -u > /tmp/requirements.txt
      ## TODO: REMOVE AFTER Cortex-Analyzers 3.2 is released
  echo "stringsifter" >> /tmp/requirements.txt
  pip3 install ${PIPPROXY} -r /tmp/requirements.txt
}


## FIREWALLD
configure-firewalld-cortex() {
  if [[ "${PACKAGE_TYPE}" == "rpm" ]] && which firewall-cmd; then
    $SUDO firewall-cmd --add-port=$1/tcp       || die
    $SUDO firewall-cmd --runtime-to-permanent  || die
    log message "* Firewalld rules updated"
  fi  # Not required for Ubuntu and Debian
}

reload-services() {
  $SUDO systemctl daemon-reload                || die
}

### START AND ENABLE DOCKER
start-enable-docker() {
  start-service docker                        || die
}

### START AND ENABLE ELASTICSEARCH
start-enable-elasticsearch(){
  start-service elasticsearch 9200            || die
}

### START AND ENABLE THEHIVE
start-enable-cassandra() {
  start-service cassandra 9042                || die
}

### START AND ENABLE THEHIVE
start-enable-thehive() {
  start-service thehive 9000                  || die
}

### START AND ENABLE CORTEX
start-enable-cortex() {
  start-service cortex 9001                   || die
}

require-confirmation() {
  log question "Do you want to continue? [yes/NO] "
  read CONFIRMATION
  [[ "$CONFIRMATION" == "yes" ]] || exit 1
}

check-installed-application() {
  INSTALLING=$1
  OTHER=$2
  if [[ -d "/etc/${INSTALLING}" && -d "/opt/${INSTALLING}" ]]; then
    log error "${INSTALLING} is already installed on the system. Exiting ..."
    exit 1
  fi

  if [[ -n "${OTHER}" && -d "/etc/${$OTHER}" && -d "/opt/${OTHER}" ]]; then
    log warning "${OTHER} is already installed. It is not recommended to install both ${INSTALLING} and ${OTHER} in the same host."
    require-confirmation
  fi
}

## CHECK AVAILABLE RESOURCES
check-available-resources() {
  NBPROC=$(nproc)
  RAM=$(awk '/MemTotal/{ print $2 }' /proc/meminfo)
  NEED_CONFIRMATION=false
  if [[ "${NBPROC}" -lt "${MINREQCPU}" ]]; then
    log warning "4 CPU cores is required but you only have ${NBPROC}"
    NEED_CONFIRMATION=true
  fi
  if [[ "${RAM}" -lt "${MINREQRAM}" ]]; then
    log warning "16GB of memory is required but you only have $((${RAM}/1048576))GB"
    NEED_CONFIRMATION=true
  fi
  if [[ "${NEED_CONFIRMATION}" == true ]]; then
    log warning "Your system doesn't meet the requirements"
    require-confirmation
  fi
}

prevent-service-to-start-at-install() {
  if [[ -e /usr/sbin/policy-rc.d ]]; then
    log warning "The file /usr/sbin/policy-rc.d already exists. The service may start when installed"
  else
    cat <<EOF | $SUDO tee /usr/sbin/policy-rc.d || die
#!/bin/sh
exit 101
EOF
    POLICY_RCD_INSTALLED=true
    chmod a+x /usr/sbin/policy-rc.d             || die
  fi
}

check-supported-os() {
  DIST=$(awk -F= '/^ID=/{ gsub("\"", ""); print $2 }' /etc/os-release)
  VERSION=$(awk -F= '/^VERSION_ID=/{ gsub("\"", ""); print $2 }' /etc/os-release)

  if [[ " ${OSDEB[*]} " =~ [[:space:]]"${DIST}"[[:space:]] ]]; then
    PACKAGE_TYPE="deb"
  elif [[ " ${OSRPM[*]} " =~ [[:space:]]"${DIST}"[[:space:]] ]]; then
    PACKAGE_TYPE="rpm"
  else
    log error "The current operating system (${DIST} ${VERSION}) is not suported. Check supported OS on https://docs.strangebee.com"
    exit 1
  fi
  if [[ ! " ${OSRPM[*]} ${OSDEB[*]} " =~ [[:space:]]"${DIST} ${VERSION}"[[:space:]] ]]; then
    log warning "The current linux distribution (${DIST} ${VERSION}) is detected as type \"${PACKAGE_TYPE}\" but this script has not been tested on it."
    log warning "It might not work or even break your system."
    log warning "The supported distributions are:"
    for I in "${OSRPM[@]}" "${OSDEB[@]}"; do log warning "- $I"; done
    require-confirmation
  fi
}

check-requirements() {
  if which sudo; then
    SUDO=sudo
  else
    if [[ "${UID}" -eq 0 ]]; then
      SUDO=""
      log info 'The command "sudo" is missing but it is not required'
    else
      log error 'The command "sudo" is missing'
      exit 1
    fi
  fi
  for CMD in ss systemctl nproc
  do
    if ! which "${CMD}" &> /dev/null; then
      log error 'The required command "'"${CMD}"'" is missing'
      exit 1
    fi
  done
}

#########################################################
# Recipe: Cortex using Docker images for public Neurons #
#########################################################

prepare-installation() {
  log question "Proxy host (hostname or IP address): "
  read PROXYHOST
  if [[ -n "${PROXYHOST}" ]]; then
    log question "Proxy port: "
    read PROXYPORT
    log question "Full path to CA Certificate (/path/to/ca.crt): "
    read CACERT
    log question "Proxy Username: "
    read PROXYUSERNAME
    if [[ -n "${PROXYUSERNAME}" ]]; then
      log question "Proxy Password: "
      read -s PROXYPASSWORD
    fi

    log info "Installation will be processed with following settings:"
    log info "Proxy host: ${PROXYHOST}"
    log info "Proxy port: ${PROXYPORT}"
    log info "CA Cert path: ${CACERT}"
    [[ -n "${PROXYUSERNAME}" ]] && log info "Proxy username: ${PROXYUSERNAME}"

    ## PROXY FOR RHEL / FEDORA & yum COMMAND
    if [[ "${PROXYCONFIGURED}" == true ]]; then
      log info "Configuring proxy: updating /etc/environment"
      [[ -z "${PROXYUSERNAME}" ]] && \
        PROXYURL="http://${PROXYHOST}:${PROXYPORT}" || \
        PROXYURL="http://${PROXYUSERNAME}:${PROXYPASSWORD}@${PROXYHOST}:${PROXYPORT}"

        cat << EOF | $SUDO tee -a /etc/environment
export http_proxy=${PROXYURL}
export https_proxy=${PROXYURL}
EOF
      export http_proxy="${PROXYURL}"
      export https_proxy="${PROXYURL}"

      [[ "${PACKAGE_TYPE}" == "deb" ]] && \
        cat << EOF | $SUDO tee -a /etc/apt/apt.conf.d/80proxy
Acquire {
  http::proxy "${PROXYURL}";
  https::proxy "${PROXYURL}";
}
EOF
    fi
    if [[ -n "${CACERT}" && "${PACKAGE_TYPE}" == "rpm" ]]; then
      ### Install CA Certificate
      log info "Installing CA certificate"
      $SUDO cp "${CACERT}" /etc/pki/ca-trust/source/anchors
      $SUDO update-ca-trust
    elif ( [ -n "${CACERT}" ] && [ "${PACKAGE_TYPE}" == "deb" ] ); then
      # pkg install ca-certificates-java
      log info "Installing CA certificate"
      $SUDO cp" ${CACERT}" /usr/local/share/ca-certificates/my-certificate.crt
      $SUDO update-ca-certificates
    fi

    PROXYCONFIGURED=true
  else
    log info "No proxy is configured"
    unset http_proxy
    unset https_proxy
    PROXYCONFIGURED=false
  fi
}

recipe-cortex() {
  check-available-resources
  check-installed-application cortex
  clear >&3
  log success "Installing Cortex ..."
  log success "${CORTEX}"
  install-required-packages
  [[ "${PROXYCONFIGURED}" == true ]]  && configure-proxy-git
  install-elasticsearch
  configure-elasticsearch
  [[ "${USEDOCKERIMAGES}" == true ]]  && install-docker
  [[ "${USEDOCKERIMAGES}" == false ]] && install-python-libs
  install-product cortex
  configure-cortex
  [[ "${USEDOCKERIMAGES}" == false ]] && install-neurons
  [[ "${USEDOCKERIMAGES}" == false ]] && configure-cortex-without-catalogs
  configure-firewalld-cortex 9001
  reload-services
  [[ "${USEDOCKERIMAGES}" == true ]]  && start-enable-docker
  start-enable-elasticsearch
  start-enable-cortex
  display-cortex-success
  exec 3>&-
  exit 0
}

recipe-thehive() {
  check-available-resources
  check-installed-application thehive
  clear >&3
  log success "Installing TheHive ..."
  log success "${THEHIVE}"
  install-required-packages
  install-java
  install-cassandra
  install-cqlsh
  configure-cassandra
  install-elasticsearch
  configure-elasticsearch
  install-product thehive
  creating-thehive-file-storage
  configure-firewalld-cortex 9000
  reload-services
  start-enable-cassandra
  start-enable-elasticsearch
  start-enable-thehive
  [[ -z "${DONT_REMOVE_CASSANDRA_TOMBSTONE}" ]] && remove-cassandra-tombstone
  display-thehive-success
  exec 3>&-
  exit 0
}

#######
# RUN #
#######

## HEADER
clear >&3
deny_root_execution
check-requirements
check-supported-os
log success "${HEADER}"
while [[ "${REPLY}" != "5" ]]; do
  echo '1) Setup proxy settings'                      >&3
  echo '2) Install TheHive'                           >&3
  echo '3) Install Cortex (run Neurons with docker)'  >&3
  echo '4) Install Cortex (run Neurons locally)'      >&3
  echo '5) Quit'                                      >&3
  echo -n 'Select an option: '                        >&3
  [[ -z "${REPLY}" ]] && read REPLY
  case "${REPLY}" in
    "1" )
      prepare-installation
      ;;
    "2" )
      recipe-thehive
      ;;
    "3" )
      USEDOCKERIMAGES=true
      recipe-cortex
      ;;
    "4" )
      if [[ "${PACKAGE_TYPE}" == "rpm" ]]; then
        log error "Unfortunately, this is not supported on RHEL and Fedora. Use Ubuntu or Debian for this recipe, or use neurons as docker images."
      else
        USEDOCKERIMAGES=false
        recipe-cortex
      fi
      ;;
    "5" )
      ;;
    * )
      log warning "invalid option ${REPLY}"
      ;;
  esac
  REPLY=
done
