mb-admin/scripts/ssl-manager/ssl_remover.sh

210 lines
5.9 KiB
Bash

#!/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
# === Configuration ===
CONF_FILE="/var/www/conf/httpd_config.xml"
BACKUP_DIR="/var/www/conf/backups"
LOG_DIR="/var/log/mb-ssl"
CERT_DIR="/etc/letsencrypt/live"
SCRIPT_LOG="${LOG_DIR}/ssl-remover.log"
VERBOSE=0
# === Functions ===
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$SCRIPT_LOG"
}
log_verbose() {
[[ "$VERBOSE" -eq 1 ]] && log "[VERBOSE] $1"
}
send_email() {
local subject="$1"
local body="$2"
local recipient="${EMAIL:-}"
if [[ -n "$recipient" ]]; then
log "Sending email notification to $recipient..."
curl -s "https://api.postmarkapp.com/email" \
-X POST \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-H "X-Postmark-Server-Token: d88b25c4-2fdb-43d3-9097-f6c655a9742b" \
-d "{
\"From\": \"admin@mightybox.io\",
\"To\": \"$recipient\",
\"Subject\": \"$subject\",
\"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_config() {
local timestamp=$(date +%Y%m%d%H%M%S)
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() {
local domain="$1"
log "Checking for certificate for domain '$domain'..."
if certbot certificates | grep -q "Domains: $domain"; then
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() {
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 Script Logic ===
main() {
declare -a DOMAINS
EMAIL=""
# Parse parameters
while [[ $# -gt 0 ]]; do
case "$1" in
--domains=*)
IFS=',' read -ra DOMAINS <<< "${1#*=}"
;;
--email=*)
EMAIL="${1#*=}"
;;
--verbose)
VERBOSE=1
log "Verbose mode enabled."
;;
*)
log "Invalid parameter: $1"
exit 1
;;
esac
shift
done
# Validate input
if [[ ${#DOMAINS[@]} -eq 0 ]]; then
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
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[*]}"
else
send_email "SSL Removal Warning" "SSL removed but configuration validation failed for domains: ${DOMAINS[*]}"
exit 1
fi
}
# === Entry Point ===
main "$@"