#!/usr/bin/env bash
#
# Скрипт установки linux-агента для Vulns.io VM
#

# Лог файл
LOG_FILE=/tmp/deploy-linuxsc.txt

# Временный файл с инсталлятором
FILE_TMP=agent-installer_$$.sh

# IP адрес сервера OnPremise
SERVER_IP=192.168.100.100

# Ключ для доступа к API
# Находится на сервере OnPremise в файле /opt/vulns.io/onpremise/config/main/credentials.ini
API_KEY="sadfghkj12312qwe"

# Указать Sensor ID, если агенты будут работать через сенсор
SENSOR_ID=""

# accountid - имя аккаунта в базе OnPremise
# По умолчанию accountid="0" - суперпользователь
accountid="0"

# userid - имя пользователя в базе OnPremise
# По умолчанию userid="0" - суперпользователь
userid="0"

# Имена сервисов агента для проверки их работоспособности
agent_service_name="vulns.io-agent-linux"
updater_service_name="vulns.io-agent-updater-linux"

# Параметр 'DELETE_ASSET_IF_INSTALL_FAIL' определяет поведение скрипта в случае если службы агента не запустились.
#  Значение 1 - указывает, что в случае не удачного запуска службы (по любой причине) удаляем установленный агент и очищаем из базы данных OnPremise asset и agent
#  Значение 0 - не предпринимаем никаких действий по удалению агента
DELETE_ASSET_IF_INSTALL_FAIL=1

# Разрешено ли выводить информацию о действиях скрипта на экран или в лог-файл
LOG_TO_SCREEN=1
LOG_TO_FILE=1

# коды выхода из скрипта
# =0  - Агент установлен и запущен в системе корректно
# =4  - Не найдена команда curl для работы с API OnPremise
# =8  - Пользователь не входит в группу 'root', необходимого для создания служб агентов в системе и их запуска
# =16 - Вызов справки по аргументам запуска скрипта
# =32 - Ошибка доступа к API OnPremise
# =64 - Ошибка скачивания инсталятора агента с сервера OnPremise

out_data_log() {
  # Вывод информации о работе скрипта на экран или в лог-файл в зависимости от переменных LOG_TO_SCREEN и LOG_TO_FILE
  if [ $LOG_TO_SCREEN -eq 1 ]; then
    echo $1
  fi
  if [ $LOG_TO_FILE -eq 1 ]; then
    echo $1 >>$LOG_FILE
  fi
}

init() {
  # Проверка существования curl. Необходимо для доступа к API OnPremise через протокол https.

  if ! command -v curl >/dev/null; then
    out_data_log "Attention: You may need to install curl for the deploy script!"
    exit 4
  fi

  # Проверка суперправ у пользователя запустившего скрипт
  if groups | grep -q "\broot\b"; then
    out_data_log "The corrent user is in group 'root'. Continuing the work of the script"
  else
    out_data_log "Attention - the user is not in the 'root' group!"
    exit 8
  fi

  if [[ -n "$1" ]]; then
    echo " "
    echo "Требуется указать корректный аргумент вызова скрипта"
    echo "Команды запуска скрипта:"
    echo $(basename $0)"  [ -h | --help ]"
    echo $'\t'"где '--help или -h '"$'\t'" - вызов этой справки по командам"
    exit 16
  fi

  # Получаем текущий IP-адрес машины
  IP_ADR=$(hostname --all-ip-addresses | awk '{print $1}')
  out_data_log "Current IP="$IP_ADR
}

check_response_api() {
  # Проверка ответа от API и результата выполнения curl

  #  если после вызова curl получаем код ошибки больше 0, то сообщаем об ошибки доступности API
  if [ $1 -ne 0 ]; then
    if [ $1 -eq 22 ]; then
      out_data_log "Request failure. API OnPremise not available, response code >= 400"
    else
      out_data_log "CURL: Error code = "$1
    fi
    RETURN_VAL="error"
  else
    RETURN_VAL="ok"
  fi
}

get_installer() {
  # Отправка запроса на скачивание установщика и получение его url
  local osType="linux"

  GET_URL=$(curl -X GET -k "https://$SERVER_IP/integration/v1/agents/download/installer/url?osType=$osType&accountId=$accountid&userId=$userid&sensorId=$SENSOR_ID" -H "Content-Type: application/json" -H "x-api-key: $API_KEY" --compressed -s)

  check_response_api $?

  if [ "$RETURN_VAL" == "error" ]; then
    out_data_log "Error send request to API OnPremise, server IP "$SERVER_IP
    # Если после первого обращения к API сервер был не доступен, то прекращаяем выполнения скрипта, считая, что проблемы с сетевым доступом или сервером OnPremise
    exit 32
  fi

  url_id=$(echo $GET_URL | sed -e "s/^.*url\"\:\"//g" | sed -e "s/\".*$//g")
  agentid=$(echo $GET_URL | sed -e "s/^.*agentId\"\:\"//g" | sed -e "s/\".*$//g")
  assetid=$(echo $GET_URL | sed -e "s/^.*assetId\"\:\"//g" | sed -e "s/\".*$//g")
}

delete_asset() {
  # Удаление asset'а

  # assetId - получить из ответа полученного при создании агента

  ASSET=$(curl -X DELETE -k "https://$SERVER_IP/integration/v1/assets/$assetid" -H "Content-Type: application/json" -H "x-api-key: $API_KEY" --compressed -s)

  check_response_api $?

  if [ "$RETURN_VAL" == "error" ]; then
    out_data_log "Error deleting asset '$assetid' data in database OnPremise, server IP $SERVER_IP"
  else
    out_data_log "Asset deleted correctly."
  fi

}

delete_agent() {
  # Удаление agent'а

  # agentId - получить из ответа полученного при создании агента

  AGENT=$(curl -X DELETE -k "https://$SERVER_IP/integration/v1/agents/$agentid" -H "Content-Type: application/json" -H "x-api-key: $API_KEY" --compressed -s)

  check_response_api $?

  if [ "$RETURN_VAL" == "error" ]; then
    out_data_log "Error deleting agent '$agentid' data in database OnPremise, server IP $SERVER_IP"
  else
    out_data_log "Agent deleted correctly."
  fi
}

deploy_agent() {
  # Скачивание и запуск установки Linux-установщика

  out_data_log "---- Download and deploy agent installer ----"
  # Скачиваем файл, игнорируя самоподписанный SSL сертификат сервера (-k)

  # Вариант #1 - скачиваем файл и сразу его запускаем
  #curl -k -s $url_id | bash

  # Вариант #2 - скачиваем файл, выдаем разрешение на запуск и запускаем исталлятор
  # В этом случае можно обработать ответ от сервера и вывести необходимую информацию на экран/лог
  curl -k -s $url_id -o ./$FILE_TMP
  check_response_api $?
  if [ "$RETURN_VAL" == "error" ]; then
    out_data_log "Error downloading agent installer script from server IP $SERVER_IP"
    # Не смогли скачать агента, прекращаем работу скрипта
    exit 64
  else
    out_data_log "Agent installer correctly downloaded."
  fi
  chmod +x ./$FILE_TMP
  ./$FILE_TMP

  echo "------------ Deploy agent finish ------------"
}

check_agent() {
  # Проверка, что хотя бы одна из служб агента запущена
  if systemctl -q is-active $agent_service_name == 'active'; then
    out_data_log "Service $agent_service_name still running."
    AGENT_INSTALLED=1
  else
    if systemctl -q is-active $updater_service_name == 'active'; then
      out_data_log "Service $updater_service_name still running."
      AGENT_INSTALLED=1
    else

      # Не нашли запущенную службу агента (vulns.io-agent-linux) или апдейтера (vulns.io-agent-updater-linux)
      AGENT_INSTALLED=0

      out_data_log "Linux-agent installation failed with an error, agent not installed"

      # В зависимости от параметра 'DELETE_ASSET_IF_INSTALL_FAIL' удаляем или нет установленный агент и (не)очищаем из базы данных OnPremise asset и agent
      if [ $DELETE_ASSET_IF_INSTALL_FAIL -eq 0 ]; then
        out_data_log "Set internal variable 'DELETE_ASSET_IF_INSTALL_FAIL=0'"
      else
        # Удаляем агента с помощью uninstaller'а и удаляем asset и agent в бд OnPremise
        if [ -f /opt/vulns.io/agent-linux/agent_uninstall.sh ]; then
          out_data_log "Run - Uninstall agent script"
          /opt/vulns.io/agent-linux/agent_uninstall.sh
        fi

        # - fix on удаляем забытые символьные ссылки (для поддержки старых версий деинсталляторов агентов)
        if [ -L /usr/lib/systemd/system/vulns.io-agent-linux.service ]; then
          rm -f /usr/lib/systemd/system/vulns.io-agent-linux.service
          out_data_log "FIX: Удалили файл /usr/lib/systemd/system/vulns.io-agent-linux.service"
        fi
        if [ -L /usr/lib/systemd/system/vulns.io-agent-updater-linux.service ]; then
          rm -f /usr/lib/systemd/system/vulns.io-agent-updater-linux.service
          out_data_log "FIX: Удалили файл /usr/lib/systemd/system/vulns.io-agent-updater-linux.service"
        fi
        # - fix off

        out_data_log "Deleting data on OnPremise"

        delete_asset

        delete_agent

        # Удаляем скачанный файл инсталятора linux-агента
        rm -f ./$FILE_TMP
      fi
    fi
  fi
  if [ $AGENT_INSTALLED -eq 1 ]; then
    out_data_log "Linux agent installation completed correctly"
  fi
}

# --------- MAIN ---------

out_data_log "-- Start deploy linux-agent at $(date +"%Y-%m-%d %T") ---"

init $1

get_installer

out_data_log "agentid='$agentid'"
out_data_log "assetid='$assetid'"

deploy_agent

WAIT_TIME=5
out_data_log "Wait $WAIT_TIME second before check linux-agent"
sleep $WAIT_TIME

check_agent

out_data_log "-- End deploy linux-agent. Total script running time $SECONDS seconds ---"
