github.com/crowdsecurity/crowdsec@v1.6.1/wizard.sh (about)

     1  #!/usr/bin/env bash
     2  
     3  set -o pipefail
     4  #set -x
     5  
     6  skip_tmp_acquis() {
     7      [[ "${TMP_ACQUIS_FILE_SKIP}" == "skip" ]]
     8  }
     9  
    10  
    11  RED='\033[0;31m'
    12  BLUE='\033[0;34m'
    13  GREEN='\033[0;32m'
    14  YELLOW='\033[1;33m'
    15  ORANGE='\033[0;33m'
    16  NC='\033[0m'
    17  
    18  SILENT="false"
    19  DOCKER_MODE="false"
    20  
    21  CROWDSEC_RUN_DIR="/var/run"
    22  CROWDSEC_LIB_DIR="/var/lib/crowdsec"
    23  CROWDSEC_USR_DIR="/usr/local/lib/crowdsec"
    24  CROWDSEC_DATA_DIR="${CROWDSEC_LIB_DIR}/data"
    25  CROWDSEC_DB_PATH="${CROWDSEC_DATA_DIR}/crowdsec.db"
    26  CROWDSEC_PATH="/etc/crowdsec"
    27  CROWDSEC_CONFIG_PATH="${CROWDSEC_PATH}"
    28  CROWDSEC_LOG_FILE="/var/log/crowdsec.log"
    29  LAPI_LOG_FILE="/var/log/crowdsec_api.log"
    30  CROWDSEC_PLUGIN_DIR="${CROWDSEC_USR_DIR}/plugins"
    31  CROWDSEC_CONSOLE_DIR="${CROWDSEC_PATH}/console"
    32  
    33  CROWDSEC_BIN="./cmd/crowdsec/crowdsec"
    34  CSCLI_BIN="./cmd/crowdsec-cli/cscli"
    35  
    36  CLIENT_SECRETS="local_api_credentials.yaml"
    37  LAPI_SECRETS="online_api_credentials.yaml"
    38  
    39  CONSOLE_FILE="console.yaml"
    40  
    41  BIN_INSTALL_PATH="/usr/local/bin"
    42  CROWDSEC_BIN_INSTALLED="${BIN_INSTALL_PATH}/crowdsec"
    43  
    44  if [[ -f "/usr/bin/cscli" ]] ; then
    45      CSCLI_BIN_INSTALLED="/usr/bin/cscli"
    46  else
    47      CSCLI_BIN_INSTALLED="${BIN_INSTALL_PATH}/cscli"
    48  fi
    49  
    50  ACQUIS_PATH="${CROWDSEC_CONFIG_PATH}"
    51  ACQUIS_TARGET="${ACQUIS_PATH}/acquis.yaml"
    52  
    53  SYSTEMD_PATH_FILE="/etc/systemd/system/crowdsec.service"
    54  
    55  PATTERNS_FOLDER="config/patterns"
    56  PATTERNS_PATH="${CROWDSEC_CONFIG_PATH}/patterns/"
    57  
    58  ACTION=""
    59  
    60  DEBUG_MODE="false"
    61  FORCE_MODE="false"
    62  
    63  # the ssh service has different names on deb vs rpm-based distros
    64  if [[ -f "/etc/debian_version" ]]; then
    65      SSH_NAME="ssh"
    66  else
    67      SSH_NAME="sshd"
    68  fi
    69  
    70  SUPPORTED_SERVICES="apache2
    71  httpd
    72  nginx
    73  $SSH_NAME
    74  mysql
    75  telnet
    76  smb
    77  "
    78  
    79  
    80  HTTP_PLUGIN_BINARY="./cmd/notification-http/notification-http"
    81  SLACK_PLUGIN_BINARY="./cmd/notification-slack/notification-slack"
    82  SPLUNK_PLUGIN_BINARY="./cmd/notification-splunk/notification-splunk"
    83  EMAIL_PLUGIN_BINARY="./cmd/notification-email/notification-email"
    84  SENTINEL_PLUGIN_BINARY="./cmd/notification-sentinel/notification-sentinel"
    85  
    86  HTTP_PLUGIN_CONFIG="./cmd/notification-http/http.yaml"
    87  SLACK_PLUGIN_CONFIG="./cmd/notification-slack/slack.yaml"
    88  SPLUNK_PLUGIN_CONFIG="./cmd/notification-splunk/splunk.yaml"
    89  EMAIL_PLUGIN_CONFIG="./cmd/notification-email/email.yaml"
    90  SENTINEL_PLUGIN_CONFIG="./cmd/notification-sentinel/sentinel.yaml"
    91  
    92  
    93  BACKUP_DIR=$(mktemp -d)
    94  rm -rf -- "$BACKUP_DIR"
    95  
    96  log_info() {
    97      msg=$1
    98      date=$(date "+%Y-%m-%d %H:%M:%S")
    99      echo -e "${BLUE}INFO${NC}[${date}] crowdsec_wizard: ${msg}"
   100  }
   101  
   102  log_fatal() {
   103      msg=$1
   104      date=$(date "+%Y-%m-%d %H:%M:%S")
   105      echo -e "${RED}FATA${NC}[${date}] crowdsec_wizard: ${msg}" 1>&2
   106      exit 1
   107  }
   108  
   109  log_warn() {
   110      msg=$1
   111      date=$(date "+%Y-%m-%d %H:%M:%S")
   112      echo -e "${ORANGE}WARN${NC}[${date}] crowdsec_wizard: ${msg}"
   113  }
   114  
   115  log_err() {
   116      msg=$1
   117      date=$(date "+%Y-%m-%d %H:%M:%S")
   118      echo -e "${RED}ERR${NC}[${date}] crowdsec_wizard: ${msg}" 1>&2
   119  }
   120  
   121  log_dbg() {
   122      if [[ ${DEBUG_MODE} == "true" ]]; then
   123          msg=$1
   124          date=$(date "+%Y-%m-%d %H:%M:%S")
   125          echo -e "[${date}][${YELLOW}DBG${NC}] crowdsec_wizard: ${msg}" 1>&2
   126      fi
   127  }
   128  
   129  detect_services () {
   130      DETECTED_SERVICES=()
   131      HMENU=()
   132      # list systemd services
   133      SYSTEMD_SERVICES=$(systemctl  --state=enabled list-unit-files '*.service' | cut -d ' ' -f1)
   134      # raw ps
   135      PSAX=$(ps ax -o comm=)
   136      for SVC in ${SUPPORTED_SERVICES} ; do
   137          log_dbg "Checking if service '${SVC}' is running (ps+systemd)"
   138          for SRC in "${SYSTEMD_SERVICES}" "${PSAX}" ; do
   139              echo ${SRC} | grep ${SVC} >/dev/null
   140              if [ $? -eq 0 ]; then
   141                  # on centos, apache2 is named httpd
   142                  if [[ ${SVC} == "httpd" ]] ; then
   143                      SVC="apache2";
   144                  fi
   145                  DETECTED_SERVICES+=(${SVC})
   146                  HMENU+=(${SVC} "on")
   147                  log_dbg "Found '${SVC}' running"
   148                  break;
   149              fi;
   150          done;
   151      done;
   152      if [[ ${OSTYPE} == "linux-gnu" ]] || [[ ${OSTYPE} == "linux-gnueabihf" ]]; then
   153          DETECTED_SERVICES+=("linux")
   154          HMENU+=("linux" "on")
   155      else
   156          log_info "NOT A LINUX"
   157      fi;
   158  
   159      if [[ ${SILENT} == "false" ]]; then
   160          # we put whiptail results in an array, notice the dark magic fd redirection
   161          DETECTED_SERVICES=($(whiptail --separate-output --noitem --ok-button Continue --title "Services to monitor" --checklist "Detected services, uncheck to ignore. Ignored services won't be monitored." 18 70 10 ${HMENU[@]} 3>&1 1>&2 2>&3))
   162          if [ $? -eq 1 ]; then
   163              log_err "user bailed out at services selection"
   164              exit 1;
   165          fi;
   166          log_dbg "Detected services (interactive) : ${DETECTED_SERVICES[@]}"
   167      else
   168          log_dbg "Detected services (unattended) : ${DETECTED_SERVICES[@]}"
   169      fi;
   170  }
   171  
   172  declare -A log_input_tags
   173  log_input_tags[apache2]='type: apache2'
   174  log_input_tags[nginx]='type: nginx'
   175  log_input_tags[$SSH_NAME]='type: syslog'
   176  log_input_tags[rsyslog]='type: syslog'
   177  log_input_tags[telnet]='type: telnet'
   178  log_input_tags[mysql]='type: mysql'
   179  log_input_tags[smb]='type: smb'
   180  log_input_tags[linux]="type: syslog"
   181  
   182  declare -A log_locations
   183  log_locations[apache2]='/var/log/apache2/*.log,/var/log/*httpd*.log,/var/log/httpd/*log'
   184  log_locations[nginx]='/var/log/nginx/*.log,/usr/local/openresty/nginx/logs/*.log'
   185  log_locations[$SSH_NAME]='/var/log/auth.log,/var/log/sshd.log,/var/log/secure'
   186  log_locations[rsyslog]='/var/log/syslog'
   187  log_locations[telnet]='/var/log/telnetd*.log'
   188  log_locations[mysql]='/var/log/mysql/error.log'
   189  log_locations[smb]='/var/log/samba*.log'
   190  log_locations[linux]='/var/log/syslog,/var/log/kern.log,/var/log/messages'
   191  
   192  # $1 is service name, such those in SUPPORTED_SERVICES
   193  find_logs_for() {
   194      x=${1}
   195      # we have trailing and starting quotes because of whiptail
   196      SVC="${x%\"}"
   197      SVC="${SVC#\"}"
   198      DETECTED_LOGFILES=()
   199      HMENU=()
   200      # log_info "Searching logs for ${SVC} : ${log_locations[${SVC}]}"
   201  
   202      # split the line into an array with ',' separator
   203      OIFS=${IFS}
   204      IFS=',' read -r -a a <<< "${log_locations[${SVC}]},"
   205      IFS=${OIFS}
   206      # readarray -td, a <<<"${log_locations[${SVC}]},"; unset 'a[-1]';
   207      for poss_path in "${a[@]}"; do
   208          # Split /var/log/nginx/*.log into '/var/log/nginx' and '*.log' so we can use find
   209  	    path=${poss_path%/*}
   210  	    fname=${poss_path##*/}
   211  	    candidates=$(find "${path}" -type f -mtime -5 -ctime -5 -name "$fname" 2>/dev/null)
   212  	    # We have some candidates, add them
   213  	    for final_file in ${candidates} ; do
   214  	        log_dbg "Found logs file for '${SVC}': ${final_file}"
   215  	        DETECTED_LOGFILES+=(${final_file})
   216              HMENU+=(${final_file} "on")
   217  	    done;
   218      done;
   219  
   220      if [[ ${SILENT} == "false" ]]; then
   221          DETECTED_LOGFILES=($(whiptail --separate-output  --noitem --ok-button Continue --title "Log files to process for ${SVC}" --checklist "Detected logfiles for ${SVC}, uncheck to ignore" 18 70 10 ${HMENU[@]} 3>&1 1>&2 2>&3))
   222          if [ $? -eq 1 ]; then
   223              log_err "user bailed out at log file selection"
   224              exit 1;
   225          fi;
   226      fi
   227  }
   228  
   229  in_array() {
   230      str=$1
   231      shift
   232      array=("$@")
   233      for element in "${array[@]}"; do
   234          if [[ ${str} == crowdsecurity/${element} ]]; then
   235              return 0
   236          fi
   237      done
   238      return 1
   239  }
   240  
   241  install_collection() {
   242      HMENU=()
   243      readarray -t AVAILABLE_COLLECTION < <(${CSCLI_BIN_INSTALLED} collections list -o raw -a)
   244      COLLECTION_TO_INSTALL=()
   245      for collect_info in "${AVAILABLE_COLLECTION[@]:1}"; do
   246          collection="$(echo ${collect_info} | cut -d "," -f1)"
   247          description="$(echo ${collect_info} | cut -d "," -f4)"
   248          in_array $collection "${DETECTED_SERVICES[@]}"
   249          if [[ $? == 0 ]]; then
   250              HMENU+=("${collection}" "${description}" "ON")
   251              # in case we're not in interactive mode, assume defaults
   252              COLLECTION_TO_INSTALL+=(${collection})
   253          else
   254              if [[ ${collection} == "linux" ]]; then
   255                  HMENU+=("${collection}" "${description}" "ON")
   256                  # in case we're not in interactive mode, assume defaults
   257                  COLLECTION_TO_INSTALL+=(${collection})
   258              else
   259                  HMENU+=("${collection}" "${description}" "OFF")
   260              fi
   261          fi
   262      done
   263  
   264      if [[ ${SILENT} == "false" ]]; then
   265          COLLECTION_TO_INSTALL=($(whiptail --separate-output --ok-button Continue --title "Crowdsec collections" --checklist "Available collections in crowdsec, try to pick one that fits your profile. Collections contains parsers and scenarios to protect your system." 20 120 10 "${HMENU[@]}" 3>&1 1>&2 2>&3))
   266          if [ $? -eq 1 ]; then
   267              log_err "user bailed out at collection selection"
   268              exit 1;
   269          fi;
   270      fi;
   271  
   272      for collection in "${COLLECTION_TO_INSTALL[@]}"; do
   273          log_info "Installing collection '${collection}'"
   274          ${CSCLI_BIN_INSTALLED} collections install "${collection}" --error
   275      done
   276  
   277      ${CSCLI_BIN_INSTALLED} parsers install "crowdsecurity/whitelists" --error
   278      if [[ ${SILENT} == "false" ]]; then
   279          whiptail --msgbox "Out of safety, I installed a parser called 'crowdsecurity/whitelists'. This one will prevent private IP addresses from being banned, feel free to remove it any time." 20 50
   280      fi
   281  
   282      if [[ ${SILENT} == "false" ]]; then
   283          whiptail --msgbox "CrowdSec alone will not block any IP address. If you want to block them, you must use a bouncer. You can find them on https://hub.crowdsec.net/browse/#bouncers" 20 50
   284      fi
   285  }
   286  
   287  # $1 is the service name, $... is the list of candidate logs (from find_logs_for)
   288  genyamllog() {
   289      local service="${1}"
   290      shift
   291      local files=("${@}")
   292  
   293      echo "#Generated acquisition file - wizard.sh (service: ${service}) / files : ${files[@]}" >> ${TMP_ACQUIS_FILE}
   294  
   295      echo "filenames:"  >> ${TMP_ACQUIS_FILE}
   296      for fd in ${files[@]}; do
   297  	echo "  - ${fd}"  >> ${TMP_ACQUIS_FILE}
   298      done
   299      echo "labels:"  >> ${TMP_ACQUIS_FILE}
   300      echo "  "${log_input_tags[${service}]}  >> ${TMP_ACQUIS_FILE}
   301      echo "---"  >> ${TMP_ACQUIS_FILE}
   302      log_dbg "${ACQUIS_FILE_MSG}"
   303  }
   304  
   305  genyamljournal() {
   306      local service="${1}"
   307      shift
   308  
   309      echo "#Generated acquisition file - wizard.sh (service: ${service}) / files : ${files[@]}" >> ${TMP_ACQUIS_FILE}
   310  
   311      echo "journalctl_filter:"  >> ${TMP_ACQUIS_FILE}
   312      echo " - _SYSTEMD_UNIT="${service}".service"  >> ${TMP_ACQUIS_FILE}
   313      echo "labels:"  >> ${TMP_ACQUIS_FILE}
   314      echo "  "${log_input_tags[${service}]}  >> ${TMP_ACQUIS_FILE}
   315      echo "---"  >> ${TMP_ACQUIS_FILE}
   316      log_dbg "${ACQUIS_FILE_MSG}"
   317  }
   318  
   319  genacquisition() {
   320      if skip_tmp_acquis; then
   321          TMP_ACQUIS_FILE="${ACQUIS_TARGET}"
   322          ACQUIS_FILE_MSG="acquisition file generated to: ${TMP_ACQUIS_FILE}"
   323      else
   324          TMP_ACQUIS_FILE="tmp-acquis.yaml"
   325          ACQUIS_FILE_MSG="tmp acquisition file generated to: ${TMP_ACQUIS_FILE}"
   326      fi
   327  
   328      log_dbg "Found following services : "${DETECTED_SERVICES[@]}
   329      for PSVG in ${DETECTED_SERVICES[@]} ; do
   330          find_logs_for ${PSVG}
   331          if [[ ${#DETECTED_LOGFILES[@]} -gt 0 ]] ; then
   332              log_info "service '${PSVG}': ${DETECTED_LOGFILES[*]}"
   333              genyamllog ${PSVG} ${DETECTED_LOGFILES[@]}
   334  	elif [[ ${PSVG} != "linux" ]] ; then
   335  	    log_info "using journald for '${PSVG}'"
   336  	    genyamljournal ${PSVG}
   337          fi;
   338      done
   339  }
   340  
   341  detect_cs_install () {
   342      if [[ -f "$CROWDSEC_BIN_INSTALLED" ]]; then
   343          log_warn "Crowdsec is already installed !"
   344          echo ""
   345          echo "We recommend to upgrade : sudo ./wizard.sh --upgrade "
   346          echo "If you want to install it anyway, please use '--force'."
   347          echo ""
   348          echo "Run : sudo ./wizard.sh -i --force"
   349          if [[ ${FORCE_MODE} == "false" ]]; then
   350              exit 1
   351          fi
   352      fi
   353  }
   354  
   355  check_cs_version () {
   356      CURRENT_CS_VERSION=$(crowdsec -version 2>&1 | grep version | grep -Eio 'v[0-9]+.[0-9]+.[0-9]+' | cut -c 2-)
   357      NEW_CS_VERSION=$($CROWDSEC_BIN -version 2>&1 | grep version | grep -Eio 'v[0-9]+.[0-9]+.[0-9]+' | cut -c 2-)
   358      CURRENT_MAJOR_VERSION=$(echo $CURRENT_CS_VERSION | cut -d'.' -f1)
   359      CURRENT_MINOR_VERSION=$(echo $CURRENT_CS_VERSION | cut -d'.' -f2)
   360      CURRENT_PATCH_VERSION=$(echo $CURRENT_CS_VERSION | cut -d'.' -f3)
   361      NEW_MAJOR_VERSION=$(echo $NEW_CS_VERSION | cut -d'.' -f1)
   362      NEW_MINOR_VERSION=$(echo $NEW_CS_VERSION | cut -d'.' -f2)
   363      NEW_PATCH_VERSION=$(echo $NEW_CS_VERSION | cut -d'.' -f3)
   364  
   365      if [[ $NEW_MAJOR_VERSION -gt $CURRENT_MAJOR_VERSION ]]; then
   366          if [[ ${FORCE_MODE} == "false" ]]; then
   367              log_warn "new version ($NEW_CS_VERSION) is a major, you should follow documentation to upgrade !"
   368              echo ""
   369              exit 1
   370          fi
   371      elif [[ $NEW_MINOR_VERSION -gt $CURRENT_MINOR_VERSION ]] ; then
   372          log_warn "new version ($NEW_CS_VERSION) is a minor upgrade !"
   373          if [[ $ACTION != "upgrade" ]] ; then
   374              if [[ ${FORCE_MODE} == "false" ]]; then
   375                  echo ""
   376                  echo "We recommend to upgrade with : sudo ./wizard.sh --upgrade "
   377                  echo "If you want to $ACTION anyway, please use '--force'."
   378                  echo ""
   379                  echo "Run : sudo ./wizard.sh --$ACTION --force"
   380                  exit 1
   381              fi
   382          fi
   383      elif [[ $NEW_PATCH_VERSION -gt $CURRENT_PATCH_VERSION ]] ; then
   384          log_warn "new version ($NEW_CS_VERSION) is a patch !"
   385          if [[ $ACTION != "binupgrade" ]] ; then
   386              if [[ ${FORCE_MODE} == "false" ]]; then
   387                  echo ""
   388                  echo "We recommend to upgrade binaries only : sudo ./wizard.sh --binupgrade "
   389                  echo "If you want to $ACTION anyway, please use '--force'."
   390                  echo ""
   391                  echo "Run : sudo ./wizard.sh --$ACTION --force"
   392                  exit 1
   393              fi
   394          fi
   395      elif [[ $NEW_MINOR_VERSION -eq $CURRENT_MINOR_VERSION ]]; then
   396          log_warn "new version ($NEW_CS_VERSION) is same as current version ($CURRENT_CS_VERSION) !"
   397          if [[ ${FORCE_MODE} == "false" ]]; then
   398              echo ""
   399              echo "We recommend to $ACTION only if it's an higher version. "
   400              echo "If it's an RC version (vX.X.X-rc) you can upgrade it using '--force'."
   401              echo ""
   402              echo "Run : sudo ./wizard.sh --$ACTION --force"
   403              exit 1
   404          fi
   405      fi
   406  }
   407  
   408  # install crowdsec and cscli
   409  install_crowdsec() {
   410      mkdir -p "${CROWDSEC_DATA_DIR}"
   411      (cd config && find patterns -type f -exec install -Dm 644 "{}" "${CROWDSEC_CONFIG_PATH}/{}" \; && cd ../) || exit
   412      mkdir -p "${CROWDSEC_CONFIG_PATH}/scenarios" || exit
   413      mkdir -p "${CROWDSEC_CONFIG_PATH}/postoverflows" || exit
   414      mkdir -p "${CROWDSEC_CONFIG_PATH}/collections" || exit
   415      mkdir -p "${CROWDSEC_CONFIG_PATH}/patterns" || exit
   416      mkdir -p "${CROWDSEC_CONFIG_PATH}/appsec-configs" || exit
   417      mkdir -p "${CROWDSEC_CONFIG_PATH}/appsec-rules" || exit
   418      mkdir -p "${CROWDSEC_CONSOLE_DIR}" || exit
   419  
   420      # tmp
   421      mkdir -p /tmp/data
   422      mkdir -p /etc/crowdsec/hub/
   423      install -v -m 600 -D "./config/${CLIENT_SECRETS}" "${CROWDSEC_CONFIG_PATH}" 1> /dev/null || exit
   424      install -v -m 600 -D "./config/${LAPI_SECRETS}" "${CROWDSEC_CONFIG_PATH}" 1> /dev/null || exit
   425  
   426      ## end tmp
   427  
   428      install -v -m 600 -D ./config/config.yaml "${CROWDSEC_CONFIG_PATH}" 1> /dev/null || exit
   429      install -v -m 644 -D ./config/dev.yaml "${CROWDSEC_CONFIG_PATH}" 1> /dev/null || exit
   430      install -v -m 644 -D ./config/user.yaml "${CROWDSEC_CONFIG_PATH}" 1> /dev/null || exit
   431      install -v -m 644 -D ./config/acquis.yaml "${CROWDSEC_CONFIG_PATH}" 1> /dev/null || exit
   432      install -v -m 644 -D ./config/profiles.yaml "${CROWDSEC_CONFIG_PATH}" 1> /dev/null || exit
   433      install -v -m 644 -D ./config/simulation.yaml "${CROWDSEC_CONFIG_PATH}" 1> /dev/null || exit
   434      install -v -m 644 -D ./config/"${CONSOLE_FILE}" "${CROWDSEC_CONFIG_PATH}" 1> /dev/null || exit
   435      install -v -m 644 -D ./config/context.yaml "${CROWDSEC_CONSOLE_DIR}" 1> /dev/null || exit
   436  
   437      DATA=${CROWDSEC_DATA_DIR} CFG=${CROWDSEC_CONFIG_PATH} envsubst '$CFG $DATA' < ./config/user.yaml > ${CROWDSEC_CONFIG_PATH}"/user.yaml" || log_fatal "unable to generate user configuration file"
   438      if [[ ${DOCKER_MODE} == "false" ]]; then
   439          CFG=${CROWDSEC_CONFIG_PATH} BIN=${CROWDSEC_BIN_INSTALLED} envsubst '$CFG $BIN' < ./config/crowdsec.service > "${SYSTEMD_PATH_FILE}" || log_fatal "unable to crowdsec systemd file"
   440      fi
   441      install_bins
   442  
   443      if [[ ${DOCKER_MODE} == "false" ]]; then
   444  	    systemctl daemon-reload
   445      fi
   446  }
   447  
   448  update_bins() {
   449      log_info "Only upgrading binaries"
   450      delete_bins
   451      install_bins
   452      log_info "Upgrade finished"
   453      systemctl restart crowdsec || log_fatal "unable to restart crowdsec with systemctl"
   454  }
   455  
   456  update_full() {
   457  
   458      if [[ ! -f "$CROWDSEC_BIN" ]]; then
   459          log_err "Crowdsec binary '$CROWDSEC_BIN' not found. Please build it with 'make build'" && exit
   460      fi
   461      if [[ ! -f "$CSCLI_BIN" ]]; then
   462          log_err "Cscli binary '$CSCLI_BIN' not found. Please build it with 'make build'" && exit
   463      fi
   464  
   465      log_info "Backing up existing configuration"
   466      ${CSCLI_BIN_INSTALLED} config backup ${BACKUP_DIR}
   467      log_info "Saving default database content if exist"
   468      if [[ -f "/var/lib/crowdsec/data/crowdsec.db" ]]; then
   469          cp /var/lib/crowdsec/data/crowdsec.db ${BACKUP_DIR}/crowdsec.db
   470      fi
   471      log_info "Cleanup existing crowdsec configuration"
   472      uninstall_crowdsec
   473      log_info "Installing crowdsec"
   474      install_crowdsec
   475      log_info "Restoring configuration"
   476      ${CSCLI_BIN_INSTALLED} hub update
   477      ${CSCLI_BIN_INSTALLED} config restore ${BACKUP_DIR}
   478      log_info "Restoring saved database if exist"
   479      if [[ -f "${BACKUP_DIR}/crowdsec.db" ]]; then
   480          cp ${BACKUP_DIR}/crowdsec.db /var/lib/crowdsec/data/crowdsec.db
   481      fi
   482      log_info "Finished, restarting"
   483      systemctl restart crowdsec || log_fatal "Failed to restart crowdsec"
   484  }
   485  
   486  install_bins() {
   487      log_dbg "Installing crowdsec binaries"
   488      install -v -m 755 -D "${CROWDSEC_BIN}" "${CROWDSEC_BIN_INSTALLED}" 1> /dev/null || exit
   489      install -v -m 755 -D "${CSCLI_BIN}" "${CSCLI_BIN_INSTALLED}" 1> /dev/null || exit
   490      which systemctl && systemctl is-active --quiet crowdsec
   491      if [ $? -eq 0 ]; then
   492          systemctl stop crowdsec
   493      fi
   494      install_plugins
   495      symlink_bins
   496  }
   497  
   498  symlink_bins() {
   499      if grep -q "${BIN_INSTALL_PATH}" <<< $PATH; then
   500          log_dbg "${BIN_INSTALL_PATH} found in PATH"
   501      else
   502          ln -s "${CSCLI_BIN_INSTALLED}" /usr/bin/cscli
   503          ln -s "${CROWDSEC_BIN_INSTALLED}" /usr/bin/crowdsec
   504      fi
   505  }
   506  
   507  delete_bins() {
   508      log_info "Removing crowdsec binaries"
   509      rm -f ${CROWDSEC_BIN_INSTALLED}
   510      rm -f ${CSCLI_BIN_INSTALLED}
   511  }
   512  
   513  delete_plugins() {
   514      rm -rf ${CROWDSEC_PLUGIN_DIR}
   515  }
   516  
   517  install_plugins(){
   518      mkdir -p ${CROWDSEC_PLUGIN_DIR}
   519      mkdir -p /etc/crowdsec/notifications
   520  
   521      cp ${SLACK_PLUGIN_BINARY} ${CROWDSEC_PLUGIN_DIR}
   522      cp ${SPLUNK_PLUGIN_BINARY} ${CROWDSEC_PLUGIN_DIR}
   523      cp ${HTTP_PLUGIN_BINARY} ${CROWDSEC_PLUGIN_DIR}
   524      cp ${EMAIL_PLUGIN_BINARY} ${CROWDSEC_PLUGIN_DIR}
   525      cp ${SENTINEL_PLUGIN_BINARY} ${CROWDSEC_PLUGIN_DIR}
   526  
   527      if [[ ${DOCKER_MODE} == "false" ]]; then
   528          cp -n ${SLACK_PLUGIN_CONFIG} /etc/crowdsec/notifications/
   529          cp -n ${SPLUNK_PLUGIN_CONFIG} /etc/crowdsec/notifications/
   530          cp -n ${HTTP_PLUGIN_CONFIG} /etc/crowdsec/notifications/
   531          cp -n ${EMAIL_PLUGIN_CONFIG} /etc/crowdsec/notifications/
   532          cp -n ${SENTINEL_PLUGIN_CONFIG} /etc/crowdsec/notifications/
   533      fi
   534  }
   535  
   536  check_running_bouncers() {
   537      # when uninstalling, check if user still has bouncers
   538      BOUNCERS_COUNT=$(${CSCLI_BIN} bouncers list -o=raw | tail -n +2 | wc -l)
   539      if [[ ${BOUNCERS_COUNT} -gt 0 ]] ; then
   540          if [[ ${FORCE_MODE} == "false" ]]; then
   541              echo "WARNING : You have at least one bouncer registered (cscli bouncers list)."
   542              echo "WARNING : Uninstalling crowdsec with a running bouncer will let it in an unpredictable state."
   543              echo "WARNING : If you want to uninstall crowdsec, you should first uninstall the bouncers."
   544              echo "Specify --force to bypass this restriction."
   545              exit 1
   546          fi;
   547      fi
   548  }
   549  
   550  # uninstall crowdsec and cscli
   551  uninstall_crowdsec() {
   552      systemctl stop crowdsec.service 1>/dev/null
   553      systemctl disable -q crowdsec.service 1>/dev/null
   554      ${CSCLI_BIN} dashboard remove -f -y >/dev/null
   555      delete_bins
   556  
   557      # tmp
   558      rm -rf /tmp/data/
   559      ## end tmp
   560  
   561      find /etc/crowdsec -maxdepth 1 -mindepth 1 | grep -v "bouncer" | xargs rm -rf || echo ""
   562      rm -f ${CROWDSEC_LOG_FILE} || echo ""
   563      rm -f ${LAPI_LOG_FILE} || echo ""
   564      rm -f ${CROWDSEC_DB_PATH} || echo ""
   565      rm -rf ${CROWDSEC_LIB_DIR} || echo ""
   566      rm -rf ${CROWDSEC_USR_DIR} || echo ""
   567      rm -f ${SYSTEMD_PATH_FILE} || echo ""
   568      log_info "crowdsec successfully uninstalled"
   569  }
   570  
   571  
   572  function show_link {
   573      echo ""
   574      echo "Useful links to start with Crowdsec:"
   575      echo ""
   576      echo "  - Documentation : https://doc.crowdsec.net/docs/getting_started/crowdsec_tour"
   577      echo "  - Crowdsec Hub  : https://hub.crowdsec.net/ "
   578      echo "  - Open issues   : https://github.com/crowdsecurity/crowdsec/issues"
   579      echo ""
   580      echo "Useful commands to start with Crowdsec:"
   581      echo ""
   582      echo "  - sudo cscli metrics             : https://doc.crowdsec.net/docs/observability/cscli"
   583      echo "  - sudo cscli decisions list      : https://doc.crowdsec.net/docs/user_guides/decisions_mgmt"
   584      echo "  - sudo cscli hub list            : https://doc.crowdsec.net/docs/user_guides/hub_mgmt"
   585      echo ""
   586      echo "Next step:  visualize all your alerts and explore our community CTI : https://app.crowdsec.net"
   587      echo ""
   588  }
   589  
   590  main() {
   591  
   592      if [ "$1" == "install" ] || [ "$1" == "configure" ] || [ "$1" == "detect" ]; then
   593          if [ "${SILENT}" == "false" ]; then
   594              which whiptail > /dev/null
   595              if [ $? -ne 0 ]; then
   596                  log_fatal "whiptail binary is needed to use the wizard in interactive mode, exiting ..."
   597              fi
   598          fi
   599          which envsubst > /dev/null
   600          if [ $? -ne 0 ]; then
   601              log_fatal "envsubst binary is needed to use do a full install with the wizard, exiting ..."
   602          fi
   603      fi
   604  
   605      if [[ "$1" == "binupgrade" ]];
   606      then
   607          if ! [ $(id -u) = 0 ]; then
   608              log_err "Please run the wizard as root or with sudo"
   609              exit 1
   610          fi
   611          check_cs_version
   612          update_bins
   613          return
   614      fi
   615  
   616      if [[ "$1" == "upgrade" ]];
   617      then
   618          if ! [ $(id -u) = 0 ]; then
   619              log_err "Please run the wizard as root or with sudo"
   620              exit 1
   621          fi
   622          check_cs_version
   623          update_full
   624          return
   625      fi
   626  
   627      if [[ "$1" == "configure" ]];
   628      then
   629          if ! [ $(id -u) = 0 ]; then
   630              log_err "Please run the wizard as root or with sudo"
   631              exit 1
   632          fi
   633          detect_services
   634          ${CSCLI_BIN_INSTALLED} hub update
   635          install_collection
   636          genacquisition
   637          if ! skip_tmp_acquis; then
   638              mv "${TMP_ACQUIS_FILE}" "${ACQUIS_TARGET}"
   639          fi
   640  
   641          return
   642      fi
   643  
   644      if [[ "$1" == "noop" ]];
   645      then
   646          return
   647      fi
   648  
   649      if [[ "$1" == "uninstall" ]];
   650      then
   651          if ! [ $(id -u) = 0 ]; then
   652              log_err "Please run the wizard as root or with sudo"
   653              exit 1
   654          fi
   655          check_running_bouncers
   656          uninstall_crowdsec
   657          return
   658      fi
   659  
   660      if [[ "$1" == "bininstall" ]];
   661      then
   662          if ! [ $(id -u) = 0 ]; then
   663              log_err "Please run the wizard as root or with sudo"
   664              exit 1
   665          fi
   666          log_info "checking existing crowdsec install"
   667          detect_cs_install
   668          log_info "installing crowdsec"
   669          install_crowdsec
   670  
   671          show_link
   672          return
   673      fi
   674  
   675      if [[ "$1" == "install" ]];
   676      then
   677          if ! [ $(id -u) = 0 ]; then
   678              log_err "Please run the wizard as root or with sudo"
   679              exit 1
   680          fi
   681          log_info "checking if crowdsec is installed"
   682          detect_cs_install
   683          ## Do make build before installing (as non--root) in order to have the binary and then install crowdsec as root
   684          log_info "installing crowdsec"
   685          install_crowdsec
   686          log_dbg "configuring ${CSCLI_BIN_INSTALLED}"
   687          ${CSCLI_BIN_INSTALLED} hub update --error || (log_err "fail to update crowdsec hub. exiting" && exit 1)
   688  
   689          # detect running services
   690          detect_services
   691          if ! [ ${#DETECTED_SERVICES[@]} -gt 0 ] ; then
   692              log_err "No detected or selected services, stopping."
   693              exit 1
   694          fi;
   695  
   696          # Generate acquisition file and move it to the right folder
   697          genacquisition
   698          if ! skip_tmp_acquis; then
   699              mv "${TMP_ACQUIS_FILE}" "${ACQUIS_TARGET}"
   700          fi
   701          log_info "acquisition file path: ${ACQUIS_TARGET}"
   702          # Install collections according to detected services
   703          log_dbg "Installing needed collections ..."
   704          install_collection
   705  
   706          # install patterns/ folder
   707          log_dbg "Installing patterns"
   708          mkdir -p "${PATTERNS_PATH}"
   709          cp "./${PATTERNS_FOLDER}/"* "${PATTERNS_PATH}/"
   710  
   711          # api register
   712          ${CSCLI_BIN_INSTALLED} machines add --force "$(cat /etc/machine-id)" -a -f "${CROWDSEC_CONFIG_PATH}/${CLIENT_SECRETS}" || log_fatal "unable to add machine to the local API"
   713          log_dbg "Crowdsec LAPI registered"
   714  
   715          ${CSCLI_BIN_INSTALLED} capi register --error || log_fatal "unable to register to the Central API"
   716  
   717          systemctl enable -q crowdsec >/dev/null || log_fatal "unable to enable crowdsec"
   718          systemctl start crowdsec >/dev/null || log_fatal "unable to start crowdsec"
   719          log_info "enabling and starting crowdsec daemon"
   720          show_link
   721          return
   722      fi
   723  
   724      if [[ "$1" == "detect" ]];
   725      then
   726          if ! skip_tmp_acquis; then
   727              rm -f "${TMP_ACQUIS_FILE}"
   728          fi
   729          detect_services
   730          if [[ ${DETECTED_SERVICES} == "" ]] ; then
   731              log_err "No detected or selected services, stopping."
   732              exit
   733          fi;
   734          log_info "Found ${#DETECTED_SERVICES[@]} supported services running:"
   735          genacquisition
   736          cat "${TMP_ACQUIS_FILE}"
   737          if ! skip_tmp_acquis; then
   738              rm "${TMP_ACQUIS_FILE}"
   739          fi
   740          return
   741      fi
   742  
   743  }
   744  
   745  usage() {
   746        echo "Usage:"
   747        echo "    ./wizard.sh -h                               Display this help message."
   748        echo "    ./wizard.sh -d|--detect                      Detect running services and associated logs file"
   749        echo "    ./wizard.sh -i|--install                     Assisted installation of crowdsec/cscli and collections"
   750        echo "    ./wizard.sh --bininstall                     Install binaries and empty config, no wizard."
   751        echo "    ./wizard.sh --uninstall                      Uninstall crowdsec/cscli"
   752        echo "    ./wizard.sh --binupgrade                     Upgrade crowdsec/cscli binaries"
   753        echo "    ./wizard.sh --upgrade                        Perform a full upgrade and try to migrate configs"
   754        echo "    ./wizard.sh --unattended                     Install in unattended mode, no question will be asked and defaults will be followed"
   755        echo "    ./wizard.sh --docker-mode                    Will install crowdsec without systemd and generate random machine-id"
   756        echo "    ./wizard.sh -n|--noop                        Do nothing"
   757  
   758        exit 0
   759  }
   760  
   761  if [[ $# -eq 0 ]]; then
   762  usage
   763  fi
   764  
   765  while [[ $# -gt 0 ]]
   766  do
   767      key="${1}"
   768      case ${key} in
   769      --uninstall)
   770          ACTION="uninstall"
   771          shift # past argument
   772          ;;
   773      --binupgrade)
   774          ACTION="binupgrade"
   775          shift # past argument
   776          ;;
   777      --upgrade)
   778          ACTION="upgrade"
   779          shift # past argument
   780          ;;
   781      -i|--install)
   782          ACTION="install"
   783          shift # past argument
   784          ;;
   785      --bininstall)
   786          ACTION="bininstall"
   787          shift # past argument
   788          ;;
   789      --docker-mode)
   790          DOCKER_MODE="true"
   791          ACTION="bininstall"
   792          shift # past argument
   793          ;;
   794      -c|--configure)
   795          ACTION="configure"
   796          shift # past argument
   797          ;;
   798      -d|--detect)
   799          ACTION="detect"
   800          shift # past argument
   801          ;;
   802      -n|--noop)
   803          ACTION="noop"
   804          shift # past argument
   805          ;;
   806      --unattended)
   807          SILENT="true"
   808          ACTION="install"
   809          shift
   810          ;;
   811      -f|--force)
   812          FORCE_MODE="true"
   813          shift
   814          ;;
   815      -v|--verbose)
   816          DEBUG_MODE="true"
   817          shift
   818          ;;
   819      -h|--help)
   820          usage
   821          exit 0
   822          ;;
   823      *)    # unknown option
   824          log_err "Unknown argument ${key}."
   825          usage
   826          exit 1
   827          ;;
   828      esac
   829  done
   830  
   831  main ${ACTION}