#!/usr/bin/env bash set -o pipefail #set -x skip_tmp_acquis() { [[ "${TMP_ACQUIS_FILE_SKIP}" == "skip" ]] } RED='\033[0;31m' BLUE='\033[0;34m' GREEN='\033[0;32m' YELLOW='\033[1;33m' ORANGE='\033[0;33m' NC='\033[0m' SILENT="false" DOCKER_MODE="false" CROWDSEC_RUN_DIR="/var/run" CROWDSEC_LIB_DIR="/var/lib/crowdsec" CROWDSEC_USR_DIR="/usr/local/lib/crowdsec" CROWDSEC_DATA_DIR="${CROWDSEC_LIB_DIR}/data" CROWDSEC_DB_PATH="${CROWDSEC_DATA_DIR}/crowdsec.db" CROWDSEC_PATH="/etc/crowdsec" CROWDSEC_CONFIG_PATH="${CROWDSEC_PATH}" CROWDSEC_LOG_FILE="/var/log/crowdsec.log" LAPI_LOG_FILE="/var/log/crowdsec_api.log" CROWDSEC_PLUGIN_DIR="${CROWDSEC_USR_DIR}/plugins" CROWDSEC_CONSOLE_DIR="${CROWDSEC_PATH}/console" CROWDSEC_BIN="./cmd/crowdsec/crowdsec" CSCLI_BIN="./cmd/crowdsec-cli/cscli" CLIENT_SECRETS="local_api_credentials.yaml" LAPI_SECRETS="online_api_credentials.yaml" CONSOLE_FILE="console.yaml" BIN_INSTALL_PATH="/usr/local/bin" CROWDSEC_BIN_INSTALLED="${BIN_INSTALL_PATH}/crowdsec" if [[ -f "/usr/bin/cscli" ]] ; then CSCLI_BIN_INSTALLED="/usr/bin/cscli" else CSCLI_BIN_INSTALLED="${BIN_INSTALL_PATH}/cscli" fi ACQUIS_PATH="${CROWDSEC_CONFIG_PATH}" ACQUIS_TARGET="${ACQUIS_PATH}/acquis.yaml" SYSTEMD_PATH_FILE="/etc/systemd/system/crowdsec.service" PATTERNS_FOLDER="config/patterns" PATTERNS_PATH="${CROWDSEC_CONFIG_PATH}/patterns/" ACTION="" DEBUG_MODE="false" FORCE_MODE="false" # the ssh service has different names on deb vs rpm-based distros if [[ -f "/etc/debian_version" ]]; then SSH_NAME="ssh" else SSH_NAME="sshd" fi SUPPORTED_SERVICES="apache2 httpd nginx $SSH_NAME mysql telnet smb " HTTP_PLUGIN_BINARY="./cmd/notification-http/notification-http" SLACK_PLUGIN_BINARY="./cmd/notification-slack/notification-slack" SPLUNK_PLUGIN_BINARY="./cmd/notification-splunk/notification-splunk" EMAIL_PLUGIN_BINARY="./cmd/notification-email/notification-email" SENTINEL_PLUGIN_BINARY="./cmd/notification-sentinel/notification-sentinel" HTTP_PLUGIN_CONFIG="./cmd/notification-http/http.yaml" SLACK_PLUGIN_CONFIG="./cmd/notification-slack/slack.yaml" SPLUNK_PLUGIN_CONFIG="./cmd/notification-splunk/splunk.yaml" EMAIL_PLUGIN_CONFIG="./cmd/notification-email/email.yaml" SENTINEL_PLUGIN_CONFIG="./cmd/notification-sentinel/sentinel.yaml" BACKUP_DIR=$(mktemp -d) rm -rf -- "$BACKUP_DIR" log_info() { msg=$1 date=$(date "+%Y-%m-%d %H:%M:%S") echo -e "${BLUE}INFO${NC}[${date}] crowdsec_wizard: ${msg}" } log_fatal() { msg=$1 date=$(date "+%Y-%m-%d %H:%M:%S") echo -e "${RED}FATA${NC}[${date}] crowdsec_wizard: ${msg}" 1>&2 exit 1 } log_warn() { msg=$1 date=$(date "+%Y-%m-%d %H:%M:%S") echo -e "${ORANGE}WARN${NC}[${date}] crowdsec_wizard: ${msg}" } log_err() { msg=$1 date=$(date "+%Y-%m-%d %H:%M:%S") echo -e "${RED}ERR${NC}[${date}] crowdsec_wizard: ${msg}" 1>&2 } log_dbg() { if [[ ${DEBUG_MODE} == "true" ]]; then msg=$1 date=$(date "+%Y-%m-%d %H:%M:%S") echo -e "[${date}][${YELLOW}DBG${NC}] crowdsec_wizard: ${msg}" 1>&2 fi } detect_services () { DETECTED_SERVICES=() HMENU=() # list systemd services SYSTEMD_SERVICES=$(systemctl --state=enabled list-unit-files '*.service' | cut -d ' ' -f1) # raw ps PSAX=$(ps ax -o comm=) for SVC in ${SUPPORTED_SERVICES} ; do log_dbg "Checking if service '${SVC}' is running (ps+systemd)" for SRC in "${SYSTEMD_SERVICES}" "${PSAX}" ; do echo ${SRC} | grep ${SVC} >/dev/null if [ $? -eq 0 ]; then # on centos, apache2 is named httpd if [[ ${SVC} == "httpd" ]] ; then SVC="apache2"; fi DETECTED_SERVICES+=(${SVC}) HMENU+=(${SVC} "on") log_dbg "Found '${SVC}' running" break; fi; done; done; if [[ ${OSTYPE} == "linux-gnu" ]] || [[ ${OSTYPE} == "linux-gnueabihf" ]]; then DETECTED_SERVICES+=("linux") HMENU+=("linux" "on") else log_info "NOT A LINUX" fi; if [[ ${SILENT} == "false" ]]; then # we put whiptail results in an array, notice the dark magic fd redirection 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)) if [ $? -eq 1 ]; then log_err "user bailed out at services selection" exit 1; fi; log_dbg "Detected services (interactive) : ${DETECTED_SERVICES[@]}" else log_dbg "Detected services (unattended) : ${DETECTED_SERVICES[@]}" fi; } declare -A log_input_tags log_input_tags[apache2]='type: apache2' log_input_tags[nginx]='type: nginx' log_input_tags[$SSH_NAME]='type: syslog' log_input_tags[rsyslog]='type: syslog' log_input_tags[telnet]='type: telnet' log_input_tags[mysql]='type: mysql' log_input_tags[smb]='type: smb' log_input_tags[linux]="type: syslog" declare -A log_locations log_locations[apache2]='/var/log/apache2/*.log,/var/log/*httpd*.log,/var/log/httpd/*log' log_locations[nginx]='/var/log/nginx/*.log,/usr/local/openresty/nginx/logs/*.log' log_locations[$SSH_NAME]='/var/log/auth.log,/var/log/sshd.log,/var/log/secure' log_locations[rsyslog]='/var/log/syslog' log_locations[telnet]='/var/log/telnetd*.log' log_locations[mysql]='/var/log/mysql/error.log' log_locations[smb]='/var/log/samba*.log' log_locations[linux]='/var/log/syslog,/var/log/kern.log,/var/log/messages' # $1 is service name, such those in SUPPORTED_SERVICES find_logs_for() { x=${1} # we have trailing and starting quotes because of whiptail SVC="${x%\"}" SVC="${SVC#\"}" DETECTED_LOGFILES=() HMENU=() # log_info "Searching logs for ${SVC} : ${log_locations[${SVC}]}" # split the line into an array with ',' separator OIFS=${IFS} IFS=',' read -r -a a <<< "${log_locations[${SVC}]}," IFS=${OIFS} # readarray -td, a <<<"${log_locations[${SVC}]},"; unset 'a[-1]'; for poss_path in "${a[@]}"; do # Split /var/log/nginx/*.log into '/var/log/nginx' and '*.log' so we can use find path=${poss_path%/*} fname=${poss_path##*/} candidates=$(find "${path}" -type f -mtime -5 -ctime -5 -name "$fname" 2>/dev/null) # We have some candidates, add them for final_file in ${candidates} ; do log_dbg "Found logs file for '${SVC}': ${final_file}" DETECTED_LOGFILES+=(${final_file}) HMENU+=(${final_file} "on") done; done; if [[ ${SILENT} == "false" ]]; then 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)) if [ $? -eq 1 ]; then log_err "user bailed out at log file selection" exit 1; fi; fi } in_array() { str=$1 shift array=("$@") for element in "${array[@]}"; do if [[ ${str} == crowdsecurity/${element} ]]; then return 0 fi done return 1 } install_collection() { HMENU=() readarray -t AVAILABLE_COLLECTION < <(${CSCLI_BIN_INSTALLED} collections list -o raw -a) COLLECTION_TO_INSTALL=() for collect_info in "${AVAILABLE_COLLECTION[@]:1}"; do collection="$(echo ${collect_info} | cut -d "," -f1)" description="$(echo ${collect_info} | cut -d "," -f4)" in_array $collection "${DETECTED_SERVICES[@]}" if [[ $? == 0 ]]; then HMENU+=("${collection}" "${description}" "ON") # in case we're not in interactive mode, assume defaults COLLECTION_TO_INSTALL+=(${collection}) else if [[ ${collection} == "linux" ]]; then HMENU+=("${collection}" "${description}" "ON") # in case we're not in interactive mode, assume defaults COLLECTION_TO_INSTALL+=(${collection}) else HMENU+=("${collection}" "${description}" "OFF") fi fi done if [[ ${SILENT} == "false" ]]; then 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)) if [ $? -eq 1 ]; then log_err "user bailed out at collection selection" exit 1; fi; fi; for collection in "${COLLECTION_TO_INSTALL[@]}"; do log_info "Installing collection '${collection}'" ${CSCLI_BIN_INSTALLED} collections install "${collection}" --error done ${CSCLI_BIN_INSTALLED} parsers install "crowdsecurity/whitelists" --error if [[ ${SILENT} == "false" ]]; then 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 fi if [[ ${SILENT} == "false" ]]; then 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 fi } # $1 is the service name, $... is the list of candidate logs (from find_logs_for) genyamllog() { local service="${1}" shift local files=("${@}") echo "#Generated acquisition file - wizard.sh (service: ${service}) / files : ${files[@]}" >> ${TMP_ACQUIS_FILE} echo "filenames:" >> ${TMP_ACQUIS_FILE} for fd in ${files[@]}; do echo " - ${fd}" >> ${TMP_ACQUIS_FILE} done echo "labels:" >> ${TMP_ACQUIS_FILE} echo " "${log_input_tags[${service}]} >> ${TMP_ACQUIS_FILE} echo "---" >> ${TMP_ACQUIS_FILE} log_dbg "${ACQUIS_FILE_MSG}" } genyamljournal() { local service="${1}" shift echo "#Generated acquisition file - wizard.sh (service: ${service}) / files : ${files[@]}" >> ${TMP_ACQUIS_FILE} echo "journalctl_filter:" >> ${TMP_ACQUIS_FILE} echo " - _SYSTEMD_UNIT="${service}".service" >> ${TMP_ACQUIS_FILE} echo "labels:" >> ${TMP_ACQUIS_FILE} echo " "${log_input_tags[${service}]} >> ${TMP_ACQUIS_FILE} echo "---" >> ${TMP_ACQUIS_FILE} log_dbg "${ACQUIS_FILE_MSG}" } genacquisition() { if skip_tmp_acquis; then TMP_ACQUIS_FILE="${ACQUIS_TARGET}" ACQUIS_FILE_MSG="acquisition file generated to: ${TMP_ACQUIS_FILE}" else TMP_ACQUIS_FILE="tmp-acquis.yaml" ACQUIS_FILE_MSG="tmp acquisition file generated to: ${TMP_ACQUIS_FILE}" fi log_dbg "Found following services : "${DETECTED_SERVICES[@]} for PSVG in ${DETECTED_SERVICES[@]} ; do find_logs_for ${PSVG} if [[ ${#DETECTED_LOGFILES[@]} -gt 0 ]] ; then log_info "service '${PSVG}': ${DETECTED_LOGFILES[*]}" genyamllog ${PSVG} ${DETECTED_LOGFILES[@]} elif [[ ${PSVG} != "linux" ]] ; then log_info "using journald for '${PSVG}'" genyamljournal ${PSVG} fi; done } detect_cs_install () { if [[ -f "$CROWDSEC_BIN_INSTALLED" ]]; then log_warn "Crowdsec is already installed !" echo "" echo "We recommend to upgrade : sudo ./wizard.sh --upgrade " echo "If you want to install it anyway, please use '--force'." echo "" echo "Run : sudo ./wizard.sh -i --force" if [[ ${FORCE_MODE} == "false" ]]; then exit 1 fi fi } check_cs_version () { CURRENT_CS_VERSION=$(crowdsec -version 2>&1 | grep version | grep -Eio 'v[0-9]+.[0-9]+.[0-9]+' | cut -c 2-) NEW_CS_VERSION=$($CROWDSEC_BIN -version 2>&1 | grep version | grep -Eio 'v[0-9]+.[0-9]+.[0-9]+' | cut -c 2-) CURRENT_MAJOR_VERSION=$(echo $CURRENT_CS_VERSION | cut -d'.' -f1) CURRENT_MINOR_VERSION=$(echo $CURRENT_CS_VERSION | cut -d'.' -f2) CURRENT_PATCH_VERSION=$(echo $CURRENT_CS_VERSION | cut -d'.' -f3) NEW_MAJOR_VERSION=$(echo $NEW_CS_VERSION | cut -d'.' -f1) NEW_MINOR_VERSION=$(echo $NEW_CS_VERSION | cut -d'.' -f2) NEW_PATCH_VERSION=$(echo $NEW_CS_VERSION | cut -d'.' -f3) if [[ $NEW_MAJOR_VERSION -gt $CURRENT_MAJOR_VERSION ]]; then if [[ ${FORCE_MODE} == "false" ]]; then log_warn "new version ($NEW_CS_VERSION) is a major, you should follow documentation to upgrade !" echo "" exit 1 fi elif [[ $NEW_MINOR_VERSION -gt $CURRENT_MINOR_VERSION ]] ; then log_warn "new version ($NEW_CS_VERSION) is a minor upgrade !" if [[ $ACTION != "upgrade" ]] ; then if [[ ${FORCE_MODE} == "false" ]]; then echo "" echo "We recommend to upgrade with : sudo ./wizard.sh --upgrade " echo "If you want to $ACTION anyway, please use '--force'." echo "" echo "Run : sudo ./wizard.sh --$ACTION --force" exit 1 fi fi elif [[ $NEW_PATCH_VERSION -gt $CURRENT_PATCH_VERSION ]] ; then log_warn "new version ($NEW_CS_VERSION) is a patch !" if [[ $ACTION != "binupgrade" ]] ; then if [[ ${FORCE_MODE} == "false" ]]; then echo "" echo "We recommend to upgrade binaries only : sudo ./wizard.sh --binupgrade " echo "If you want to $ACTION anyway, please use '--force'." echo "" echo "Run : sudo ./wizard.sh --$ACTION --force" exit 1 fi fi elif [[ $NEW_MINOR_VERSION -eq $CURRENT_MINOR_VERSION ]]; then log_warn "new version ($NEW_CS_VERSION) is same as current version ($CURRENT_CS_VERSION) !" if [[ ${FORCE_MODE} == "false" ]]; then echo "" echo "We recommend to $ACTION only if it's an higher version. " echo "If it's an RC version (vX.X.X-rc) you can upgrade it using '--force'." echo "" echo "Run : sudo ./wizard.sh --$ACTION --force" exit 1 fi fi } # install crowdsec and cscli install_crowdsec() { mkdir -p "${CROWDSEC_DATA_DIR}" (cd config && find patterns -type f -exec install -Dm 644 "{}" "${CROWDSEC_CONFIG_PATH}/{}" \; && cd ../) || exit mkdir -p "${CROWDSEC_CONFIG_PATH}/scenarios" || exit mkdir -p "${CROWDSEC_CONFIG_PATH}/postoverflows" || exit mkdir -p "${CROWDSEC_CONFIG_PATH}/collections" || exit mkdir -p "${CROWDSEC_CONFIG_PATH}/patterns" || exit mkdir -p "${CROWDSEC_CONFIG_PATH}/appsec-configs" || exit mkdir -p "${CROWDSEC_CONFIG_PATH}/appsec-rules" || exit mkdir -p "${CROWDSEC_CONSOLE_DIR}" || exit # tmp mkdir -p /tmp/data mkdir -p /etc/crowdsec/hub/ install -v -m 600 -D "./config/${CLIENT_SECRETS}" "${CROWDSEC_CONFIG_PATH}" 1> /dev/null || exit install -v -m 600 -D "./config/${LAPI_SECRETS}" "${CROWDSEC_CONFIG_PATH}" 1> /dev/null || exit ## end tmp install -v -m 600 -D ./config/config.yaml "${CROWDSEC_CONFIG_PATH}" 1> /dev/null || exit install -v -m 644 -D ./config/dev.yaml "${CROWDSEC_CONFIG_PATH}" 1> /dev/null || exit install -v -m 644 -D ./config/user.yaml "${CROWDSEC_CONFIG_PATH}" 1> /dev/null || exit install -v -m 644 -D ./config/acquis.yaml "${CROWDSEC_CONFIG_PATH}" 1> /dev/null || exit install -v -m 644 -D ./config/profiles.yaml "${CROWDSEC_CONFIG_PATH}" 1> /dev/null || exit install -v -m 644 -D ./config/simulation.yaml "${CROWDSEC_CONFIG_PATH}" 1> /dev/null || exit install -v -m 644 -D ./config/"${CONSOLE_FILE}" "${CROWDSEC_CONFIG_PATH}" 1> /dev/null || exit install -v -m 644 -D ./config/context.yaml "${CROWDSEC_CONSOLE_DIR}" 1> /dev/null || exit 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" if [[ ${DOCKER_MODE} == "false" ]]; then CFG=${CROWDSEC_CONFIG_PATH} BIN=${CROWDSEC_BIN_INSTALLED} envsubst '$CFG $BIN' < ./config/crowdsec.service > "${SYSTEMD_PATH_FILE}" || log_fatal "unable to crowdsec systemd file" fi install_bins if [[ ${DOCKER_MODE} == "false" ]]; then systemctl daemon-reload fi } update_bins() { log_info "Only upgrading binaries" delete_bins install_bins log_info "Upgrade finished" systemctl restart crowdsec || log_fatal "unable to restart crowdsec with systemctl" } update_full() { if [[ ! -f "$CROWDSEC_BIN" ]]; then log_err "Crowdsec binary '$CROWDSEC_BIN' not found. Please build it with 'make build'" && exit fi if [[ ! -f "$CSCLI_BIN" ]]; then log_err "Cscli binary '$CSCLI_BIN' not found. Please build it with 'make build'" && exit fi log_info "Backing up existing configuration" ${CSCLI_BIN_INSTALLED} config backup ${BACKUP_DIR} log_info "Saving default database content if exist" if [[ -f "/var/lib/crowdsec/data/crowdsec.db" ]]; then cp /var/lib/crowdsec/data/crowdsec.db ${BACKUP_DIR}/crowdsec.db fi log_info "Cleanup existing crowdsec configuration" uninstall_crowdsec log_info "Installing crowdsec" install_crowdsec log_info "Restoring configuration" ${CSCLI_BIN_INSTALLED} hub update ${CSCLI_BIN_INSTALLED} config restore ${BACKUP_DIR} log_info "Restoring saved database if exist" if [[ -f "${BACKUP_DIR}/crowdsec.db" ]]; then cp ${BACKUP_DIR}/crowdsec.db /var/lib/crowdsec/data/crowdsec.db fi log_info "Finished, restarting" systemctl restart crowdsec || log_fatal "Failed to restart crowdsec" } install_bins() { log_dbg "Installing crowdsec binaries" install -v -m 755 -D "${CROWDSEC_BIN}" "${CROWDSEC_BIN_INSTALLED}" 1> /dev/null || exit install -v -m 755 -D "${CSCLI_BIN}" "${CSCLI_BIN_INSTALLED}" 1> /dev/null || exit which systemctl && systemctl is-active --quiet crowdsec if [ $? -eq 0 ]; then systemctl stop crowdsec fi install_plugins symlink_bins } symlink_bins() { if grep -q "${BIN_INSTALL_PATH}" <<< $PATH; then log_dbg "${BIN_INSTALL_PATH} found in PATH" else ln -s "${CSCLI_BIN_INSTALLED}" /usr/bin/cscli ln -s "${CROWDSEC_BIN_INSTALLED}" /usr/bin/crowdsec fi } delete_bins() { log_info "Removing crowdsec binaries" rm -f ${CROWDSEC_BIN_INSTALLED} rm -f ${CSCLI_BIN_INSTALLED} } delete_plugins() { rm -rf ${CROWDSEC_PLUGIN_DIR} } install_plugins(){ mkdir -p ${CROWDSEC_PLUGIN_DIR} mkdir -p /etc/crowdsec/notifications cp ${SLACK_PLUGIN_BINARY} ${CROWDSEC_PLUGIN_DIR} cp ${SPLUNK_PLUGIN_BINARY} ${CROWDSEC_PLUGIN_DIR} cp ${HTTP_PLUGIN_BINARY} ${CROWDSEC_PLUGIN_DIR} cp ${EMAIL_PLUGIN_BINARY} ${CROWDSEC_PLUGIN_DIR} cp ${SENTINEL_PLUGIN_BINARY} ${CROWDSEC_PLUGIN_DIR} if [[ ${DOCKER_MODE} == "false" ]]; then cp -n ${SLACK_PLUGIN_CONFIG} /etc/crowdsec/notifications/ cp -n ${SPLUNK_PLUGIN_CONFIG} /etc/crowdsec/notifications/ cp -n ${HTTP_PLUGIN_CONFIG} /etc/crowdsec/notifications/ cp -n ${EMAIL_PLUGIN_CONFIG} /etc/crowdsec/notifications/ cp -n ${SENTINEL_PLUGIN_CONFIG} /etc/crowdsec/notifications/ fi } check_running_bouncers() { # when uninstalling, check if user still has bouncers BOUNCERS_COUNT=$(${CSCLI_BIN} bouncers list -o=raw | tail -n +2 | wc -l) if [[ ${BOUNCERS_COUNT} -gt 0 ]] ; then if [[ ${FORCE_MODE} == "false" ]]; then echo "WARNING : You have at least one bouncer registered (cscli bouncers list)." echo "WARNING : Uninstalling crowdsec with a running bouncer will let it in an unpredictable state." echo "WARNING : If you want to uninstall crowdsec, you should first uninstall the bouncers." echo "Specify --force to bypass this restriction." exit 1 fi; fi } # uninstall crowdsec and cscli uninstall_crowdsec() { systemctl stop crowdsec.service 1>/dev/null systemctl disable -q crowdsec.service 1>/dev/null ${CSCLI_BIN} dashboard remove -f -y >/dev/null delete_bins # tmp rm -rf /tmp/data/ ## end tmp find /etc/crowdsec -maxdepth 1 -mindepth 1 | grep -v "bouncer" | xargs rm -rf || echo "" rm -f ${CROWDSEC_LOG_FILE} || echo "" rm -f ${LAPI_LOG_FILE} || echo "" rm -f ${CROWDSEC_DB_PATH} || echo "" rm -rf ${CROWDSEC_LIB_DIR} || echo "" rm -rf ${CROWDSEC_USR_DIR} || echo "" rm -f ${SYSTEMD_PATH_FILE} || echo "" log_info "crowdsec successfully uninstalled" } function show_link { echo "" echo "Useful links to start with Crowdsec:" echo "" echo " - Documentation : https://doc.crowdsec.net/docs/getting_started/crowdsec_tour" echo " - Crowdsec Hub : https://hub.crowdsec.net/ " echo " - Open issues : https://github.com/crowdsecurity/crowdsec/issues" echo "" echo "Useful commands to start with Crowdsec:" echo "" echo " - sudo cscli metrics : https://doc.crowdsec.net/docs/observability/cscli" echo " - sudo cscli decisions list : https://doc.crowdsec.net/docs/user_guides/decisions_mgmt" echo " - sudo cscli hub list : https://doc.crowdsec.net/docs/user_guides/hub_mgmt" echo "" echo "Next step: visualize all your alerts and explore our community CTI : https://app.crowdsec.net" echo "" } main() { if [ "$1" == "install" ] || [ "$1" == "configure" ] || [ "$1" == "detect" ]; then if [ "${SILENT}" == "false" ]; then which whiptail > /dev/null if [ $? -ne 0 ]; then log_fatal "whiptail binary is needed to use the wizard in interactive mode, exiting ..." fi fi which envsubst > /dev/null if [ $? -ne 0 ]; then log_fatal "envsubst binary is needed to use do a full install with the wizard, exiting ..." fi fi if [[ "$1" == "binupgrade" ]]; then if ! [ $(id -u) = 0 ]; then log_err "Please run the wizard as root or with sudo" exit 1 fi check_cs_version update_bins return fi if [[ "$1" == "upgrade" ]]; then if ! [ $(id -u) = 0 ]; then log_err "Please run the wizard as root or with sudo" exit 1 fi check_cs_version update_full return fi if [[ "$1" == "configure" ]]; then if ! [ $(id -u) = 0 ]; then log_err "Please run the wizard as root or with sudo" exit 1 fi detect_services ${CSCLI_BIN_INSTALLED} hub update install_collection genacquisition if ! skip_tmp_acquis; then mv "${TMP_ACQUIS_FILE}" "${ACQUIS_TARGET}" fi return fi if [[ "$1" == "noop" ]]; then return fi if [[ "$1" == "uninstall" ]]; then if ! [ $(id -u) = 0 ]; then log_err "Please run the wizard as root or with sudo" exit 1 fi check_running_bouncers uninstall_crowdsec return fi if [[ "$1" == "bininstall" ]]; then if ! [ $(id -u) = 0 ]; then log_err "Please run the wizard as root or with sudo" exit 1 fi log_info "checking existing crowdsec install" detect_cs_install log_info "installing crowdsec" install_crowdsec show_link return fi if [[ "$1" == "install" ]]; then if ! [ $(id -u) = 0 ]; then log_err "Please run the wizard as root or with sudo" exit 1 fi log_info "checking if crowdsec is installed" detect_cs_install ## Do make build before installing (as non--root) in order to have the binary and then install crowdsec as root log_info "installing crowdsec" install_crowdsec log_dbg "configuring ${CSCLI_BIN_INSTALLED}" ${CSCLI_BIN_INSTALLED} hub update --error || (log_err "fail to update crowdsec hub. exiting" && exit 1) # detect running services detect_services if ! [ ${#DETECTED_SERVICES[@]} -gt 0 ] ; then log_err "No detected or selected services, stopping." exit 1 fi; # Generate acquisition file and move it to the right folder genacquisition if ! skip_tmp_acquis; then mv "${TMP_ACQUIS_FILE}" "${ACQUIS_TARGET}" fi log_info "acquisition file path: ${ACQUIS_TARGET}" # Install collections according to detected services log_dbg "Installing needed collections ..." install_collection # install patterns/ folder log_dbg "Installing patterns" mkdir -p "${PATTERNS_PATH}" cp "./${PATTERNS_FOLDER}/"* "${PATTERNS_PATH}/" # api register ${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" log_dbg "Crowdsec LAPI registered" ${CSCLI_BIN_INSTALLED} capi register --error || log_fatal "unable to register to the Central API" systemctl enable -q crowdsec >/dev/null || log_fatal "unable to enable crowdsec" systemctl start crowdsec >/dev/null || log_fatal "unable to start crowdsec" log_info "enabling and starting crowdsec daemon" show_link return fi if [[ "$1" == "detect" ]]; then if ! skip_tmp_acquis; then rm -f "${TMP_ACQUIS_FILE}" fi detect_services if [[ ${DETECTED_SERVICES} == "" ]] ; then log_err "No detected or selected services, stopping." exit fi; log_info "Found ${#DETECTED_SERVICES[@]} supported services running:" genacquisition cat "${TMP_ACQUIS_FILE}" if ! skip_tmp_acquis; then rm "${TMP_ACQUIS_FILE}" fi return fi } usage() { echo "Usage:" echo " ./wizard.sh -h Display this help message." echo " ./wizard.sh -d|--detect Detect running services and associated logs file" echo " ./wizard.sh -i|--install Assisted installation of crowdsec/cscli and collections" echo " ./wizard.sh --bininstall Install binaries and empty config, no wizard." echo " ./wizard.sh --uninstall Uninstall crowdsec/cscli" echo " ./wizard.sh --binupgrade Upgrade crowdsec/cscli binaries" echo " ./wizard.sh --upgrade Perform a full upgrade and try to migrate configs" echo " ./wizard.sh --unattended Install in unattended mode, no question will be asked and defaults will be followed" echo " ./wizard.sh --docker-mode Will install crowdsec without systemd and generate random machine-id" echo " ./wizard.sh -n|--noop Do nothing" exit 0 } if [[ $# -eq 0 ]]; then usage fi while [[ $# -gt 0 ]] do key="${1}" case ${key} in --uninstall) ACTION="uninstall" shift # past argument ;; --binupgrade) ACTION="binupgrade" shift # past argument ;; --upgrade) ACTION="upgrade" shift # past argument ;; -i|--install) ACTION="install" shift # past argument ;; --bininstall) ACTION="bininstall" shift # past argument ;; --docker-mode) DOCKER_MODE="true" ACTION="bininstall" shift # past argument ;; -c|--configure) ACTION="configure" shift # past argument ;; -d|--detect) ACTION="detect" shift # past argument ;; -n|--noop) ACTION="noop" shift # past argument ;; --unattended) SILENT="true" ACTION="install" shift ;; -f|--force) FORCE_MODE="true" shift ;; -v|--verbose) DEBUG_MODE="true" shift ;; -h|--help) usage exit 0 ;; *) # unknown option log_err "Unknown argument ${key}." usage exit 1 ;; esac done main ${ACTION}