271 lines
8.7 KiB
Bash
Executable file
271 lines
8.7 KiB
Bash
Executable file
#!/bin/bash
|
|
|
|
# Script to verify nginx configurations for conflicts and errors
|
|
# This script checks for common nginx configuration issues
|
|
|
|
set -e
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
CONFIG_DIR="$SCRIPT_DIR/generated_configs"
|
|
|
|
echo "🔍 Verifying nginx configurations..."
|
|
echo "Config directory: $CONFIG_DIR"
|
|
echo ""
|
|
|
|
# Check if config directory exists
|
|
if [ ! -d "$CONFIG_DIR" ]; then
|
|
echo "❌ Config directory not found: $CONFIG_DIR"
|
|
echo "Run generate-nginx-configs.sh first"
|
|
exit 1
|
|
fi
|
|
|
|
# Arrays to track found issues
|
|
issues_found=0
|
|
warnings_found=0
|
|
|
|
# Function to check server block structure
|
|
check_server_structure() {
|
|
local file="$1"
|
|
local filename=$(basename "$file")
|
|
|
|
echo "📋 Checking $filename..."
|
|
|
|
# Check for server blocks
|
|
local server_blocks=$(grep -c "^server {" "$file")
|
|
if [ "$server_blocks" -lt 2 ]; then
|
|
echo "❌ Expected at least 2 server blocks (HTTP + HTTPS), found $server_blocks"
|
|
((issues_found++))
|
|
else
|
|
echo "✅ Found $server_blocks server blocks"
|
|
fi
|
|
|
|
# Check for proper closing braces
|
|
local open_braces=$(grep -c "{" "$file")
|
|
local close_braces=$(grep -c "}" "$file")
|
|
if [ "$open_braces" -ne "$close_braces" ]; then
|
|
echo "❌ Mismatched braces: $open_braces open, $close_braces close"
|
|
((issues_found++))
|
|
else
|
|
echo "✅ Braces balanced"
|
|
fi
|
|
|
|
# Check for server_name directives
|
|
if ! grep -q "server_name" "$file"; then
|
|
echo "❌ Missing server_name directive"
|
|
((issues_found++))
|
|
else
|
|
echo "✅ Has server_name directive"
|
|
fi
|
|
|
|
# Check for SSL configuration in HTTPS block
|
|
if grep -q "listen 443" "$file"; then
|
|
if ! grep -q "ssl_certificate" "$file"; then
|
|
echo "❌ HTTPS block missing SSL certificate configuration"
|
|
((issues_found++))
|
|
else
|
|
echo "✅ HTTPS block has SSL configuration"
|
|
fi
|
|
fi
|
|
|
|
# Check for location blocks
|
|
local location_blocks=$(grep -c "^ location" "$file")
|
|
if [ "$location_blocks" -eq 0 ]; then
|
|
echo "❌ No location blocks found"
|
|
((issues_found++))
|
|
else
|
|
echo "✅ Found $location_blocks location blocks"
|
|
fi
|
|
|
|
# Check for security headers
|
|
if grep -q "add_header.*X-Frame-Options" "$file"; then
|
|
echo "✅ Has security headers"
|
|
else
|
|
echo "⚠️ Missing security headers"
|
|
((warnings_found++))
|
|
fi
|
|
|
|
# Check for deny access to hidden files
|
|
if grep -F -q "location ~ /\." "$file"; then
|
|
echo "✅ Has protection for hidden files"
|
|
else
|
|
echo "⚠️ Missing protection for hidden files"
|
|
((warnings_found++))
|
|
fi
|
|
|
|
echo ""
|
|
}
|
|
|
|
# Function to check for server_name conflicts
|
|
check_server_name_conflicts() {
|
|
echo "🔍 Checking for server_name conflicts..."
|
|
|
|
# Collect all unique server_names from all config files
|
|
# Multiple server blocks in the same file with the same name are OK (HTTP/HTTPS)
|
|
local all_names=""
|
|
local conflicts=""
|
|
|
|
for config in "$CONFIG_DIR"/*.conf; do
|
|
if [ -f "$config" ]; then
|
|
local filename=$(basename "$config")
|
|
local file_unique_names=""
|
|
|
|
# First collect all unique server_names from this file
|
|
while read -r line; do
|
|
if [[ $line =~ server_name[[:space:]]+(.*)[[:space:]]*\; ]]; then
|
|
local names="${BASH_REMATCH[1]}"
|
|
# Split multiple names and add to file's unique list
|
|
for name in $names; do
|
|
# Trim whitespace and check uniqueness
|
|
name=$(echo "$name" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
|
|
if [ "$name" != "_" ] && [ "$name" != "" ]; then
|
|
# Check if name is already in the list
|
|
local already_exists=0
|
|
for existing in $file_unique_names; do
|
|
if [ "$existing" = "$name" ]; then
|
|
already_exists=1
|
|
break
|
|
fi
|
|
done
|
|
|
|
if [ $already_exists -eq 0 ]; then
|
|
file_unique_names="$file_unique_names $name"
|
|
fi
|
|
fi
|
|
done
|
|
fi
|
|
done < "$config"
|
|
|
|
# Now check each unique name from this file against all previously seen names
|
|
for name in $file_unique_names; do
|
|
if echo "$all_names" | grep -q "^$name:"; then
|
|
local existing_file=$(echo "$all_names" | grep "^$name:" | cut -d: -f2)
|
|
# Only report conflict if it's a different file
|
|
if [ "$existing_file" != "$filename" ]; then
|
|
echo "❌ server_name conflict: '$name' found in both $existing_file and $filename"
|
|
conflicts="$conflicts $name"
|
|
((issues_found++))
|
|
fi
|
|
else
|
|
all_names="$all_names$name:$filename "
|
|
fi
|
|
done
|
|
fi
|
|
done
|
|
|
|
local unique_count=$(echo "$all_names" | wc -w)
|
|
if [ $unique_count -gt 0 ]; then
|
|
echo "✅ Found $unique_count unique server_names across files"
|
|
else
|
|
echo "❌ No server_names found"
|
|
((issues_found++))
|
|
fi
|
|
|
|
echo ""
|
|
}
|
|
|
|
# Function to check for common nginx syntax issues
|
|
check_syntax_issues() {
|
|
echo "🔧 Checking for common syntax issues..."
|
|
|
|
for config in "$CONFIG_DIR"/*.conf; do
|
|
if [ -f "$config" ]; then
|
|
local filename=$(basename "$config")
|
|
|
|
# Check for directives that should not be in server blocks
|
|
if grep -q "^ limit_req_zone" "$config"; then
|
|
echo "❌ limit_req_zone found inside server block in $filename (should be in http block)"
|
|
((issues_found++))
|
|
fi
|
|
|
|
if grep -q "^ gzip " "$config"; then
|
|
echo "❌ gzip directive found inside server block in $filename (should be in http block)"
|
|
((issues_found++))
|
|
fi
|
|
|
|
# Check for unclosed strings
|
|
local unclosed_quotes=$(grep -c '"' "$config")
|
|
if [ $((unclosed_quotes % 2)) -ne 0 ]; then
|
|
echo "❌ Unclosed quotes in $filename"
|
|
((issues_found++))
|
|
fi
|
|
|
|
# Check for invalid characters in server_name
|
|
while read -r line; do
|
|
if [[ $line =~ server_name[[:space:]]+(.*)[[:space:]]*\; ]]; then
|
|
local names="${BASH_REMATCH[1]}"
|
|
if [[ $names =~ [^a-zA-Z0-9._*-] ]]; then
|
|
echo "❌ Invalid characters in server_name '$names' in $filename"
|
|
((issues_found++))
|
|
fi
|
|
fi
|
|
done < "$config"
|
|
fi
|
|
done
|
|
|
|
echo "✅ Syntax check completed"
|
|
echo ""
|
|
}
|
|
|
|
# Function to check SSL configuration
|
|
check_ssl_config() {
|
|
echo "🔐 Checking SSL configuration..."
|
|
|
|
for config in "$CONFIG_DIR"/*.conf; do
|
|
if [ -f "$config" ]; then
|
|
local filename=$(basename "$config")
|
|
|
|
if grep -q "listen 443" "$config"; then
|
|
# Check SSL protocols
|
|
if grep -q "ssl_protocols" "$config"; then
|
|
echo "✅ $filename has SSL protocols configured"
|
|
else
|
|
echo "⚠️ $filename missing SSL protocols configuration"
|
|
((warnings_found++))
|
|
fi
|
|
|
|
# Check SSL ciphers
|
|
if grep -q "ssl_ciphers" "$config"; then
|
|
echo "✅ $filename has SSL ciphers configured"
|
|
else
|
|
echo "⚠️ $filename missing SSL ciphers configuration"
|
|
((warnings_found++))
|
|
fi
|
|
fi
|
|
fi
|
|
done
|
|
|
|
echo ""
|
|
}
|
|
|
|
# Main verification process
|
|
echo "📊 Starting comprehensive verification..."
|
|
echo ""
|
|
|
|
# Check each configuration file
|
|
for config in "$CONFIG_DIR"/*.conf; do
|
|
if [ -f "$config" ]; then
|
|
check_server_structure "$config"
|
|
fi
|
|
done
|
|
|
|
# Cross-file checks
|
|
check_server_name_conflicts
|
|
check_syntax_issues
|
|
check_ssl_config
|
|
|
|
# Summary
|
|
echo "📊 Verification Summary:"
|
|
echo "Issues found: $issues_found"
|
|
echo "Warnings: $warnings_found"
|
|
echo ""
|
|
|
|
if [ $issues_found -gt 0 ]; then
|
|
echo "❌ Configuration has $issues_found issue(s) that must be fixed"
|
|
exit 1
|
|
elif [ $warnings_found -gt 0 ]; then
|
|
echo "⚠️ Configuration has $warnings_found warning(s) - review recommended"
|
|
exit 0
|
|
else
|
|
echo "✅ All configurations passed verification!"
|
|
exit 0
|
|
fi
|