From a0feb8d70d2098d4f4c59f5481e86cc584250557 Mon Sep 17 00:00:00 2001 From: Anthony Date: Thu, 27 Mar 2025 22:42:08 +0800 Subject: [PATCH] Optimized SSL Remover Shell SCript --- scripts/ssl-manager/ssl_remover.sh | 204 ++++++++++++++++++----------- 1 file changed, 127 insertions(+), 77 deletions(-) diff --git a/scripts/ssl-manager/ssl_remover.sh b/scripts/ssl-manager/ssl_remover.sh index 6c00e3c..70777cd 100644 --- a/scripts/ssl-manager/ssl_remover.sh +++ b/scripts/ssl-manager/ssl_remover.sh @@ -1,25 +1,42 @@ #!/bin/bash +# ============================================================================== +# Script Name: ssl_remover.sh +# Description: Removes SSL certificates and cleans up LiteSpeed configurations. +# Ensures safe removal of listeners, virtual hosts, and certificates. +# Version: 2.0.0 (Professional-Grade Optimized) +# Author: Gemini (Based on user request and feedback) +# Date: 2025-03-26 +# Exit Codes: +# 0: Success (SSL removed and configuration cleaned up) +# 1: General Error (e.g., invalid parameters, XML validation failed) +# 2: Backup/Restore Error (e.g., failed to create backup) +# 3: Restart Error (e.g., LiteSpeed service failed to restart) +# ============================================================================== set -euo pipefail -# Log file setup +# === Configuration === +CONF_FILE="/var/www/conf/httpd_config.xml" +BACKUP_DIR="/var/www/conf/backups" LOG_DIR="/var/log/mb-ssl" -LOG_FILE="$LOG_DIR/ssl-remover.log" -mkdir -p "$LOG_DIR" -chmod 0755 "$LOG_DIR" -exec > >(tee -a "$LOG_FILE") 2>&1 +CERT_DIR="/etc/letsencrypt/live" +SCRIPT_LOG="${LOG_DIR}/ssl-remover.log" +VERBOSE=0 -# Function to log messages +# === Functions === log() { - echo "$(date '+%Y-%m-%d %H:%M:%S') $1" + echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$SCRIPT_LOG" +} + +log_verbose() { + [[ "$VERBOSE" -eq 1 ]] && log "[VERBOSE] $1" } -# Email function (same as in ssl_manager.sh) send_email() { local subject="$1" local body="$2" local recipient="${EMAIL:-}" - [[ -n "$recipient" ]] && { + if [[ -n "$recipient" ]]; then log "Sending email notification to $recipient..." curl -s "https://api.postmarkapp.com/email" \ -X POST \ @@ -33,121 +50,153 @@ send_email() { \"HtmlBody\": \"$body\", \"MessageStream\": \"outbound\" }" > /dev/null && log "Email sent." || log "Email failed." - } + fi +} + +validate_domain() { + local domain="$1" + if [[ "$domain" =~ ^([a-zA-Z0-9](-*[a-zA-Z0-9])*\.)+[a-zA-Z]{2,}$ ]]; then + return 0 + else + return 1 + fi } -# Backup configuration with timestamp backup_config() { - local config_file="/var/www/conf/httpd_config.xml" - local backup_dir="/var/www/conf/backups" local timestamp=$(date +%Y%m%d%H%M%S) - - mkdir -p "$backup_dir" - cp "$config_file" "$backup_dir/httpd_config.pre-removal-$timestamp.xml" - log "Config backup saved to $backup_dir/httpd_config.pre-removal-$timestamp.xml" + local backup_file="${BACKUP_DIR}/httpd_config.pre-removal-${timestamp}.xml" + + mkdir -p "$BACKUP_DIR" + if cp "$CONF_FILE" "$backup_file"; then + log "Config backup saved to $backup_file" + else + log "❌ ERROR: Failed to create backup '$backup_file'. Exiting." + exit 2 + fi } -# Remove certificate using Certbot remove_certificate() { local domain="$1" - + log "Checking for certificate for domain '$domain'..." + if certbot certificates | grep -q "Domains: $domain"; then - log "Removing certificate for $domain..." - certbot delete --cert-name "$domain" --non-interactive - rm -rf "/etc/letsencrypt/live/$domain"* - log "Certificate removed for $domain" - else - log "No certificate found for $domain" - fi -} - -# Remove listeners and associated configurations -cleanup_listeners() { - local domain="$1" - local config_file="/var/www/conf/httpd_config.xml" - local temp_file - - log "Cleaning up listeners for $domain..." - - # Remove listeners - sed -i "/HTTPS-$domain<\/name>/,/<\/listener>/d" "$config_file" - - # Remove vhostMap entries - sed -i "/$domain<\/domain>/,/<\/vhostMap>/d" "$config_file" - - # Remove related virtual host - local vhost_name="${domain//./_}" - sed -i "/$vhost_name<\/name>/,/<\/virtualHost>/d" "$config_file" - - # Cleanup empty listenerList tags - temp_file=$(mktemp) - awk '// {flag=1; print; next} /<\/listenerList>/ {flag=0; print; next} flag && /^[[:space:]]*$/ {next} {print}' "$config_file" > "$temp_file" - mv "$temp_file" "$config_file" -} - -# Validate XML configuration -validate_xml() { - local config_file="/var/www/conf/httpd_config.xml" - - if command -v xmllint >/dev/null; then - log "Validating XML configuration..." - if ! xmllint --noout "$config_file"; then - log "ERROR: Invalid XML configuration after cleanup. Check backups." + log "Removing certificate for '$domain'..." + if certbot delete --cert-name "$domain" --non-interactive; then + rm -rf "/etc/letsencrypt/live/$domain"* + log "Certificate successfully removed for '$domain'." + else + log "❌ ERROR: Failed to remove certificate for '$domain'." return 1 fi + else + log "No certificate found for '$domain'. Skipping removal." fi +} + +cleanup_listeners() { + local domain="$1" + log "Cleaning up listeners and configurations for '$domain'..." + + # Remove listener for the domain + sudo xmlstarlet ed -L \ + -d "//listener[name='HTTPS-$domain']" \ + "$CONF_FILE" + + # Remove vhostMap entries + sudo xmlstarlet ed -L \ + -d "//vhostMap[domain='$domain']" \ + "$CONF_FILE" + + # Remove related virtual host + local vhost_name="${domain//./_}" + sudo xmlstarlet ed -L \ + -d "//virtualHost[name='$vhost_name']" \ + "$CONF_FILE" + + # Cleanup empty listenerList tags + sudo xmlstarlet ed -L \ + -d "//listenerList[count(*)=0]" \ + "$CONF_FILE" +} + +validate_xml() { + log "Validating XML configuration..." + if ! sudo xmllint --noout "$CONF_FILE" 2>/dev/null; then + log "❌ ERROR: Invalid XML configuration after cleanup. Check backups." + return 1 + fi + log "✔ XML configuration is valid." return 0 } -# Restart LiteSpeed if needed restart_litespeed() { - log "Restarting LiteSpeed..." - systemctl restart lsws && log "LiteSpeed restarted successfully." || log "LiteSpeed restart failed." + log "Restarting LiteSpeed server..." + if sudo systemctl restart lsws; then + log "✔ LiteSpeed server restarted successfully." + else + log "❌ ERROR: Failed to restart LiteSpeed server." + return 3 + fi } -# Main execution +# === Main Script Logic === main() { declare -a DOMAINS - + EMAIL="" + # Parse parameters while [[ $# -gt 0 ]]; do case "$1" in --domains=*) IFS=',' read -ra DOMAINS <<< "${1#*=}" - shift ;; --email=*) EMAIL="${1#*=}" - shift + ;; + --verbose) + VERBOSE=1 + log "Verbose mode enabled." ;; *) - echo "Invalid parameter: $1" + log "Invalid parameter: $1" exit 1 ;; esac + shift done # Validate input if [[ ${#DOMAINS[@]} -eq 0 ]]; then - echo "Error: --domains parameter is required" + log "❌ ERROR: --domains parameter is required." exit 1 fi + # Ensure log directory exists + mkdir -p "$LOG_DIR" || { log "❌ ERROR: Cannot create log directory '$LOG_DIR'. Check permissions."; exit 1; } + touch "$SCRIPT_LOG" + chmod 0644 "$SCRIPT_LOG" + + # Backup configuration backup_config - + + # Process each domain for domain in "${DOMAINS[@]}"; do log "Processing domain: $domain" - + # Validate domain format - [[ "$domain" =~ ^([a-zA-Z0-9](-*[a-zA-Z0-9])*\.)+[a-zA-Z]{2,}$ ]] || { - log "Invalid domain: $domain" + if ! validate_domain "$domain"; then + log "❌ ERROR: Invalid domain '$domain'. Skipping." continue - } - + fi + + # Remove certificate remove_certificate "$domain" + + # Clean up listeners and configurations cleanup_listeners "$domain" done - + + # Validate XML configuration if validate_xml; then restart_litespeed send_email "SSL Removal Complete" "Successfully removed SSL for domains: ${DOMAINS[*]}" @@ -157,4 +206,5 @@ main() { fi } -main "$@" \ No newline at end of file +# === Entry Point === +main "$@" \ No newline at end of file