Skip to content

quinnoshea/cert-spreader

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

97 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Certificate Spreader

License Bash Python Codacy Badge Codacy Badge Status CI

Overview

A practical SSL certificate deployment tool for automating the secure distribution of certificates across multiple hosts. Supports multiple certificate formats, service management, and comprehensive logging.

Key Capabilities

  • Multi-format certificate generation: PKCS#12, PEM, DER, JKS, and custom formats
  • Intelligent service management: Automatic reload/restart with fallback handling
  • Security-focused: Configurable permissions, SSH key authentication, audit logging
  • Dual implementation: Identical functionality in both Bash and Python
  • Reliable operations: Idempotent operations, comprehensive error handling, dry-run validation

Table of Contents


Quick Start

Prerequisites

System Requirements

  • Linux/Unix environment with SSH access to target hosts
  • Bash 4.0+ or Python 3.9+
  • Valid SSL certificates (Let's Encrypt recommended)
  • Standard tools: rsync, ssh, openssl

For Python Implementation

pip install requests

5-Minute Setup

# 1. Clone and configure
git clone <repository-url>
cd cert-spreader
cp config.example.conf config.conf

# 2. Edit configuration (see Configuration section)
nano config.conf

# 3. Set up SSH keys
ssh-keygen -t ed25519 -f ~/.ssh/cert_spreader_key
ssh-copy-id -i ~/.ssh/cert_spreader_key user@target-host

# 4. Validate configuration
./cert-spreader.sh --dry-run  # or ./cert-spreader.py --dry-run

# 5. Deploy certificates
./cert-spreader.sh            # or ./cert-spreader.py

Installation

System Deployment

# Create dedicated system user (recommended)
sudo useradd -r -s /bin/bash -d /opt/cert-spreader cert-spreader

# Install to system location
sudo mkdir -p /opt/cert-spreader
sudo cp cert-spreader.{sh,py} config.example.conf /opt/cert-spreader/
sudo chown -R cert-spreader:cert-spreader /opt/cert-spreader
sudo chmod +x /opt/cert-spreader/cert-spreader.{sh,py}

# Configure logging
sudo mkdir -p /var/log/cert-spreader
sudo chown cert-spreader:cert-spreader /var/log/cert-spreader

Dependencies

Bash Version (cert-spreader.sh)

  • No additional dependencies required
  • Uses standard Unix tools: rsync, ssh, openssl, curl, sha256sum

Python Version (cert-spreader.py)

# Required Python packages
pip install requests

# System packages (Ubuntu/Debian)
sudo apt update && sudo apt install python3-requests

# System packages (RHEL/CentOS/Fedora)  
sudo dnf install python3-requests

Integration with Certificate Authorities

Let's Encrypt Integration

# Add post-renewal hook
# Add to Let's Encrypt renewal configuration if using certbot
echo 'post_hook = /opt/cert-spreader/cert-spreader.sh' >> /etc/letsencrypt/renewal/yourdomain.com.conf

# Or run manually after renewal
certbot renew && /opt/cert-spreader/cert-spreader.sh

Configuration

Core Configuration

Edit config.conf with your environment details:

# Basic settings
DOMAIN="yourdomain.com"
CERT_DIR="/opt/ssl-certs/yourdomain.com"
LOG_FILE="/var/log/cert-spreader/cert-spreader.log"

# SSH configuration
SSH_OPTS="-o ConnectTimeout=10 -o StrictHostKeyChecking=accept-new"

# Target hosts
HOSTS="web-01 web-02 app-01 db-01 legacy-host alpine-host"

# Default service manager for remote hosts
SERVICE_MANAGER="systemctl"              # Global default (systemctl, service, rc-service, etc.)

# Service configuration per host
# Legacy format: "hostname:port:service1,service2,service3" (uses SERVICE_MANAGER default)
# Enhanced format: "hostname:port:service_manager:service1,service2,service3"
HOST_SERVICES=(
    # Modern systemd hosts (use global SERVICE_MANAGER default)
    "web-01:22:nginx,apache2"
    "web-02:22:nginx"
    "app-01:2222:myapp,redis"
    "db-01:22:mysql"
    
    # Mixed environments with explicit service managers
    "legacy-host:22:service:nginx,apache2"        # SysV init (older RHEL/CentOS)
    "alpine-host:22:rc-service:nginx,php-fpm82"   # OpenRC (Alpine Linux)
)

Advanced Configuration

Multi-Format Certificate Generation

CUSTOM_CERTIFICATES=(
    # Windows/IIS certificates
    "pkcs12:SecurePassword123:windows-iis.pfx"
    
    # Web server certificates with DH parameters
    "concatenated:/etc/ssl/dhparam.pem:nginx-combined.pem"
    
    # Java application certificates
    "jks:KeystorePassword:tomcat-app.jks"
    
    # Mobile/embedded certificates
    "der::mobile-app.der"
)

Security Configuration

# File permissions and ownership
FILE_PERMISSIONS=644              # Certificate files
PRIVKEY_PERMISSIONS=600           # Private keys (more restrictive)
DIRECTORY_PERMISSIONS=755         # Directories
FILE_OWNER=root                   # File owner
FILE_GROUP=ssl-cert              # File group

Local Service Configuration

# Configure local service management (replaces hardcoded nginx)
LOCAL_SERVICE="nginx"             # Service to reload/restart (empty = skip)
LOCAL_SERVICE_MANAGER="systemctl" # Service manager (systemctl, service, rc-service, etc.)

# Examples for different service managers:
# LOCAL_SERVICE="apache2" LOCAL_SERVICE_MANAGER="systemctl"    # Ubuntu/Debian systemd
# LOCAL_SERVICE="httpd" LOCAL_SERVICE_MANAGER="service"       # RHEL/CentOS SysV init  
# LOCAL_SERVICE="nginx" LOCAL_SERVICE_MANAGER="rc-service"    # Alpine/OpenRC
# LOCAL_SERVICE=""                                            # Disable local service management

Remote Service Configuration

# Global default service manager for remote hosts
SERVICE_MANAGER="systemctl"       # Default for all remote hosts

# Enhanced HOST_SERVICES format supporting mixed environments:
HOST_SERVICES=(
    # Legacy format (uses SERVICE_MANAGER default)
    "web-server:22:nginx,apache2"
    "database:22:mysql,redis"
    
    # Enhanced format with explicit service managers
    "legacy-rhel6:22:service:httpd,postfix"         # SysV init
    "alpine-server:22:rc-service:nginx,php-fpm82"   # OpenRC
    "freebsd-host:22:service:nginx,mysql-server"    # BSD service
    "custom-host:22:/usr/local/bin/svc:myapp"       # Custom service manager
)

# Service manager compatibility matrix:
# systemctl    - systemd (Ubuntu 16+, RHEL 7+, SUSE 12+)
# service      - SysV init (older RHEL/CentOS, Debian, FreeBSD)
# rc-service   - OpenRC (Alpine, Gentoo)
# custom path  - Custom service management scripts

Proxmox Integration

PROXMOX_USER="automation@pve!cert-deployer"
PROXMOX_TOKEN="your-api-token-here"
PROXMOX_NODES=("proxmox-01" "proxmox-02")

Configuration Validation

# Validate configuration before deployment
./cert-spreader.sh --dry-run
./cert-spreader.py --dry-run

# Test SSH connectivity
ssh -i ~/.ssh/cert_spreader_key user@target-host 'echo "Connection OK"'

Usage

Command-Line Interface

Both implementations provide identical command-line interfaces:

# Full deployment (certificates + services + Proxmox)
./cert-spreader.sh
./cert-spreader.py

# Deployment modes
./cert-spreader.sh --cert-only        # Deploy certificates only
./cert-spreader.sh --services-only    # Restart services only  
./cert-spreader.sh --proxmox-only     # Update Proxmox only
./cert-spreader.sh --permissions-fix  # Fix permissions only

# Validation and debugging
./cert-spreader.sh --dry-run          # Preview actions without changes
./cert-spreader.sh --help             # Display usage information

# Custom configuration
./cert-spreader.sh /path/to/custom.conf --dry-run

Operational Workflows

Standard Deployment Workflow

  1. Validate: ./cert-spreader.sh --dry-run
  2. Deploy: ./cert-spreader.sh
  3. Monitor: Check logs at /var/log/cert-spreader/cert-spreader.log
  4. Verify: Test services and certificate validity

Maintenance Workflows

# Fix certificate permissions across all hosts
./cert-spreader.sh --permissions-fix

# Restart services after manual certificate updates
./cert-spreader.sh --services-only

# Update only Proxmox certificates
./cert-spreader.sh --proxmox-only

Automation & Scheduling

Cron Integration

# Add to crontab for automated renewals
0 3 * * 1 /opt/cert-spreader/cert-spreader.sh >> /var/log/cert-spreader/cron.log 2>&1

Systemd Timer (Recommended)

# Create systemd service and timer files
sudo systemctl enable cert-spreader.timer
sudo systemctl start cert-spreader.timer

Security

Authentication & Authorization

SSH Key Management

# Generate dedicated SSH keys
ssh-keygen -t ed25519 -f ~/.ssh/cert_spreader_key

# Secure key permissions
chmod 600 ~/.ssh/cert_spreader_key
chown root:root ~/.ssh/cert_spreader_key

# Deploy keys to target hosts
for host in web-01 web-02 app-01; do
    ssh-copy-id -i ~/.ssh/cert_spreader_key user@${host}.yourdomain.com
done

Configuration Security

# Secure configuration files
chmod 600 config.conf
chown root:root config.conf

# Use environment variables for sensitive data
export PROXMOX_TOKEN="your-token-here"
./cert-spreader.sh

Certificate Security

Default Security Model

  • Certificate directories: 755 (drwxr-xr-x)
  • Private keys: 600 (-rw-------)
  • Certificate files: 644 (-rw-r--r--)
  • Custom ownership and group assignment supported

Security Best Practices

  • Never commit config.conf to version control
  • Use dedicated service accounts for deployment
  • Implement proper SSH key rotation
  • Monitor certificate deployment logs
  • Validate certificate chains and expiration dates

Certificate Formats

Supported Formats & Use Cases

Format Extension Primary Use Cases Platform Support
PKCS#12 .pfx, .p12 Windows IIS, Exchange, client certs Windows, Cross-platform
Concatenated .pem Nginx, Apache, HAProxy, ZNC Linux, Unix
DER .der, .crt Java applications, Android, embedded Java, Mobile, IoT
PKCS#7 .p7b, .p7c Windows cert stores, Java trust chains Windows, Java
JKS .jks Java applications, Tomcat, Kafka Java ecosystem
PEM .pem Custom applications, OpenSSL Linux, Unix
CRT .crt Individual certificates, web servers Cross-platform

Configuration Examples

Web Infrastructure

CUSTOM_CERTIFICATES=(
    # Load balancer with DH parameters
    "concatenated:/etc/ssl/dhparam.pem:haproxy-frontend.pem"
    
    # Application servers
    "pkcs12:AppServerPassword:app-server.pfx"
    
    # Java middleware
    "jks:MiddlewareKeystore:tomcat-cluster.jks"
)

Multi-Platform Environment

CUSTOM_CERTIFICATES=(
    # Windows infrastructure
    "pkcs12:WindowsPassword:exchange-server.pfx"
    "pkcs12:IISPassword:web-server.pfx"
    
    # Linux web services
    "concatenated:/etc/nginx/ssl/dhparam.pem:nginx-production.pem"
    "concatenated::apache-staging.pem"
    
    # Mobile applications
    "der::android-app.der"
    "der::ios-app.crt"
    
    # Java applications
    "jks:ProductionKeystore:spring-boot-app.jks"
)

Monitoring & Troubleshooting

Logging & Monitoring

Log Locations

  • Main log: /var/log/cert-spreader/cert-spreader.log
  • Cron log: /var/log/cert-spreader/cron.log
  • System log: journalctl -u cert-spreader

Log Analysis

# Monitor real-time deployment
tail -f /var/log/cert-spreader/cert-spreader.log

# Check recent deployments
grep "Certificate deployment" /var/log/cert-spreader/cert-spreader.log | tail -10

# Analyze errors
grep -i error /var/log/cert-spreader/cert-spreader.log

Common Issues & Solutions

Connection Issues

# Test SSH connectivity
ssh -i ~/.ssh/cert_spreader_key user@target-host 'echo "Connection test"'

# Verify SSH agent
ssh-add -l

# Check DNS resolution
nslookup target-host.yourdomain.com

Certificate Issues

# Verify certificate validity and chain
openssl x509 -in /opt/ssl-certs/domain/cert.pem -text -noout | grep -A2 Validity
openssl verify -CApath /etc/ssl/certs /opt/ssl-certs/domain/fullchain.pem

# Check certificate hash for change detection
sha256sum /opt/ssl-certs/domain/fullchain.pem | head -c 64

Service Issues

# Test service reload manually
ssh target-host 'systemctl reload nginx || systemctl restart nginx'

# Check service status
ssh target-host 'systemctl status nginx'

# Verify certificate loading
ssh target-host 'openssl s_client -connect localhost:443 -servername yourdomain.com'

Permission Issues

# Fix permissions manually
./cert-spreader.sh --permissions-fix --dry-run
./cert-spreader.sh --permissions-fix

# Verify ownership and permissions
ls -la /opt/ssl-certs/domain/

Health Checks

Pre-deployment Validation

# Comprehensive pre-flight check
./cert-spreader.sh --dry-run 2>&1 | tee pre-deployment-check.log

# Validate configuration syntax
bash -n cert-spreader.sh
python3 -m py_compile cert-spreader.py

Post-deployment Verification

# Verify certificate deployment
for host in $(echo $HOSTS); do
    ssh ${host}.${DOMAIN} "ls -la /opt/ssl-certs/${DOMAIN}/"
done

# Test HTTPS connectivity
for host in $(echo $HOSTS); do
    curl -I https://${host}.${DOMAIN}
done

Testing

Comprehensive test suites are provided for both implementations. See TESTING.md for detailed information.

Quick Test Commands

# Run all tests
./test-cert-spreader.sh
./test-cert-spreader.py

# Run with verbose output
./test-cert-spreader.py -v

# Test specific functionality
python3 -m unittest test-cert-spreader.TestCustomCertificates -v

Implementation Comparison

Choosing Between Bash and Python

Criteria Bash Implementation Python Implementation
Dependencies Standard Unix tools only Python 3.9+ + requests
Performance Excellent (native shell) Very good
Error Handling Good with proper exit codes Excellent with exceptions
Maintainability Good for shell expertise Excellent for development teams
Debugging Shell debugging tools Rich debugging and logging
Portability Unix/Linux only Cross-platform
Extensibility Moderate High

Recommendation

  • Bash: Choose for minimal dependencies, maximum performance, pure Unix environments
  • Python: Choose for better error handling, easier maintenance, team development

Contributing

Development Guidelines

  1. Maintain dual compatibility: Changes must work in both Bash and Python implementations
  2. Security first: Follow security best practices, never expose secrets
  3. Test thoroughly: All changes must include tests and pass existing test suites
  4. Document changes: Update README.md, TESTING.md, and inline documentation

Testing Requirements

# Before submitting changes
./test-cert-spreader.sh
./test-cert-spreader.py

# Validate with real configuration
./cert-spreader.sh --dry-run
./cert-spreader.py --dry-run

Code Standards

  • Bash: Follow shell scripting best practices, use set -euo pipefail
  • Python: Follow PEP 8, use type hints, maintain Python 3.9+ compatibility
  • Documentation: Clear comments, comprehensive docstrings, updated examples

License & Attribution

Licensed under the Apache License, Version 2.0.
See LICENSE for full terms.

Attribution Requirement: If you publicly use or modify this project, credit the original author in your documentation.


Support & Resources

  • Issues: Report bugs and feature requests via GitHub Issues
  • Documentation: See TESTING.md for testing details
  • Security: Never commit real credentials; use .gitignore and example files
  • Best Practices: Always run --dry-run before production deployments

Practical SSL certificate management for distributed infrastructure.

About

No description, website, or topics provided.

Resources

License

Contributing

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published