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}