#!/bin/bash # Calejo Control Adapter Security Audit Script # This script performs basic security checks on the deployment set -e # Colors for output RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' NC='\033[0m' # No Color # Logging functions log() { echo -e "${GREEN}[$(date +'%Y-%m-%d %H:%M:%S')]${NC} $1" } warn() { echo -e "${YELLOW}[$(date +'%Y-%m-%d %H:%M:%S')] WARNING:${NC} $1" } error() { echo -e "${RED}[$(date +'%Y-%m-%d %H:%M:%S')] ERROR:${NC} $1" } info() { echo -e "${BLUE}[$(date +'%Y-%m-%d %H:%M:%S')] INFO:${NC} $1" } # Function to check if command exists command_exists() { command -v "$1" >/dev/null 2>&1 } # Function to check Docker security check_docker_security() { log "Checking Docker security..." if command_exists docker; then # Check if containers are running as root local containers=$(docker ps --format "table {{.Names}}\t{{.Image}}\t{{.RunningFor}}") if echo "$containers" | grep -q "root"; then warn "Some containers may be running as root" else log "✓ Containers not running as root" fi # Check for exposed ports local exposed_ports=$(docker ps --format "table {{.Names}}\t{{.Ports}}") if echo "$exposed_ports" | grep -q "0.0.0.0"; then warn "Some containers have ports exposed to all interfaces" else log "✓ Container ports properly configured" fi else info "Docker not found, skipping Docker checks" fi } # Function to check network security check_network_security() { log "Checking network security..." # Check if firewall is active if command_exists ufw; then if ufw status | grep -q "Status: active"; then log "✓ Firewall (ufw) is active" else warn "Firewall (ufw) is not active" fi elif command_exists firewall-cmd; then if firewall-cmd --state 2>/dev/null | grep -q "running"; then log "✓ Firewall (firewalld) is active" else warn "Firewall (firewalld) is not active" fi else warn "No firewall management tool detected" fi # Check for open ports if command_exists netstat; then local open_ports=$(netstat -tulpn 2>/dev/null | grep LISTEN) if echo "$open_ports" | grep -q ":8080\|:4840\|:502\|:9090"; then log "✓ Application ports are listening" fi elif command_exists ss; then local open_ports=$(ss -tulpn 2>/dev/null | grep LISTEN) if echo "$open_ports" | grep -q ":8080\|:4840\|:502\|:9090"; then log "✓ Application ports are listening" fi fi } # Function to check application security check_application_security() { log "Checking application security..." # Check if application is running if curl -f http://localhost:8080/health >/dev/null 2>&1; then log "✓ Application is running and responding" # Check health endpoint local health_status=$(curl -s http://localhost:8080/health | grep -o '"status":"[^"]*' | cut -d'"' -f4) if [ "$health_status" = "healthy" ]; then log "✓ Application health status: $health_status" else warn "Application health status: $health_status" fi # Check if metrics endpoint is accessible if curl -f http://localhost:8080/metrics >/dev/null 2>&1; then log "✓ Metrics endpoint is accessible" else warn "Metrics endpoint is not accessible" fi else error "Application is not running or not accessible" fi # Check for default credentials if [ -f ".env" ]; then if grep -q "your-secret-key-change-in-production" .env; then error "Default JWT secret key found in .env" else log "✓ JWT secret key appears to be customized" fi if grep -q "your-api-key-here" .env; then error "Default API key found in .env" else log "✓ API key appears to be customized" fi if grep -q "password" .env && grep -q "postgresql://calejo:password" .env; then warn "Default database password found in .env" else log "✓ Database password appears to be customized" fi else warn ".env file not found, cannot check credentials" fi } # Function to check file permissions check_file_permissions() { log "Checking file permissions..." # Check for world-writable files local world_writable=$(find . -type f -perm -o+w 2>/dev/null | head -10) if [ -n "$world_writable" ]; then warn "World-writable files found:" echo "$world_writable" else log "✓ No world-writable files found" fi # Check for sensitive files if [ -f ".env" ] && [ "$(stat -c %a .env 2>/dev/null)" = "644" ]; then log "✓ .env file has secure permissions" elif [ -f ".env" ]; then warn ".env file permissions: $(stat -c %a .env 2>/dev/null)" fi } # Function to check database security check_database_security() { log "Checking database security..." if command_exists docker-compose && docker-compose ps | grep -q postgres; then # Check if PostgreSQL is listening on localhost only local pg_listen=$(docker-compose exec postgres psql -U calejo -c "SHOW listen_addresses;" -t 2>/dev/null | tr -d ' ') if [ "$pg_listen" = "localhost" ]; then log "✓ PostgreSQL listening on localhost only" else warn "PostgreSQL listening on: $pg_listen" fi # Check if SSL is enabled local ssl_enabled=$(docker-compose exec postgres psql -U calejo -c "SHOW ssl;" -t 2>/dev/null | tr -d ' ') if [ "$ssl_enabled" = "on" ]; then log "✓ PostgreSQL SSL enabled" else warn "PostgreSQL SSL disabled" fi else info "PostgreSQL container not found, skipping database checks" fi } # Function to check monitoring security check_monitoring_security() { log "Checking monitoring security..." # Check if Prometheus is accessible if curl -f http://localhost:9091 >/dev/null 2>&1; then log "✓ Prometheus is accessible" else info "Prometheus is not accessible (may be expected)" fi # Check if Grafana is accessible if curl -f http://localhost:3000 >/dev/null 2>&1; then log "✓ Grafana is accessible" # Check if default credentials are changed if curl -u admin:admin http://localhost:3000/api/user/preferences >/dev/null 2>&1; then error "Grafana default credentials (admin/admin) are still in use" else log "✓ Grafana default credentials appear to be changed" fi else info "Grafana is not accessible (may be expected)" fi } # Function to generate security report generate_report() { log "Generating security audit report..." local report_file="security_audit_report_$(date +%Y%m%d_%H%M%S).txt" cat > "$report_file" << EOF Calejo Control Adapter Security Audit Report ============================================ Audit Date: $(date) System: $(uname -a) Summary: -------- $(date): Security audit completed Findings: --------- EOF # Run checks and append to report { echo "\nDocker Security:" check_docker_security 2>&1 | sed 's/\x1b\[[0-9;]*m//g' echo "\nNetwork Security:" check_network_security 2>&1 | sed 's/\x1b\[[0-9;]*m//g' echo "\nApplication Security:" check_application_security 2>&1 | sed 's/\x1b\[[0-9;]*m//g' echo "\nFile Permissions:" check_file_permissions 2>&1 | sed 's/\x1b\[[0-9;]*m//g' echo "\nDatabase Security:" check_database_security 2>&1 | sed 's/\x1b\[[0-9;]*m//g' echo "\nMonitoring Security:" check_monitoring_security 2>&1 | sed 's/\x1b\[[0-9;]*m//g' } >> "$report_file" log "Security audit report saved to: $report_file" # Show summary echo echo "=== SECURITY AUDIT SUMMARY ===" grep -E "(✓|WARNING|ERROR):" "$report_file" | tail -20 } # Main function main() { echo "Calejo Control Adapter Security Audit" echo "=====================================" echo # Run all security checks check_docker_security check_network_security check_application_security check_file_permissions check_database_security check_monitoring_security # Generate report generate_report echo log "Security audit completed" echo echo "Recommendations:" echo "1. Review and address all warnings and errors" echo "2. Change default credentials if found" echo "3. Ensure firewall is properly configured" echo "4. Regular security audits are recommended" } # Parse command line arguments case "${1:-}" in --help|-h) echo "Usage: $0 [OPTIONS]" echo "" echo "Options:" echo " --help, -h Show this help message" echo "" echo "This script performs a security audit of the Calejo Control Adapter deployment." exit 0 ;; *) main ;; esac