diff --git a/mbadmin.jps b/mbadmin.jps index dc11dc1..f17c525 100644 --- a/mbadmin.jps +++ b/mbadmin.jps @@ -617,6 +617,79 @@ actions: - return: type: info message: "${response.out}" + clean_cert_references: + - cmd[cp]: + user: root + commands: + - | + DOMAIN="${settings.domain}" + CONF_FILE="/var/www/conf/httpd_config.xml" + BACKUP_FILE="${CONF_FILE}.bak.$(date +%Y%m%d%H%M%S)" + + # Create backup + cp "${CONF_FILE}" "${BACKUP_FILE}" + echo "Created backup at ${BACKUP_FILE}" + + # Create temp file for processing + TEMP_FILE=$(mktemp) + + # Clean up certificate references + echo "Cleaning up certificate references for ${DOMAIN}..." + + # Use awk with proper quoting and domain variable handling + awk -v domain="${DOMAIN}" ' + BEGIN { in_listener = 0; is_shared = 0; } + + // { + in_listener = 1; + print; + next; + } + + in_listener && (/HTTPS<\/name>/ || /HTTPS-ipv6<\/name>/) { + is_shared = 1; + print; + next; + } + + in_listener && is_shared && /.*live\/'"${DOMAIN}"'\/.*<\/keyFile>/ { + print " /var/www/conf/default.key"; + next; + } + + in_listener && is_shared && /.*live\/'"${DOMAIN}"'\/.*<\/certFile>/ { + print " /var/www/conf/default.crt"; + next; + } + + /<\/listener>/ { + in_listener = 0; + is_shared = 0; + print; + next; + } + + { print; } + ' "${CONF_FILE}" > "${TEMP_FILE}" + + # Verify the file is valid + if grep -q "" "${TEMP_FILE}" && grep -q "" "${TEMP_FILE}"; then + # Apply changes + cat "${TEMP_FILE}" > "${CONF_FILE}" + rm -f "${TEMP_FILE}" + echo "Certificate references cleaned up successfully." + + # Restart LiteSpeed + echo "Restarting LiteSpeed..." + systemctl restart lsws + else + echo "ERROR: Generated config is invalid. Keeping original configuration." + rm -f "${TEMP_FILE}" + 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 bf29679..4c773e4 100644 --- a/scripts/ssl-manager/ssl_manager.sh +++ b/scripts/ssl-manager/ssl_manager.sh @@ -188,55 +188,24 @@ validate_xml_config() { log "Validating XML configuration..." - # Check if xmllint is available - if ! command -v xmllint >/dev/null 2>&1; then - log "WARNING: xmllint not available. Skipping XML validation." - return 0 # Return success and continue + # Check basic tag balance first + local open_listeners=$(grep -c '' "$config_file") + local close_listeners=$(grep -c '' "$config_file") + + if [ "$open_listeners" -ne "$close_listeners" ]; then + log "ERROR: Listener tag mismatch (${open_listeners} open vs ${close_listeners} close)" + return 1 fi - - # Create a temporary validation copy (don't modify the original yet) - local validate_file=$(mktemp) - if [ ! -f "$validate_file" ]; then - log "Error: Failed to create temporary file for validation." - return 0 # Continue without validation rather than failing + + # Use xmllint if available + if command -v xmllint >/dev/null; then + if ! xmllint --noout "$config_file"; then + log "ERROR: XML validation failed with xmllint" + return 1 + fi fi - - # Copy the file - don't try to fix formatting - cp "$config_file" "$validate_file" - - # Try basic validation first - if xmllint --noout "$validate_file" 2>/dev/null; then - log "XML configuration validation passed." - rm -f "$validate_file" - return 0 - fi - - # Validation failed - attempt a simple check to see if main tags are balanced - local open_http=$(grep -c "" "$config_file") - local close_http=$(grep -c "" "$config_file") - local open_listeners=$(grep -c "" "$config_file") - local close_listeners=$(grep -c "" "$config_file") - - if [ "$open_http" -eq "$close_http" ] && [ "$open_listeners" -eq "$close_listeners" ]; then - log "WARNING: XML syntax validation failed but basic structure seems intact. Proceeding with caution." - rm -f "$validate_file" - return 0 # Continue anyway - LiteSpeed may be more forgiving than xmllint - fi - - # If we reach here, validation failed and basic structure check failed - log "ERROR: XML validation failed. Configuration file may be corrupted." - log "Found $open_http opening and $close_http closing httpServerConfig tags" - log "Found $open_listeners opening and $close_listeners closing listener tags" - - rm -f "$validate_file" - - if [ -f "$backup_file" ]; then - log "Restoring from backup..." - cp "$backup_file" "$config_file" - log "Backup restored. Please check your configuration manually." - fi - - return 1 + + return 0 } # Function to clean up redundant listeners with more reliable pattern matching @@ -429,96 +398,67 @@ create_domain_listener() { local cert_file="/etc/letsencrypt/live/$domain/fullchain.pem" local timestamp=$(date +%Y%m%d%H%M%S) local backup_file="${config_file}.backup.${timestamp}" - + log "Creating/updating domain-specific HTTPS listener for $domain..." # Create backup if not already done - if [ ! -f "$backup_file" ]; then - cp "$config_file" "$backup_file" - log "Created backup of LiteSpeed configuration at $backup_file" - fi - - # Check if listener already exists + [ -f "$backup_file" ] || cp "$config_file" "$backup_file" + + # Check for existing listener if grep -q "HTTPS-$domain" "$config_file"; then - log "HTTPS listener for $domain already exists, updating configuration..." - - # Update certificate paths in existing listener - sed -i "/HTTPS-$domain<\/name>/,/<\/listener>/ s|.*|$key_file|" "$config_file" - sed -i "/HTTPS-$domain<\/name>/,/<\/listener>/ s|.*|$cert_file|" "$config_file" - - # Verify updates were applied - if grep -A5 "HTTPS-$domain" "$config_file" | grep -q "$key_file"; then - log "Certificate paths updated successfully for $domain listener." - else - log "ERROR: Failed to update certificate paths for $domain listener." - return 1 - fi - + log "Updating existing listener for $domain..." + # Use full XML scope for replacements + sed -i "/HTTPS-$domain<\/name>/,/<\/listener>/ { + s|.*|$key_file|; + s|.*|$cert_file|; + }" "$config_file" return 0 fi - + log "Creating new HTTPS listener for $domain..." - # Create a temporary file for XML editing - local temp_file=$(mktemp) - if [ ! -f "$temp_file" ]; then - log "ERROR: Failed to create temporary file for configuration update." - return 1 - fi - - # Insert new listener into configuration before listenerList end tag - awk -v domain="$domain" -v vhost="$vhost_name" -v key="$key_file" -v cert="$cert_file" ' + # Generate properly indented XML block + listener_xml=$(cat < + HTTPS-${domain} +
*:443
+ 1 + + + ${vhost_name} + ${domain} + + + ${key_file} + ${cert_file} + 24 + ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384 +
+EOF + ) + + # Insert new listener before the listenerList closing tag + awk -v xml="$listener_xml" ' /<\/listenerList>/ { - print " " - print " HTTPS-" domain "" - print "
*:443
" - print " 1" - print " " - print " " - print " " vhost "" - print " " domain "" - print " " - print " " - print " " key "" - print " " cert "" - print " 1" - print " 24" - print " ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384" - print " 1" - print " 1" - print " 15" - print "
" + print xml print $0 + inserted=1 next } { print } - ' "$config_file" > "$temp_file" - - # Validate the temporary file - if [ ! -s "$temp_file" ]; then - log "ERROR: Generated configuration is empty. Keeping original configuration." - rm -f "$temp_file" + END { + if (!inserted) { + print "ERROR: Failed to find listenerList closing tag" + exit 1 + } + }' "$config_file" > "${config_file}.tmp" && mv "${config_file}.tmp" "$config_file" + + # Validate XML structure after modification + if ! validate_xml_config "$config_file" "$backup_file"; then + log "ERROR: Failed to create valid listener for $domain" return 1 fi - - # Check for basic XML validity - if ! grep -q "" "$temp_file" || ! grep -q "" "$temp_file"; then - log "ERROR: Generated configuration appears invalid. Keeping original configuration." - rm -f "$temp_file" - return 1 - fi - - # Apply changes - cp "$temp_file" "$config_file" - if [ $? -ne 0 ]; then - log "ERROR: Failed to update configuration file. Keeping original configuration." - rm -f "$temp_file" - return 1 - fi - - # Clean up temp file - rm -f "$temp_file" - + log "Domain-specific HTTPS listener for $domain created successfully." return 0 } @@ -674,46 +614,25 @@ remove_domain_from_shared_listeners() { return 0 } -# Restart LiteSpeed with extra verification +# Revised service restart with pre-check restart_litespeed() { log "Restarting LiteSpeed web server..." - # Verify configuration before restart - if command -v /usr/local/lsws/bin/lshttpd > /dev/null; then - log "Verifying LiteSpeed configuration before restart..." - /usr/local/lsws/bin/lshttpd -t - if [ $? -ne 0 ]; then - log "ERROR: LiteSpeed configuration test failed. Not restarting server." - return 1 - fi - log "LiteSpeed configuration verified successfully." + # Configuration test first + if /usr/local/lsws/bin/lshttpd -t 2>&1 | grep -q "Configuration file check failed"; then + log "ERROR: Configuration test failed, not restarting" + return 1 fi - # Now restart the service - if systemctl is-active --quiet lsws; then - systemctl restart lsws - if [ $? -ne 0 ]; then - log "ERROR: Failed to restart LiteSpeed. Please check logs." - return 1 - fi - - # Verify LiteSpeed is running after restart - sleep 2 - if ! systemctl is-active --quiet lsws; then - log "ERROR: LiteSpeed failed to start after restart. Please check logs." - return 1 - fi - - log "LiteSpeed successfully restarted." - else - systemctl start lsws - if [ $? -ne 0 ]; then - log "ERROR: Failed to start LiteSpeed. Please check logs." - return 1 - fi - log "LiteSpeed was not running. Started the service." + systemctl restart lsws + sleep 2 + + if ! systemctl is-active --quiet lsws; then + log "ERROR: LiteSpeed failed to start" + return 1 fi + log "LiteSpeed successfully restarted" return 0 }