diff --git a/maintenance/crowdsec_removal.sh b/maintenance/crowdsec_removal.sh index e223640..1a152ce 100644 --- a/maintenance/crowdsec_removal.sh +++ b/maintenance/crowdsec_removal.sh @@ -4,7 +4,7 @@ # VARIABLES # #-----------------------------------# -this_script_url="https://git.hhf.technology/hhf/script-management-cloudpanel/raw/branch/main/maintenance/crowdsec_removal.sh" # Replace with actual URL +this_script_url="https://git.hhf.technology/hhf/script-management-cloudpanel/raw/branch/main/maintenance/crowdsec_removal.sh" this_script_name="CrowdSec Removal Script" formatter_url="https://git.hhf.technology/hhf/TaskFormatter/raw/branch/main/bash_task_formatter/task_formatter.sh" scriptname=$0 @@ -19,7 +19,7 @@ success=0 USER_TO_RUN_AS="${1:-$SUDO_USER}" USER_HOME=$(eval echo ~$USER_TO_RUN_AS) -# Logging and backup setup +# Logging setup LOGFILE="/var/log/crowdsec_removal_$(date +%Y%m%d_%H%M%S).log" BACKUP_DIR="/var/backup/crowdsec_$(date +%Y%m%d_%H%M%S)" @@ -61,23 +61,86 @@ download_formatter # FUNCTIONS # #-----------------------------------# +# Trap errors and interrupts +trap 'error_handler $? $LINENO' ERR +trap 'cleanup' EXIT +trap 'interrupt_handler' INT TERM + +# Function to handle errors +error_handler() { + local exit_code=$1 + local line_number=$2 + log_message "ERROR" "Error $exit_code occurred on line $line_number" + cleanup + exit "$exit_code" +} + +# Function to handle interrupts +interrupt_handler() { + log_message "WARNING" "Script interrupted by user" + cleanup + exit 130 +} + +# Cleanup function +cleanup() { + # Remove temporary files if they exist + [ -f "/tmp/crowdsec_services.tmp" ] && rm -f "/tmp/crowdsec_services.tmp" + [ -f "/tmp/crowdsec_packages.tmp" ] && rm -f "/tmp/crowdsec_packages.tmp" + format_output cleanup_files "Cleaning up temporary files" + format_output remove_script "Removing script" +} + # Function to check if a command exists command_exists() { command -v "$1" >/dev/null 2>&1 } +# Enhanced logging function with formatter integration +log_message() { + local level=$1 + local message=$2 + local timestamp=$(date '+%Y-%m-%d %H:%M:%S') + echo "[$timestamp] [$level] $message" >> "$LOGFILE" + case $level in + "INFO") log "$message" ;; + "WARNING") log "$message" ;; + "ERROR") log "$message" ;; + "SUCCESS") log "${CHECK_MARK} $message" ;; + esac +} + +# Function to check system requirements +check_system_requirements() { + local missing_deps=() + + # Check for required commands + for cmd in systemctl grep awk sed; do + if ! command_exists "$cmd"; then + missing_deps+=("$cmd") + fi + done + + if [ ${#missing_deps[@]} -ne 0 ]; then + log_message "ERROR" "Missing required dependencies: ${missing_deps[*]}" + return 1 + fi + return 0 +} + # Function to check if running as root check_root() { if [ "$(id -u)" -ne 0 ]; then - echo -e "Please run as root $CROSS_MARK" - exit 1 + log_message "ERROR" "Please run as root" + return 1 fi - echo -e "Running as root $CHECK_MARK" return 0 } # Function to create backup create_backup() { + log_message "INFO" "Creating backup of CrowdSec configurations..." + mkdir -p "$BACKUP_DIR" # Backup configuration files @@ -94,198 +157,169 @@ create_backup() { find "/etc/systemd/system" -name "*crowdsec*" -exec cp {} "$BACKUP_DIR/" \; fi - echo -e "Backup created at $BACKUP_DIR $CHECK_MARK" + log_message "SUCCESS" "Backup created at $BACKUP_DIR" return 0 } -# Function to check services +# Enhanced service check function check_services() { + log_message "INFO" "Checking for CrowdSec services..." systemctl list-units --type=service --all | grep -i crowdsec | awk '{print $1}' > /tmp/crowdsec_services.tmp if [ ! -s /tmp/crowdsec_services.tmp ]; then - echo -e "No CrowdSec services found $CHECK_MARK" + log_message "SUCCESS" "No CrowdSec services found." services="" return 0 else services=$(cat /tmp/crowdsec_services.tmp) - echo "Found CrowdSec services:" - cat /tmp/crowdsec_services.tmp - echo -e "Service check completed $CHECK_MARK" + log_message "WARNING" "Found CrowdSec services:" + echo "$services" | while read -r service; do + log_message "INFO" "Found service: $service" + done return 0 fi } -# Function to check packages +# Enhanced package check function check_packages() { + log_message "INFO" "Checking for CrowdSec packages..." + if command_exists dpkg; then dpkg -l | grep -i crowdsec | awk '{print $2}' > /tmp/crowdsec_packages.tmp elif command_exists rpm; then rpm -qa | grep -i crowdsec > /tmp/crowdsec_packages.tmp else - echo -e "Unable to determine package manager $CROSS_MARK" + log_message "ERROR" "Unable to determine package manager." return 1 fi if [ ! -s /tmp/crowdsec_packages.tmp ]; then - echo -e "No CrowdSec packages found $CHECK_MARK" + log_message "SUCCESS" "No CrowdSec packages found." packages="" - return 0 else packages=$(cat /tmp/crowdsec_packages.tmp) - echo "Found CrowdSec packages:" - cat /tmp/crowdsec_packages.tmp - echo -e "Package check completed $CHECK_MARK" - return 0 + log_message "WARNING" "Found CrowdSec packages:" + echo "$packages" | while read -r package; do + log_message "INFO" "Found package: $package" + done fi -} - -# Function to disable services -disable_services() { - if [ -z "$services" ]; then - echo -e "No CrowdSec services to disable $CHECK_MARK" - return 0 - fi - - local success=0 - echo "$services" | while read -r service; do - if ! systemctl stop "$service" 2>/dev/null || ! systemctl disable "$service" 2>/dev/null; then - echo -e "Failed to disable $service $CROSS_MARK" - success=1 - fi - done - - if [ $success -eq 0 ]; then - echo -e "Services disabled successfully $CHECK_MARK" - return 0 - else - echo -e "Some services failed to disable $CROSS_MARK" - return 1 - fi -} - -# Function to remove packages -remove_packages() { - if [ -z "$packages" ]; then - echo -e "No CrowdSec packages to remove $CHECK_MARK" - return 0 - fi - - # First stop and disable all CrowdSec-related services - systemctl stop 'crowdsec*' 2>/dev/null - systemctl disable 'crowdsec*' 2>/dev/null - - local success=0 - - # Debian/Ubuntu systems - if command_exists apt-get; then - # Remove CrowdSec packages - DEBIAN_FRONTEND=noninteractive apt-get remove --purge -y crowdsec crowdsec-firewall-bouncer-iptables '*crowdsec*' 2>/dev/null - DEBIAN_FRONTEND=noninteractive apt-get autoremove -y 2>/dev/null - - # Remove APT repository - rm -f /etc/apt/sources.list.d/crowdsec.list - apt-get update - - # RHEL/CentOS systems - elif command_exists yum; then - yum remove -y crowdsec crowdsec-firewall-bouncer-iptables '*crowdsec*' 2>/dev/null - yum autoremove -y 2>/dev/null - - # Remove YUM repository - rm -f /etc/yum.repos.d/crowdsec.repo - yum clean all - - # Fedora systems - elif command_exists dnf; then - dnf remove -y crowdsec crowdsec-firewall-bouncer-iptables '*crowdsec*' 2>/dev/null - dnf autoremove -y 2>/dev/null - - # Remove DNF repository - rm -f /etc/yum.repos.d/crowdsec.repo - dnf clean all - else - echo -e "No supported package manager found $CROSS_MARK" - return 1 - fi - - echo -e "Packages and repositories removed successfully $CHECK_MARK" return 0 } -# Function to remove configuration and additional files -remove_config() { - # List of locations to clean - local paths_to_clean=( - # Configuration directories - "/etc/crowdsec" - "/var/lib/crowdsec" - "/usr/local/lib/crowdsec" - "/usr/share/crowdsec" - # Binary and executable files - "/usr/local/bin/crowdsec" - "/usr/local/bin/cscli" - "/usr/bin/crowdsec" - "/usr/bin/cscli" - # Service files - "/etc/systemd/system/crowdsec.service" - "/etc/systemd/system/crowdsec-firewall-bouncer.service" - "/lib/systemd/system/crowdsec.service" - "/lib/systemd/system/crowdsec-firewall-bouncer.service" - # Log files - "/var/log/crowdsec.log" - "/var/log/crowdsec-firewall-bouncer.log" - # Additional data directories - "/var/run/crowdsec" - "/run/crowdsec" - # Database files - "/var/lib/crowdsec/data/crowdsec.db" - ) +# Enhanced service disable function +disable_services() { + log_message "INFO" "Disabling CrowdSec services..." + if [ -z "$services" ]; then + log_message "WARNING" "No CrowdSec services to disable." + return 0 + fi - local success=0 - for path in "${paths_to_clean[@]}"; do - if [ -e "$path" ]; then - if ! rm -rf "$path" 2>/dev/null; then - echo -e "Failed to remove: $path $CROSS_MARK" - success=1 + echo "$services" | while read -r service; do + systemctl stop "$service" 2>/dev/null + if [ $? -eq 0 ]; then + systemctl disable "$service" 2>/dev/null + log_message "SUCCESS" "Disabled $service" + else + log_message "ERROR" "Failed to stop $service" + return 1 + fi + done + return 0 +} + +# Enhanced package removal function +remove_packages() { + log_message "INFO" "Removing CrowdSec packages..." + if [ -z "$packages" ]; then + log_message "WARNING" "No CrowdSec packages to remove." + return 0 + fi + + local remove_cmd="" + if command_exists apt-get; then + remove_cmd="apt-get remove --purge -y" + cleanup_cmd="apt-get autoremove -y" + elif command_exists yum; then + remove_cmd="yum remove -y" + cleanup_cmd="yum autoremove -y" + elif command_exists dnf; then + remove_cmd="dnf remove -y" + cleanup_cmd="dnf autoremove -y" + else + log_message "ERROR" "No supported package manager found." + return 1 + fi + + local failed=0 + echo "$packages" | while read -r package; do + if $remove_cmd "$package"; then + log_message "SUCCESS" "Removed package: $package" + else + log_message "ERROR" "Failed to remove package: $package" + failed=1 + fi + done + + if [ $failed -eq 0 ] && $cleanup_cmd; then + log_message "SUCCESS" "Cleaned up dependencies" + return 0 + fi + return 1 +} + +# Enhanced repository removal function +remove_apt_repos() { + log_message "INFO" "Removing CrowdSec repository entries..." + if ! command_exists apt-get; then + log_message "INFO" "System is not Debian/Ubuntu based, skipping repo removal" + return 0 + fi + + local repo_files=("/etc/apt/sources.list" "/etc/apt/sources.list.d/"*) + local failed=0 + + for file in "${repo_files[@]}"; do + if [ -f "$file" ] && grep -q "crowdsec" "$file"; then + if sed -i '/crowdsec/d' "$file"; then + log_message "SUCCESS" "Removed CrowdSec entry from $file" else - echo -e "Removed: $path $CHECK_MARK" + log_message "ERROR" "Failed to remove CrowdSec entry from $file" + failed=1 fi fi done - # Clean up any remaining crowdsec processes - pkill -f crowdsec 2>/dev/null - - # Reload systemd to recognize the changes - systemctl daemon-reload 2>/dev/null - - if [ $success -eq 0 ]; then - echo -e "All CrowdSec files and configurations removed successfully $CHECK_MARK" + if [ $failed -eq 0 ] && apt-get update >/dev/null 2>&1; then + log_message "SUCCESS" "APT repositories updated" return 0 - else - echo -e "Some files or configurations could not be removed $CROSS_MARK" - return 1 fi + return 1 } -# Remove created files on cleanup -cleanup_files() { - rm -f /tmp/crowdsec_services.tmp /tmp/crowdsec_packages.tmp - echo -e "Cleaned up temporary files $CHECK_MARK" - return 0 -} - -# Remove the script itself -remove_script() { - if [ -f "$0" ]; then - echo "Removing monitoring script..." - rm -- "$0" - fi - if [ -f "task_formatter.sh" ]; then - rm task_formatter.sh - fi - echo -e "Cleaned up $CHECK_MARK" - return 0 +# Enhanced configuration removal function +remove_config() { + log_message "INFO" "Removing CrowdSec configuration files..." + + local config_dirs=( + "/etc/crowdsec" + "/var/lib/crowdsec" + "/usr/local/lib/crowdsec" + "/usr/share/crowdsec" + ) + + local failed=0 + for dir in "${config_dirs[@]}"; do + if [ -d "$dir" ]; then + if rm -rf "$dir" 2>/dev/null; then + log_message "SUCCESS" "Removed directory: $dir" + else + log_message "ERROR" "Failed to remove directory: $dir" + failed=1 + fi + fi + done + + [ $failed -eq 0 ] && return 0 || return 1 } #-----------------------------------# @@ -297,33 +331,36 @@ print_header "$this_script_name" "$this_script_url" echo -e "Running as User: $USER_TO_RUN_AS\nUser Home: $USER_HOME\n" -# Run with formatted output +# Check requirements if ! format_output check_root "Checking root privileges"; then - cleanup_files - success=1 + cleanup + exit 1 fi -if ! format_output check_services "Checking CrowdSec services"; then - cleanup_files - success=1 +if ! format_output check_system_requirements "Checking system requirements"; then + cleanup + exit 1 fi -if ! format_output check_packages "Checking CrowdSec packages"; then - cleanup_files - success=1 -fi +# Initialize log file +touch "$LOGFILE" || { echo "Cannot create log file"; exit 1; } +log_message "INFO" "Starting CrowdSec removal script v${VERSION}" + +# Check current state +format_output check_services "Checking CrowdSec services" +format_output check_packages "Checking CrowdSec packages" if [ -z "$services" ] && [ -z "$packages" ]; then - echo -e "No CrowdSec components found on your system $CHECK_MARK" - format_output cleanup_files "Cleaning up temporary files" - format_output remove_script "Removing script" + log_message "SUCCESS" "No CrowdSec components found on your system." + cleanup exit 0 fi -echo "What would you like to do?" +# Interactive menu +log_message "INFO" "What would you like to do?" echo "1) Disable CrowdSec services" echo "2) Remove CrowdSec packages" -echo "3) Remove everything (services, packages, and configuration)" +echo "3) Remove everything (services, packages, configuration, and repositories)" echo "4) Exit without changes" read -r -p "Enter your choice (1-4): " choice @@ -333,22 +370,17 @@ case $choice in 2) format_output remove_packages "Removing CrowdSec packages" ;; 3) format_output create_backup "Creating backup" - format_output disable_services "Disabling CrowdSec services" - format_output remove_packages "Removing CrowdSec packages" - format_output remove_config "Removing CrowdSec configuration" - ;; - 4) - echo -e "Exiting without changes $CHECK_MARK" - success=0 - ;; - *) - echo -e "Invalid choice $CROSS_MARK" - success=1 + format_output disable_services "Disabling services" + format_output remove_packages "Removing packages" + format_output remove_apt_repos "Removing repositories" + format_output remove_config "Removing configuration" ;; + 4) log_message "INFO" "Exiting without changes."; cleanup; exit 0 ;; + *) log_message "ERROR" "Invalid choice."; cleanup; exit 1 ;; esac -format_output cleanup_files "Cleaning up temporary files" -format_output remove_script "Removing script" +log_message "SUCCESS" "Operations completed successfully." +echo "Log file available at: $LOGFILE" # Exit with appropriate status exit $success \ No newline at end of file