#!/bin/bash

# Copyright Security Onion Solutions LLC and/or licensed to Security Onion Solutions LLC under one
# or more contributor license agreements. Licensed under the Elastic License 2.0 as shown at 
# https://securityonion.net/license; you may not use this file except in compliance with the
# Elastic License 2.0.


source $(dirname $0)/so-common
require_manager

user=$1
elasticUsersFile=${ELASTIC_USERS_FILE:-/opt/so/saltstack/local/salt/elasticsearch/files/users}
elasticAuthPillarFile=${ELASTIC_AUTH_PILLAR_FILE:-/opt/so/saltstack/local/pillar/elasticsearch/auth.sls}

if [[ $# -ne 1 ]]; then
  echo "Usage: $0 <user>"
  echo ""
  echo " where <user> is one of the following:"
  echo ""
  echo "         all: Reset the password for the so_elastic, so_kibana, so_logstash, so_beats, and so_monitor users"
  echo "  so_elastic: Reset the password for the so_elastic user"
  echo "   so_kibana: Reset the password for the so_kibana user"
  echo " so_logstash: Reset the password for the so_logstash user"
  echo "    so_beats: Reset the password for the so_beats user"
  echo "  so_monitor: Reset the password for the so_monitor user"
  echo ""
  exit 1
fi

# function to create a lock so that the so-user sync cronjob can't run while this is running
function lock() {
  # Obtain file descriptor lock
  exec 99>/var/tmp/so-user.lock || fail "Unable to create lock descriptor; if the system was not shutdown gracefully you may need to remove /var/tmp/so-user.lock manually."
  flock -w 10 99 || fail "Another process is using so-user; if the system was not shutdown gracefully you may need to remove /var/tmp/so-user.lock manually."
  trap 'rm -f /var/tmp/so-user.lock' EXIT
}

function unlock() {
  rm -f /var/tmp/so-user.lock
}

function fail() {
  msg=$1
  echo "$1"
  exit 1
}

function removeSingleUserPass() {
  local user=$1
  sed -i '/user: '"${user}"'/{N;/pass: /d}' "${elasticAuthPillarFile}"
}

function removeAllUserPass() {
  local userList=("so_elastic" "so_kibana" "so_logstash" "so_beats" "so_monitor")

  for u in ${userList[@]}; do
    removeSingleUserPass "$u"
  done
}

function removeElasticUsersFile() {
  rm -f "$elasticUsersFile"
}

function createElasticAuthPillar() {
  salt-call state.apply elasticsearch.auth queue=True
}

# this will disable highstate to prevent a highstate from starting while the script is running
# will also disable salt.minion-state-apply-test allow so-salt-minion-check cronjob to restart salt-minion service incase
function disableSaltStates() {
  printf "\nDisabling salt.minion-state-apply-test and highstate from running.\n\n"
  salt-call state.disable salt.minion-state-apply-test
  salt-call state.disable highstate
}

function enableSaltStates() {
  printf "\nEnabling salt.minion-state-apply-test and highstate.\n\n"
  salt-call state.enable salt.minion-state-apply-test
  salt-call state.enable highstate
}

function killAllSaltJobs() {
  printf "\nKilling all running salt jobs.\n\n"
  salt-call saltutil.kill_all_jobs
}

function soUserSync() {
  # apply this state to update /opt/so/saltstack/local/salt/elasticsearch/curl.config on the manager
  salt-call state.sls_id elastic_curl_config_distributed manager queue=True
  salt -C 'G@role:so-standalone or G@role:so-eval or G@role:so-import or G@role:so-manager or G@role:so-managersearch or G@role:so-searchnode or G@role:so-heavynode' saltutil.kill_all_jobs
  # apply this state to get the curl.config
  salt -C 'G@role:so-standalone or G@role:so-eval or G@role:so-import or G@role:so-manager or G@role:so-managersearch or G@role:so-searchnode or G@role:so-heavynode' state.sls_id elastic_curl_config common queue=True
  $(dirname $0)/so-user sync
  printf "\nApplying logstash state to the appropriate nodes.\n\n"
  salt -C 'G@role:so-standalone or G@role:so-eval or G@role:so-import or G@role:so-manager or G@role:so-managersearch or G@role:so-searchnode or G@role:so-heavynode' state.apply logstash queue=True
  printf "\nApplying kibana state to the appropriate nodes.\n\n"
  salt -C 'G@role:so-standalone or G@role:so-eval or G@role:so-import or G@role:so-manager or G@role:so-managersearch' state.apply kibana queue=True
}

function highstateManager() {
  killAllSaltJobs
  printf "\nRunning highstate on the manager to finalize password reset.\n\n"
  salt-call state.highstate -linfo queue=True
}

case "${user}" in

  so_elastic | so_kibana | so_logstash | so_beats | so_monitor)
    lock
    killAllSaltJobs
    disableSaltStates
    removeSingleUserPass "$user"
    createElasticAuthPillar
    removeElasticUsersFile
    unlock
    soUserSync
    enableSaltStates
    highstateManager
    ;;

  all)
    lock
    killAllSaltJobs
    disableSaltStates
    removeAllUserPass
    createElasticAuthPillar
    removeElasticUsersFile
    unlock
    soUserSync
    enableSaltStates
    highstateManager
    ;;

  *)
    fail "Unsupported user: $user"
    ;;

esac

exit 0
