From bdb471340e103c3eb68b1a216b0b7b6fec85385e Mon Sep 17 00:00:00 2001 From: Anthony Date: Sat, 22 Mar 2025 00:55:28 +0800 Subject: [PATCH] Added SSL Cert Removal --- mbadmin.jps | 31 +++++ scripts/ssl-manager/ssl_manager.sh | 206 +++++++++++++++++++++++++++++ 2 files changed, 237 insertions(+) diff --git a/mbadmin.jps b/mbadmin.jps index a53adea..7e9de3f 100644 --- a/mbadmin.jps +++ b/mbadmin.jps @@ -137,6 +137,12 @@ menu: action: check_domain_ip settings: checkDomainConfig successText: "${response.out}" + - confirmText: Are you sure you want to remove the SSL certificate for this domain? + loadingText: Removing SSL Certificate... + caption: Remove SSL Certificate + action: remove_ssl_cert + settings: sslRemoveConfig + successText: "SSL certificate for '${settings.domain}' has been successfully removed." settings: checkDomainConfig: @@ -256,6 +262,17 @@ settings: type: text caption: Email Address required: true + sslRemoveConfig: + submitUnchanged: true + fields: + - name: domain + type: text + caption: Domain Name + required: true + - name: confirm + type: checkbox + caption: I confirm I want to remove this certificate + value: false actions: dynamic_wp_cli: @@ -570,6 +587,20 @@ actions: - return: type: info message: "${response.out}" + remove_ssl_cert: + - cmd[cp]: + user: root + commands: + - > + if [[ "${settings.confirm}" == "true" ]]; then + bash /home/litespeed/mbmanager/ssl-manager/ssl_manager.sh --domain="${settings.domain}" --remove-cert=yes --confirm=yes + else + echo "Confirmation checkbox must be checked to proceed with certificate removal." + exit 1 + fi + - return: + type: info + message: "${response.out}" responses: enableSuccess: diff --git a/scripts/ssl-manager/ssl_manager.sh b/scripts/ssl-manager/ssl_manager.sh index 432b937..833e1c9 100644 --- a/scripts/ssl-manager/ssl_manager.sh +++ b/scripts/ssl-manager/ssl_manager.sh @@ -716,6 +716,198 @@ restart_litespeed() { return 0 } +# Function to remove SSL certificate and its configuration +remove_ssl_certificate() { + local domain="$1" + local confirm="${2:-no}" + + if [[ -z "$domain" ]]; then + log "Error: Domain parameter is required for certificate removal." + return 1 + fi + + # Check if certificate exists + if [[ ! -d "/etc/letsencrypt/live/$domain" && ! -d "/etc/letsencrypt/archive/$domain" ]]; then + log "Certificate for $domain not found. Nothing to remove." + return 1 + fi + + # Confirm removal if not forced + if [[ "$confirm" != "yes" ]]; then + log "WARNING: This will remove the SSL certificate for $domain and update LiteSpeed configuration." + log "Please run again with --confirm=yes to proceed with removal." + return 1 + fi + + log "Starting removal of SSL certificate for $domain..." + + # 1. Backup LiteSpeed configuration before making changes + local config_file="/var/www/conf/httpd_config.xml" + local vhost_config="/var/www/conf/vhconf.xml" + local timestamp=$(date +%Y%m%d%H%M%S) + local backup_file="${config_file}.removal.${timestamp}" + local vhost_backup="${vhost_config}.removal.${timestamp}" + + cp "$config_file" "$backup_file" + log "Created backup of LiteSpeed configuration at $backup_file" + + if [ -f "$vhost_config" ]; then + cp "$vhost_config" "$vhost_backup" + log "Created backup of virtual host configuration at $vhost_backup" + fi + + # 2. Remove domain-specific listener from LiteSpeed configuration + log "Removing domain-specific listener from LiteSpeed configuration..." + local temp_file=$(mktemp) + if [ ! -f "$temp_file" ]; then + log "ERROR: Failed to create temporary file for configuration update." + return 1 + fi + + # Remove the HTTPS-domain listener section + awk -v domain="$domain" ' + BEGIN { skip = 0; } + /HTTPS-'"$domain"'<\/name>/,/<\/listener>/ { + if ($0 ~ /HTTPS-'"$domain"'<\/name>/) { + skip = 1; + print ""; + } + if ($0 ~ /<\/listener>/ && skip == 1) { + skip = 0; + next; + } + if (skip) next; + } + { if (!skip) print; } + ' "$config_file" > "$temp_file" + + # 3. Remove from domain-specific virtual host if it exists + log "Removing domain-specific virtual host if it exists..." + local vhost_name="${domain//[.]/_}" + + awk -v vhost="$vhost_name" ' + BEGIN { skip = 0; } + /'"$vhost"'<\/name>/,/<\/virtualHost>/ { + if ($0 ~ /'"$vhost"'<\/name>/) { + skip = 1; + print ""; + } + if ($0 ~ /<\/virtualHost>/ && skip == 1) { + skip = 0; + next; + } + if (skip) next; + } + { if (!skip) print; } + ' "$temp_file" > "${temp_file}.new" + + # 4. Remove any domain mappings from shared listeners + log "Removing domain mappings from shared listeners..." + awk -v domain="$domain" ' + BEGIN { in_vhostmap = 0; skip_vhostmap = 0; vhostmap_buffer = ""; } + // { + in_vhostmap = 1; + vhostmap_buffer = $0 "\n"; + next; + } + in_vhostmap == 1 { + vhostmap_buffer = vhostmap_buffer $0 "\n"; + if ($0 ~ /'"$domain"'<\/domain>/) { + skip_vhostmap = 1; + } + if ($0 ~ /<\/vhostMap>/) { + if (skip_vhostmap == 0) { + printf "%s", vhostmap_buffer; + } else { + print ""; + } + in_vhostmap = 0; + skip_vhostmap = 0; + vhostmap_buffer = ""; + } + next; + } + { print; } + ' "${temp_file}.new" > "${temp_file}.final" + + # Verify the processed file is valid + if [ ! -s "${temp_file}.final" ]; then + log "ERROR: Generated configuration is empty. Keeping original configuration." + rm -f "$temp_file" "${temp_file}.new" "${temp_file}.final" + return 1 + fi + + # Check for basic XML validity (main structure tags) + if ! grep -q "" "${temp_file}.final" || ! grep -q "" "${temp_file}.final"; then + log "ERROR: Generated configuration appears invalid. Keeping original configuration." + rm -f "$temp_file" "${temp_file}.new" "${temp_file}.final" + return 1 + fi + + # Apply changes + cp "${temp_file}.final" "$config_file" + rm -f "$temp_file" "${temp_file}.new" "${temp_file}.final" + + # 5. Clean up any references in vhconf.xml files + log "Cleaning up references in vhost configuration files..." + find /var/www/conf -name "vhconf.xml" -type f -exec grep -l "$domain" {} \; | while read vhconf_file; do + log "Cleaning references in $vhconf_file..." + sed -i "/$domain/d" "$vhconf_file" + done + + # 6. Use certbot to revoke and delete the certificate + log "Revoking and removing certificate using Certbot..." + if certbot revoke --cert-name "$domain" --delete-after-revoke --non-interactive; then + log "Certificate for $domain successfully revoked and removed." + else + # If certbot revoke fails, try direct removal + log "Certbot revoke failed. Attempting direct removal of certificate files..." + rm -rf "/etc/letsencrypt/live/$domain" "/etc/letsencrypt/archive/$domain" "/etc/letsencrypt/renewal/$domain.conf" + + # Remove any symlinks that might point to the domain + find /etc/letsencrypt -type l -exec ls -l {} \; | grep "$domain" | cut -d " " -f 9 | xargs -r rm + + log "Certificate files for $domain removed directly." + fi + + # 7. Clean up Apache configuration if exists (some servers might have Apache installed) + if [ -d "/etc/apache2" ]; then + log "Checking for Apache configuration references..." + find /etc/apache2 -name "*.conf" -type f -exec grep -l "$domain" {} \; | while read apache_conf; do + log "Cleaning references in $apache_conf..." + sed -i "/$domain/d" "$apache_conf" + done + elif [ -d "/etc/httpd" ]; then + log "Checking for Apache configuration references..." + find /etc/httpd -name "*.conf" -type f -exec grep -l "$domain" {} \; | while read apache_conf; do + log "Cleaning references in $apache_conf..." + sed -i "/$domain/d" "$apache_conf" + done + fi + + # 8. Clean up LiteSpeed logs for this domain + log "Cleaning up log files for $domain..." + find /var/log/lsws/ -name "*$domain*" -type f -delete + + # 9. Clean related cache files + log "Cleaning related cache files..." + find /var/www/webroot/ROOT/.well-known/acme-challenge/ -type f -delete 2>/dev/null + + # 10. Restart LiteSpeed to apply configuration changes + if restart_litespeed; then + log "LiteSpeed restarted successfully after certificate removal." + else + log "ERROR: Failed to restart LiteSpeed after certificate removal." + return 1 + fi + + # 11. Send email notification if configured + send_email "$domain SSL Certificate Removed" "The SSL certificate for $domain has been successfully removed from the server and all related configuration has been cleaned up." + + log "SSL certificate removal completed successfully for $domain." + return 0 +} + # Parse input parameters for arg in "$@"; do case $arg in @@ -728,6 +920,12 @@ for arg in "$@"; do --email=*) EMAIL="${arg#*=}" ;; + --remove-cert=*) + REMOVE_CERT="${arg#*=}" + ;; + --confirm=*) + CONFIRM="${arg#*=}" + ;; *) echo "Invalid argument: $arg" exit 1 @@ -735,6 +933,14 @@ for arg in "$@"; do esac done +# Check for certificate removal request +if [[ -n "${REMOVE_CERT:-}" ]]; then + if [[ "${REMOVE_CERT}" == "yes" ]]; then + remove_ssl_certificate "${DOMAIN}" "${CONFIRM:-no}" + exit $? + fi +fi + # Input validation log "Validating inputs..." if [[ -z "${PUBLIC_IP:-}" || -z "${DOMAIN:-}" ]]; then