Set up ModSecurity 3 with structured logging, webhook notifications, and API integrations to automatically feed security events into SOAR platforms for real-time threat detection and incident response workflows.
Prerequisites
- Root or sudo access
- Web server (Nginx recommended)
- Python 3.6 or later
- SOAR platform with webhook support
- Basic understanding of web application security
What this solves
ModSecurity 3 web application firewall generates security events that need structured processing for automated incident response. This tutorial configures ModSecurity with JSON logging, webhook notifications, and API integrations to feed security data into SOAR (Security Orchestration, Automation, and Response) platforms like Splunk Phantom, IBM Resilient, or Demisto for automated threat detection and response workflows.
Step-by-step installation and configuration
Update system packages and install dependencies
Start by updating your system and installing required packages for ModSecurity 3 compilation and web server integration.
sudo apt update && sudo apt upgrade -y
sudo apt install -y build-essential libcurl4-openssl-dev liblua5.3-dev libfuzzy-dev ssdeep gettext pkg-config libpcre3-dev libxml2-dev libcurl4-openssl-dev libyajl-dev doxygen nginx apache2-dev git autoconf automake libtool libgeoip-dev
sudo dnf update -y
sudo dnf groupinstall -y "Development Tools"
sudo dnf install -y libcurl-devel lua-devel libfuzzy-devel ssdeep gettext-devel pkgconfig pcre-devel libxml2-devel yajl-devel doxygen nginx httpd-devel git autoconf automake libtool GeoIP-devel
Download and compile ModSecurity 3
Clone the ModSecurity 3 source code and compile it with all necessary modules for web application firewall functionality.
cd /opt
sudo git clone --depth 1 -b v3/master --single-branch https://github.com/SpiderLabs/ModSecurity.git
sudo chown -R $USER:$USER /opt/ModSecurity
cd ModSecurity
git submodule init
git submodule update
./build.sh
./configure
make
sudo make install
Install ModSecurity-nginx connector
Download and compile the ModSecurity-nginx connector to integrate ModSecurity 3 with Nginx web server.
cd /opt
sudo git clone --depth 1 https://github.com/SpiderLabs/ModSecurity-nginx.git
sudo chown -R $USER:$USER /opt/ModSecurity-nginx
# Get nginx version for dynamic module compilation
nginx -v 2>&1 | grep -o '[0-9]\+\.[0-9]\+\.[0-9]\+'
# Download nginx source matching your version (replace 1.24.0 with your version)
wget http://nginx.org/download/nginx-1.24.0.tar.gz
tar zxvf nginx-1.24.0.tar.gz
cd nginx-1.24.0
# Configure and build the dynamic module
./configure --with-compat --add-dynamic-module=../ModSecurity-nginx
make modules
sudo cp objs/ngx_http_modsecurity_module.so /etc/nginx/modules/
Download OWASP Core Rule Set
Install the OWASP Core Rule Set (CRS) which provides comprehensive protection rules for common web application attacks.
cd /opt
sudo wget https://github.com/coreruleset/coreruleset/archive/v4.0.0.tar.gz
sudo tar -xzf v4.0.0.tar.gz
sudo mv coreruleset-4.0.0 /opt/coreruleset
sudo cp /opt/coreruleset/crs-setup.conf.example /opt/coreruleset/crs-setup.conf
Create ModSecurity main configuration
Configure ModSecurity 3 with JSON logging format for SOAR platform consumption and structured event data.
SecRuleEngine On
SecRequestBodyAccess On
SecRequestBodyLimit 13107200
SecRequestBodyNoFilesLimit 131072
SecRequestBodyInMemoryLimit 131072
SecRequestBodyLimitAction Reject
SecRule REQUEST_HEADERS:Content-Type "text/xml" "id:'200000',phase:1,t:none,t:lowercase,pass,nolog,ctl:requestBodyProcessor=XML"
SecRule REQUEST_HEADERS:Content-Type "application/xml" "id:'200001',phase:1,t:none,t:lowercase,pass,nolog,ctl:requestBodyProcessor=XML"
SecRule REQUEST_HEADERS:Content-Type "text/xml" "id:'200002',phase:1,t:none,t:lowercase,pass,nolog,ctl:requestBodyProcessor=XML"
SecResponseBodyAccess On
SecResponseBodyMimeType text/plain text/html text/xml
SecResponseBodyLimit 524288
SecResponseBodyLimitAction ProcessPartial
SecTmpDir /tmp/
SecDataDir /tmp/
# JSON Logging Configuration for SOAR Integration
SecAuditEngine On
SecAuditLogRelevantStatus "^(?:5|4(?!04))"
SecAuditLogParts ABIJDEFHZ
SecAuditLogType Serial
SecAuditLog /var/log/modsecurity/audit.log
SecAuditLogFormat JSON
# Enhanced JSON logging with additional fields for SOAR
SecAuditLogStorageDir /var/log/modsecurity/
SecRule RESPONSE_STATUS "@streq 200" "id:999001,phase:5,pass,nolog,setvar:'tx.allowed_request=1'"
SecRule TX:ALLOWED_REQUEST "@eq 1" "id:999002,phase:5,pass,log,msg:'Legitimate request logged for baseline',logdata:'client_ip=%{REMOTE_ADDR} user_agent=%{REQUEST_HEADERS.User-Agent} method=%{REQUEST_METHOD} uri=%{REQUEST_URI}'"
# Custom action for webhook notifications
SecAction "id:999003,phase:1,pass,nolog,setvar:'tx.webhook_url=http://your-soar-platform.example.com/api/webhook/modsecurity'"
SecDebugLog /var/log/modsecurity/debug.log
SecDebugLogLevel 3
SecArgumentSeparator &
SecCookieFormat 0
SecTmpSaveUploadedFiles on
SecUploadDir /opt/modsecurity/var/upload
Create structured JSON logging script
Create a Python script to parse ModSecurity logs and format them for SOAR platform consumption with enriched metadata.
#!/usr/bin/env python3
import json
import re
import requests
import time
from datetime import datetime
import hashlib
import os
import sys
class ModSecuritySOARIntegration:
def __init__(self, webhook_url, api_key=None):
self.webhook_url = webhook_url
self.api_key = api_key
self.headers = {
'Content-Type': 'application/json',
'User-Agent': 'ModSecurity-SOAR-Integration/1.0'
}
if api_key:
self.headers['Authorization'] = f'Bearer {api_key}'
def parse_audit_log(self, log_line):
"""Parse ModSecurity audit log line and extract security event data"""
try:
log_data = json.loads(log_line)
# Extract key security indicators
event = {
'timestamp': datetime.utcnow().isoformat() + 'Z',
'source_ip': log_data.get('request', {}).get('remote_addr', ''),
'request_method': log_data.get('request', {}).get('method', ''),
'request_uri': log_data.get('request', {}).get('uri', ''),
'user_agent': log_data.get('request', {}).get('headers', {}).get('User-Agent', ''),
'host': log_data.get('request', {}).get('headers', {}).get('Host', ''),
'response_status': log_data.get('response', {}).get('http_code', 0),
'rules_matched': [],
'threat_score': 0,
'severity': 'info'
}
# Process matched rules
messages = log_data.get('audit_data', {}).get('messages', [])
for msg in messages:
rule_info = {
'rule_id': msg.get('details', {}).get('ruleId', ''),
'message': msg.get('details', {}).get('msg', ''),
'data': msg.get('details', {}).get('data', ''),
'file': msg.get('details', {}).get('file', ''),
'line': msg.get('details', {}).get('lineNumber', ''),
'severity': msg.get('details', {}).get('severity', '')
}
event['rules_matched'].append(rule_info)
# Calculate threat score based on rule severity
severity_scores = {'EMERGENCY': 5, 'ALERT': 4, 'CRITICAL': 4, 'ERROR': 3, 'WARNING': 2, 'NOTICE': 1}
event['threat_score'] += severity_scores.get(rule_info['severity'].upper(), 1)
# Set overall severity based on threat score
if event['threat_score'] >= 10:
event['severity'] = 'critical'
elif event['threat_score'] >= 5:
event['severity'] = 'high'
elif event['threat_score'] >= 3:
event['severity'] = 'medium'
else:
event['severity'] = 'low'
# Generate unique event ID
event_string = f"{event['timestamp']}{event['source_ip']}{event['request_uri']}"
event['event_id'] = hashlib.sha256(event_string.encode()).hexdigest()[:16]
return event
except (json.JSONDecodeError, KeyError) as e:
print(f"Error parsing log line: {e}")
return None
def send_to_soar(self, event_data):
"""Send security event to SOAR platform via webhook"""
try:
# Prepare SOAR-compatible payload
soar_payload = {
'alert_type': 'modsecurity_waf',
'severity': event_data['severity'],
'timestamp': event_data['timestamp'],
'source': 'ModSecurity WAF',
'event_id': event_data['event_id'],
'indicators': {
'ip_address': event_data['source_ip'],
'user_agent': event_data['user_agent'],
'host': event_data['host'],
'request_uri': event_data['request_uri']
},
'details': {
'method': event_data['request_method'],
'response_code': event_data['response_status'],
'threat_score': event_data['threat_score'],
'matched_rules': event_data['rules_matched']
},
'raw_data': event_data
}
response = requests.post(
self.webhook_url,
headers=self.headers,
json=soar_payload,
timeout=10
)
if response.status_code == 200:
print(f"Successfully sent event {event_data['event_id']} to SOAR platform")
return True
else:
print(f"Failed to send event to SOAR: HTTP {response.status_code}")
return False
except requests.RequestException as e:
print(f"Error sending to SOAR platform: {e}")
return False
def monitor_audit_log(log_file_path, soar_integration):
"""Monitor ModSecurity audit log and send events to SOAR"""
try:
with open(log_file_path, 'r') as f:
# Seek to end of file
f.seek(0, 2)
while True:
line = f.readline()
if line:
event = soar_integration.parse_audit_log(line.strip())
if event and event['threat_score'] > 0:
soar_integration.send_to_soar(event)
else:
time.sleep(1)
except FileNotFoundError:
print(f"Audit log file not found: {log_file_path}")
except KeyboardInterrupt:
print("Monitoring stopped")
if __name__ == "__main__":
# Configuration - modify these values for your SOAR platform
WEBHOOK_URL = os.getenv('MODSEC_SOAR_WEBHOOK', 'http://your-soar-platform.example.com/api/webhook/modsecurity')
API_KEY = os.getenv('MODSEC_SOAR_API_KEY', '')
LOG_FILE = '/var/log/modsecurity/audit.log'
soar = ModSecuritySOARIntegration(WEBHOOK_URL, API_KEY)
monitor_audit_log(LOG_FILE, soar)
Configure Nginx with ModSecurity module
Enable ModSecurity module in Nginx and configure it to use our security rules and logging settings.
# Add at the top of nginx.conf
load_module modules/ngx_http_modsecurity_module.so;
http {
# ModSecurity configuration
modsecurity on;
modsecurity_rules_file /opt/ModSecurity/modsecurity.conf;
# Enable detailed logging
log_format modsec_json escape=json '{'
'"time":"$time_iso8601",'
'"remote_addr":"$remote_addr",'
'"request":"$request",'
'"status":$status,'
'"body_bytes_sent":$body_bytes_sent,'
'"http_referer":"$http_referer",'
'"http_user_agent":"$http_user_agent",'
'"request_time":$request_time,'
'"upstream_response_time":"$upstream_response_time"'
'}';
access_log /var/log/nginx/access.log modsec_json;
error_log /var/log/nginx/error.log warn;
# Include other configurations
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
}
Create virtual host with ModSecurity protection
Configure a virtual host that demonstrates ModSecurity protection with OWASP Core Rule Set integration.
server {
listen 80;
server_name example.com www.example.com;
# Enable ModSecurity for this virtual host
modsecurity on;
modsecurity_rules_file /opt/ModSecurity/modsecurity.conf;
# Include OWASP Core Rule Set
modsecurity_rules '
Include /opt/coreruleset/crs-setup.conf
Include /opt/coreruleset/rules/*.conf
# Custom rule for SOAR integration
SecRule REQUEST_URI "@detectSQLi" \
"id:2001,phase:2,block,msg:SQL Injection Attack,logdata:Matched Data: %{MATCHED_VAR} found within %{MATCHED_VAR_NAME},tag:attack-sqli,severity:CRITICAL"
SecRule ARGS "@detectXSS" \
"id:2002,phase:2,block,msg:XSS Attack,logdata:Matched Data: %{MATCHED_VAR} found within %{MATCHED_VAR_NAME},tag:attack-xss,severity:CRITICAL"
# Custom action to trigger webhook on high severity events
SecRule TX:ANOMALY_SCORE "@gt 4" \
"id:2003,phase:5,pass,exec:/opt/modsecurity/webhook_notify.sh %{TX.ANOMALY_SCORE} %{REMOTE_ADDR} %{REQUEST_URI}"
';
location / {
root /var/www/html;
index index.html index.htm;
# Additional security headers
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header X-Content-Type-Options "nosniff" always;
}
# Specific protection for admin areas
location /admin {
modsecurity_rules '
SecRuleRemoveById 920350
SecRule REQUEST_URI "@beginsWith /admin" \
"id:3001,phase:1,pass,log,msg:Admin area access,logdata:IP: %{REMOTE_ADDR} URI: %{REQUEST_URI}"
';
root /var/www/html;
index index.html;
}
}
Create webhook notification script
Create a shell script that triggers immediate webhook notifications for high-severity security events.
#!/bin/bash
# ModSecurity Webhook Notification Script
# Arguments: $1=anomaly_score $2=remote_addr $3=request_uri
ANOMALY_SCORE=$1
REMOTE_ADDR=$2
REQUEST_URI=$3
TIMESTAMP=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
WEBHOOK_URL="${MODSEC_SOAR_WEBHOOK:-http://your-soar-platform.example.com/api/webhook/modsecurity}"
API_KEY="${MODSEC_SOAR_API_KEY:-}"
# Create JSON payload for immediate notification
PAYLOAD=$(cat <
Set up log directories and permissions
Create necessary directories and set appropriate permissions for ModSecurity logging and scripts.
sudo mkdir -p /var/log/modsecurity
sudo mkdir -p /opt/modsecurity/var/upload
sudo chown -R www-data:www-data /var/log/modsecurity
sudo chown -R www-data:www-data /opt/modsecurity/var/upload
sudo chmod 755 /opt/modsecurity/webhook_notify.sh
sudo chmod 755 /opt/modsecurity/soar_integration.py
# Create logrotate configuration
sudo tee /etc/logrotate.d/modsecurity > /dev/null <
Configure environment variables for SOAR integration
Set up environment variables for SOAR platform connection details and API credentials.
# ModSecurity SOAR Integration Configuration
MODSEC_SOAR_WEBHOOK=https://your-soar-platform.example.com/api/webhook/modsecurity
MODSEC_SOAR_API_KEY=your_api_key_here
MODSEC_THREAT_THRESHOLD=3
Create systemd service for SOAR integration
Create a systemd service to run the SOAR integration script continuously and ensure it starts on boot.
[Unit]
Description=ModSecurity SOAR Integration Service
After=network.target nginx.service
Requires=nginx.service
[Service]
Type=simple
User=www-data
Group=www-data
WorkingDirectory=/opt/modsecurity
ExecStart=/usr/bin/python3 /opt/modsecurity/soar_integration.py
Restart=always
RestartSec=5
EnvironmentFile=/etc/environment
# Logging
StandardOutput=journal
StandardError=journal
SyslogIdentifier=modsecurity-soar
# Security settings
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=strict
ProtectHome=true
ReadWritePaths=/var/log/modsecurity
[Install]
WantedBy=multi-user.target
Enable and start services
Enable the Nginx virtual host, start ModSecurity protection, and activate the SOAR integration service.
# Enable the protected site
sudo ln -s /etc/nginx/sites-available/protected-site /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx
# Enable and start the SOAR i
Automated install script
Run this to automate the entire setup
#!/usr/bin/env bash
set -euo pipefail
# ModSecurity 3 with SOAR Integration Install Script
# Production-ready installation script for multiple Linux distributions
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
# Configuration variables
NGINX_CONFIG_DIR=""
NGINX_USER=""
WEBHOOK_URL="${1:-}"
# Print colored output
print_status() {
echo -e "${GREEN}[INFO]${NC} $1"
}
print_warning() {
echo -e "${YELLOW}[WARN]${NC} $1"
}
print_error() {
echo -e "${RED}[ERROR]${NC} $1"
}
# Usage message
usage() {
echo "Usage: $0 [webhook_url]"
echo " webhook_url: Optional SOAR platform webhook URL for notifications"
exit 1
}
# Cleanup function for rollback
cleanup() {
print_error "Installation failed. Cleaning up..."
rm -rf /opt/ModSecurity /opt/ModSecurity-nginx /opt/coreruleset 2>/dev/null || true
systemctl stop nginx 2>/dev/null || true
}
# Set trap for cleanup on error
trap cleanup ERR
# Check if running as root or with sudo
if [[ $EUID -eq 0 ]] && [[ -z "${SUDO_USER:-}" ]]; then
print_warning "Running as root. Consider using sudo instead."
elif [[ $EUID -ne 0 ]] && [[ -z "${SUDO_USER:-}" ]]; then
print_error "This script requires root privileges. Please run with sudo."
exit 1
fi
# Auto-detect distribution and set package manager
echo "[1/12] Detecting distribution and setting up package manager..."
if [ -f /etc/os-release ]; then
. /etc/os-release
case "$ID" in
ubuntu|debian)
PKG_MGR="apt"
PKG_UPDATE="apt update"
PKG_INSTALL="apt install -y"
NGINX_CONFIG_DIR="/etc/nginx"
NGINX_USER="www-data"
;;
almalinux|rocky|centos|rhel|ol)
PKG_MGR="dnf"
PKG_UPDATE="dnf update -y"
PKG_INSTALL="dnf install -y"
NGINX_CONFIG_DIR="/etc/nginx"
NGINX_USER="nginx"
if ! command -v dnf &> /dev/null; then
PKG_MGR="yum"
PKG_UPDATE="yum update -y"
PKG_INSTALL="yum install -y"
fi
;;
fedora)
PKG_MGR="dnf"
PKG_UPDATE="dnf update -y"
PKG_INSTALL="dnf install -y"
NGINX_CONFIG_DIR="/etc/nginx"
NGINX_USER="nginx"
;;
amzn)
PKG_MGR="yum"
PKG_UPDATE="yum update -y"
PKG_INSTALL="yum install -y"
NGINX_CONFIG_DIR="/etc/nginx"
NGINX_USER="nginx"
;;
*)
print_error "Unsupported distribution: $ID"
exit 1
;;
esac
else
print_error "Cannot detect distribution. /etc/os-release not found."
exit 1
fi
print_status "Detected $ID, using $PKG_MGR package manager"
# Update system packages
echo "[2/12] Updating system packages..."
$PKG_UPDATE
# Install dependencies based on distribution
echo "[3/12] Installing build dependencies..."
if [[ "$PKG_MGR" == "apt" ]]; then
$PKG_INSTALL build-essential libcurl4-openssl-dev liblua5.3-dev libfuzzy-dev ssdeep gettext pkg-config libpcre3-dev libxml2-dev yajl-tools libyajl-dev doxygen nginx git autoconf automake libtool libgeoip-dev
else
$PKG_INSTALL "@Development Tools" libcurl-devel lua-devel ssdeep-devel gettext-devel pkgconfig pcre-devel libxml2-devel yajl-devel doxygen nginx git autoconf automake libtool GeoIP-devel
if [[ "$ID" == "fedora" ]] || [[ "$ID" == "almalinux" ]] || [[ "$ID" == "rocky" ]]; then
$PKG_INSTALL libfuzzy-devel
fi
fi
# Create necessary directories with proper permissions
echo "[4/12] Creating directories and setting permissions..."
mkdir -p /var/log/modsecurity /opt
chown root:root /opt
chmod 755 /opt
chown $NGINX_USER:$NGINX_USER /var/log/modsecurity
chmod 755 /var/log/modsecurity
# Download and compile ModSecurity 3
echo "[5/12] Downloading and compiling ModSecurity 3..."
cd /opt
git clone --depth 1 -b v3/master --single-branch https://github.com/SpiderLabs/ModSecurity.git
chown -R root:root ModSecurity
cd ModSecurity
git submodule init
git submodule update
./build.sh
./configure --enable-standalone-module
make -j$(nproc)
make install
ldconfig
# Get nginx version for module compilation
echo "[6/12] Preparing nginx module compilation..."
NGINX_VERSION=$(nginx -v 2>&1 | grep -o '[0-9]\+\.[0-9]\+\.[0-9]\+' | head -1)
print_status "Detected nginx version: $NGINX_VERSION"
# Download and compile ModSecurity-nginx connector
echo "[7/12] Compiling ModSecurity-nginx connector..."
cd /opt
git clone --depth 1 https://github.com/SpiderLabs/ModSecurity-nginx.git
chown -R root:root ModSecurity-nginx
# Download nginx source
wget -q "http://nginx.org/download/nginx-${NGINX_VERSION}.tar.gz"
tar -xzf "nginx-${NGINX_VERSION}.tar.gz"
cd "nginx-${NGINX_VERSION}"
# Configure and build the dynamic module
./configure --with-compat --add-dynamic-module=../ModSecurity-nginx
make modules
# Install the module with proper permissions
mkdir -p "${NGINX_CONFIG_DIR}/modules"
cp objs/ngx_http_modsecurity_module.so "${NGINX_CONFIG_DIR}/modules/"
chown root:root "${NGINX_CONFIG_DIR}/modules/ngx_http_modsecurity_module.so"
chmod 644 "${NGINX_CONFIG_DIR}/modules/ngx_http_modsecurity_module.so"
# Download OWASP Core Rule Set
echo "[8/12] Installing OWASP Core Rule Set..."
cd /opt
wget -q https://github.com/coreruleset/coreruleset/archive/v4.0.0.tar.gz
tar -xzf v4.0.0.tar.gz
mv coreruleset-4.0.0 coreruleset
chown -R root:root coreruleset
chmod -R 644 coreruleset/*
find coreruleset -type d -exec chmod 755 {} \;
cp coreruleset/crs-setup.conf.example coreruleset/crs-setup.conf
# Create ModSecurity main configuration
echo "[9/12] Creating ModSecurity configuration..."
cat > /opt/modsecurity.conf << 'EOF'
SecRuleEngine On
SecRequestBodyAccess On
SecRequestBodyLimit 13107200
SecRequestBodyNoFilesLimit 131072
SecRequestBodyInMemoryLimit 131072
SecRequestBodyLimitAction Reject
SecResponseBodyAccess On
SecResponseBodyMimeType text/plain text/html text/xml application/json
SecResponseBodyLimit 524288
SecResponseBodyLimitAction ProcessPartial
SecTmpDir /tmp/
SecDataDir /tmp/
# JSON Logging for SOAR Integration
SecAuditEngine On
SecAuditLogRelevantStatus "^(?:5|4(?!04))"
SecAuditLogParts ABIJDEFHZ
SecAuditLogType Serial
SecAuditLog /var/log/modsecurity/audit.log
SecAuditLogFormat JSON
SecAuditLogStorageDir /var/log/modsecurity/
# Enhanced security rules
SecRule REQUEST_HEADERS:Content-Type "(?:text|application)/xml" "id:'200000',phase:1,t:none,t:lowercase,pass,nolog,ctl:requestBodyProcessor=XML"
SecRule RESPONSE_STATUS "@streq 404" "id:'200001',phase:5,pass,nolog,setvar:tx.allowed_request_content_type=|application/x-www-form-urlencoded| |multipart/form-data| |text/xml| |application/xml| |application/soap+xml| |application/x-amf| |application/json| |application/octet-stream| |text/plain|"
# Include OWASP CRS
Include /opt/coreruleset/crs-setup.conf
Include /opt/coreruleset/rules/*.conf
EOF
chown root:root /opt/modsecurity.conf
chmod 644 /opt/modsecurity.conf
# Configure nginx with ModSecurity
echo "[10/12] Configuring nginx with ModSecurity..."
# Load the module
sed -i '1i load_module modules/ngx_http_modsecurity_module.so;' "${NGINX_CONFIG_DIR}/nginx.conf"
# Create ModSecurity nginx configuration
mkdir -p "${NGINX_CONFIG_DIR}/conf.d"
cat > "${NGINX_CONFIG_DIR}/conf.d/modsecurity.conf" << 'EOF'
modsecurity on;
modsecurity_rules_file /opt/modsecurity.conf;
# Log format for SOAR integration
log_format modsec_json escape=json
'{'
'"timestamp":"$time_iso8601",'
'"remote_addr":"$remote_addr",'
'"request_method":"$request_method",'
'"request_uri":"$request_uri",'
'"status":"$status",'
'"body_bytes_sent":"$body_bytes_sent",'
'"http_referer":"$http_referer",'
'"http_user_agent":"$http_user_agent",'
'"request_time":"$request_time"'
'}';
access_log /var/log/nginx/modsec_access.log modsec_json;
EOF
chown root:root "${NGINX_CONFIG_DIR}/conf.d/modsecurity.conf"
chmod 644 "${NGINX_CONFIG_DIR}/conf.d/modsecurity.conf"
# Create webhook notification script if URL provided
echo "[11/12] Setting up SOAR integration..."
if [[ -n "$WEBHOOK_URL" ]]; then
cat > /usr/local/bin/modsec_webhook.sh << EOF
#!/bin/bash
WEBHOOK_URL="$WEBHOOK_URL"
tail -F /var/log/modsecurity/audit.log | while read line; do
if echo "\$line" | grep -q '"messages":\['; then
curl -X POST -H "Content-Type: application/json" -d "\$line" "\$WEBHOOK_URL" &
fi
done
EOF
chmod 755 /usr/local/bin/modsec_webhook.sh
chown root:root /usr/local/bin/modsec_webhook.sh
# Create systemd service for webhook
cat > /etc/systemd/system/modsec-webhook.service << EOF
[Unit]
Description=ModSecurity SOAR Webhook Service
After=network.target
[Service]
Type=simple
User=root
ExecStart=/usr/local/bin/modsec_webhook.sh
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable modsec-webhook.service
print_status "SOAR webhook integration configured"
fi
# Start and enable services
echo "[12/12] Starting services and performing verification..."
systemctl enable nginx
systemctl restart nginx
if [[ -n "$WEBHOOK_URL" ]]; then
systemctl start modsec-webhook.service
fi
# Verification checks
print_status "Performing verification checks..."
# Check if nginx is running
if systemctl is-active --quiet nginx; then
print_status "✓ Nginx is running"
else
print_error "✗ Nginx is not running"
exit 1
fi
# Check if ModSecurity module is loaded
if nginx -t 2>&1 | grep -q "successful"; then
print_status "✓ Nginx configuration is valid"
else
print_error "✗ Nginx configuration has errors"
exit 1
fi
# Check log files
if [[ -f /var/log/modsecurity/audit.log ]]; then
print_status "✓ ModSecurity audit log is created"
else
print_warning "ModSecurity audit log not yet created (will be created on first request)"
fi
# Clean up build artifacts
rm -rf /opt/nginx-* /opt/v4.0.0.tar.gz
print_status "ModSecurity 3 with SOAR integration installed successfully!"
print_status "Configuration files:"
print_status " - ModSecurity config: /opt/modsecurity.conf"
print_status " - Nginx config: ${NGINX_CONFIG_DIR}/conf.d/modsecurity.conf"
print_status " - Audit logs: /var/log/modsecurity/audit.log"
if [[ -n "$WEBHOOK_URL" ]]; then
print_status " - SOAR webhook service: modsec-webhook.service"
fi
print_warning "Remember to configure your server blocks to include ModSecurity directives"
print_warning "Test the installation by triggering a security rule and checking the logs"
Review the script before running. Execute with: bash install.sh