Securing CloudPanel on Ubuntu 24.04 Part 7

18/11/2024 18/11/2024 security 5 mins read
Table Of Contents

Part 7: SSL Certificate Management and Security #

Let’s create a comprehensive SSL certificate management system:

Terminal window
# Create SSL certificate management script
sudo nano /usr/local/bin/cloudpanel-ssl-manager.sh

#

#!/bin/bash
# Initialize paths and configuration
CP_HOME="/home/clp"
DB_PATH="${CP_HOME}/htdocs/app/data/db.sq3"
SSL_DIR="${CP_HOME}/services/nginx/ssl-certificates"
LOG_DIR="${CP_HOME}/logs/ssl"
mkdir -p "$SSL_DIR" "$LOG_DIR"
# Function to get certificate information from CloudPanel database
get_certificate_info() {
sqlite3 "$DB_PATH" "
SELECT
c.id,
c.site_id,
c.uid,
c.expires_at,
c.type,
s.domain_name,
s.user
FROM certificate c
JOIN site s ON c.site_id = s.id
WHERE c.default_certificate = 1;"
}
# Function to monitor certificate expiration
monitor_certificates() {
echo "Monitoring SSL certificates..."
local current_time=$(date +%s)
while IFS='|' read -r cert_id site_id uid expires domain user; do
# Convert expires_at to timestamp
local expire_time=$(date -d "$expires" +%s)
local days_remaining=$(( ($expire_time - $current_time) / 86400 ))
echo "Checking certificate for $domain (Expires in $days_remaining days)"
# Alert if certificate is expiring soon
if [ $days_remaining -lt 30 ]; then
handle_expiring_certificate "$domain" "$days_remaining" "$cert_id"
fi
# Verify certificate chain
verify_certificate_chain "$domain" "$cert_id"
done < <(get_certificate_info)
}
# Function to verify and secure certificates
verify_certificate_chain() {
local domain="$1"
local cert_id="$2"
# Get certificate chain from database
local cert_path="${SSL_DIR}/${domain}.crt"
local key_path="${SSL_DIR}/${domain}.key"
# Extract certificate data from database
sqlite3 "$DB_PATH" "
SELECT
certificate,
private_key,
certificate_chain
FROM certificate
WHERE id = $cert_id;" | while IFS='|' read -r cert key chain; do
# Save certificate files with proper permissions
echo "$cert" > "$cert_path"
echo "$key" > "$key_path"
chmod 644 "$cert_path"
chmod 600 "$key_path"
# Verify certificate chain
if ! openssl verify -CAfile <(echo "$chain") "$cert_path" > /dev/null 2>&1; then
log_ssl_error "$domain" "Certificate chain verification failed"
fi
# Verify certificate matches private key
cert_modulus=$(openssl x509 -noout -modulus -in "$cert_path" | openssl md5)
key_modulus=$(openssl rsa -noout -modulus -in "$key_path" | openssl md5)
if [ "$cert_modulus" != "$key_modulus" ]; then
log_ssl_error "$domain" "Certificate and private key mismatch"
fi
done
}
# Function to handle expiring certificates
handle_expiring_certificate() {
local domain="$1"
local days="$2"
local cert_id="$3"
echo "Certificate for $domain is expiring in $days days"
# Log the expiration warning
local message="SSL Certificate Expiration Warning for $domain"
local details="Certificate will expire in $days days"
# Update CloudPanel notification system
sqlite3 "$DB_PATH" "
INSERT INTO notification (
created_at,
updated_at,
severity,
subject,
message,
is_read
) VALUES (
datetime('now'),
datetime('now'),
'warning',
'$message',
'$details',
0
);"
}
# Function to update Nginx SSL configuration
update_nginx_ssl_config() {
local domain="$1"
local cert_id="$2"
# Get site configuration path
local nginx_conf="${CP_HOME}/services/nginx/sites-enabled/${domain}.conf"
# Update SSL configuration
cat > "$nginx_conf" <<EOF
server {
listen 443 ssl http2;
server_name ${domain};
# SSL Configuration
ssl_certificate ${SSL_DIR}/${domain}.crt;
ssl_certificate_key ${SSL_DIR}/${domain}.key;
# Modern SSL Configuration
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers off;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256;
# OCSP Stapling
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;
# Security Headers
add_header Strict-Transport-Security "max-age=63072000" always;
add_header X-Frame-Options SAMEORIGIN;
add_header X-Content-Type-Options nosniff;
# Additional security headers for SSL
add_header Content-Security-Policy "default-src 'self' https: data: 'unsafe-inline' 'unsafe-eval'; frame-ancestors 'self'";
}
# Redirect HTTP to HTTPS
server {
listen 80;
server_name ${domain};
return 301 https://$server_name$request_uri;
}
EOF
}
# Function to log SSL-related events
log_ssl_event() {
local domain="$1"
local message="$2"
local level="$3"
echo "[$(date '+%Y-%m-%d %H:%M:%S')] [$level] $domain: $message" >> "${LOG_DIR}/ssl-events.log"
}
# Main execution
main() {
echo "Starting SSL certificate management..."
# Create backup of current SSL configurations
backup_date=$(date +%Y%m%d_%H%M%S)
backup_dir="${CP_HOME}/backups/ssl_${backup_date}"
mkdir -p "$backup_dir"
cp -r "$SSL_DIR" "$backup_dir/"
# Monitor and update certificates
monitor_certificates
# Set up daily certificate monitoring
if ! crontab -l | grep -q "cloudpanel-ssl-manager.sh"; then
(crontab -l 2>/dev/null; echo "0 0 * * * /usr/local/bin/cloudpanel-ssl-manager.sh") | crontab -
fi
echo "SSL certificate management completed successfully"
}
main "$@"

This script provides:

  1. Comprehensive SSL certificate management based on CloudPanel’s database structure
  2. Automatic monitoring of certificate expiration
  3. Certificate chain verification
  4. Private key security
  5. Nginx SSL configuration management
  6. Integration with CloudPanel’s notification system

To implement this SSL management system:

Terminal window
# Make the script executable
chmod +x /usr/local/bin/cloudpanel-ssl-manager.sh
# Run the script
/usr/local/bin/cloudpanel-ssl-manager.sh