Complete guide for configuring Wazuh to send alerts to the AI-powered integration service.
┌─────────────────┐
│ Wazuh Manager │
│ (Alert Gen) │
└────────┬────────┘
│ HTTP POST
↓
┌──────────────────────┐
│ Wazuh Integration │
│ Service (Port 8002) │
└──────────┬───────────┘
│
┌──────┴──────┐
↓ ↓
┌─────────┐ ┌──────────┐
│ Alert │ │ RAG │
│ Triage │ │ Service │
│ (LLM) │ │(severity │
│ │ │ >= 8) │
└─────────┘ └──────────┘
- Wazuh Manager 4.x deployed
- AI-SOC services running (
docker-compose -f docker-compose/ai-services.yml up -d) - Network connectivity between Wazuh Manager and integration service
- API credentials configured in
.env
Pros:
- Built-in reliability and retry logic
- Officially supported by Wazuh
- Automatic JSON formatting
Steps:
-
SSH into Wazuh Manager container/server:
docker exec -it wazuh-manager bash # OR ssh user@wazuh-manager-host
-
Edit
/var/ossec/etc/ossec.conf:<ossec_config> <!-- Add inside <ossec_config> block --> <integration> <name>custom-webhook</name> <hook_url>http://wazuh-integration:8002/webhook</hook_url> <level>7</level> <alert_format>json</alert_format> <options>{"data": "all"}</options> </integration> </ossec_config>
-
Verify configuration syntax:
/var/ossec/bin/verify-agent-conf
-
Restart Wazuh Manager:
systemctl restart wazuh-manager # OR (inside Docker container) /var/ossec/bin/wazuh-control restart -
Monitor integration logs:
tail -f /var/ossec/logs/ossec.log | grep integration
For advanced filtering or pre-processing.
Steps:
-
Create integration script
/var/ossec/integrations/ai-soc-webhook:#!/bin/bash # AI-SOC Webhook Integration Script # Called by Wazuh integratord for each alert WEBHOOK_URL="http://wazuh-integration:8002/webhook" ALERT_FILE="$1" # Optional: Add custom headers, authentication, or filtering RULE_LEVEL=$(jq -r '.rule.level' "$ALERT_FILE") # Only send if level >= 7 if [ "$RULE_LEVEL" -ge 7 ]; then curl -X POST "$WEBHOOK_URL" \ -H "Content-Type: application/json" \ -H "X-Wazuh-Alert: true" \ --max-time 10 \ --retry 3 \ --retry-delay 2 \ -d @"$ALERT_FILE" \ --silent \ --output /dev/null \ --write-out "%{http_code}\n" >> /var/ossec/logs/integrations.log 2>&1 fi
-
Set permissions:
chmod 750 /var/ossec/integrations/ai-soc-webhook chown root:wazuh /var/ossec/integrations/ai-soc-webhook
-
Configure in
ossec.conf:<integration> <name>ai-soc-webhook</name> <hook_url>http://wazuh-integration:8002/webhook</hook_url> <level>7</level> <alert_format>json</alert_format> </integration>
-
Test script manually:
# Generate test alert echo '{"timestamp":"2025-01-13T14:30:45Z","rule":{"level":10,"description":"Test alert","id":"99999"},"id":"test-001","agent":{"id":"000","name":"test"}}' > /tmp/test_alert.json # Run script /var/ossec/integrations/ai-soc-webhook /tmp/test_alert.json # Check response code in logs tail /var/ossec/logs/integrations.log
For centralized log shipping infrastructure.
Filebeat Configuration (filebeat.yml):
filebeat.inputs:
- type: log
enabled: true
paths:
- /var/ossec/logs/alerts/alerts.json
json.keys_under_root: true
json.add_error_key: true
processors:
# Filter by severity
- drop_event:
when:
range:
rule.level:
lt: 7
output.http:
hosts: ["http://wazuh-integration:8002/webhook"]
headers:
Content-Type: application/json
timeout: 30
max_retries: 3
backoff.init: 1s
backoff.max: 30sDeploy Filebeat:
# Download and install Filebeat
curl -L -O https://artifacts.elastic.co/downloads/beats/filebeat/filebeat-8.11.0-amd64.deb
sudo dpkg -i filebeat-8.11.0-amd64.deb
# Copy configuration
sudo cp filebeat.yml /etc/filebeat/filebeat.yml
# Start service
sudo systemctl enable filebeat
sudo systemctl start filebeat
# Verify
sudo systemctl status filebeat
sudo tail -f /var/log/filebeat/filebeatIf Wazuh Manager is in Docker Compose:
Add to Wazuh's docker-compose.yml:
services:
wazuh-manager:
# ... existing config ...
networks:
- wazuh-network
- ai-network # Add this
networks:
wazuh-network:
driver: bridge
ai-network:
external: true # Reference AI services networkIf Wazuh Manager is external:
Expose integration service:
# In docker-compose/ai-services.yml
services:
wazuh-integration:
ports:
- "8002:8002" # Expose to hostUse host IP in Wazuh config:
<hook_url>http://192.168.1.100:8002/webhook</hook_url>Allow traffic from Wazuh Manager to integration service:
# Linux iptables
sudo iptables -A INPUT -p tcp -s <wazuh-manager-ip> --dport 8002 -j ACCEPT
# UFW
sudo ufw allow from <wazuh-manager-ip> to any port 8002
# Firewalld
sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="<wazuh-manager-ip>" port protocol="tcp" port="8002" accept'
sudo firewall-cmd --reloadThe integration service filters alerts by Wazuh rule level:
| Rule Level | Severity | Processing |
|---|---|---|
| 0-6 | Low/Medium | Rejected (400 Bad Request) |
| 7-9 | High | AI Triage only |
| 10-15 | Critical | AI Triage + RAG enrichment |
Adjust thresholds in .env:
# Minimum severity to process (reject below this)
MIN_SEVERITY=7
# Trigger RAG enrichment at this level
RAG_SEVERITY_THRESHOLD=8Or in Wazuh configuration (pre-filter):
<integration>
<name>custom-webhook</name>
<hook_url>http://wazuh-integration:8002/webhook</hook_url>
<level>10</level> <!-- Only send critical alerts -->
<alert_format>json</alert_format>
</integration>Filter by specific rule groups:
<integration>
<name>custom-webhook</name>
<hook_url>http://wazuh-integration:8002/webhook</hook_url>
<level>7</level>
<group>authentication_failed,attack,exploit</group>
<alert_format>json</alert_format>
</integration>Common useful groups:
authentication_failed- Failed login attemptsattack- Active attacksexploit- Exploit attemptsmalware- Malware detectionintrusion_attempt- Intrusion attemptsweb_attack- Web application attacksprivilege_escalation- Privilege escalation
curl http://localhost:8002/healthExpected response:
{
"status": "healthy",
"service": "wazuh-integration",
"dependencies": {
"wazuh_manager": true,
"alert_triage": true,
"rag_service": true
}
}curl -X POST http://localhost:8002/webhook \
-H "Content-Type: application/json" \
-d '{
"timestamp": "2025-01-13T14:30:45.123+0000",
"rule": {
"level": 10,
"description": "Multiple failed SSH login attempts",
"id": "5710",
"mitre": {
"id": ["T1110"],
"tactic": ["Credential Access"],
"technique": ["Brute Force"]
}
},
"agent": {
"id": "001",
"name": "web-server-01",
"ip": "10.0.1.50"
},
"id": "test-alert-12345",
"data": {
"srcip": "203.0.113.42",
"srcuser": "admin"
},
"full_log": "Failed password for admin from 203.0.113.42"
}'Verify enriched response includes:
ai_severity,ai_category,ai_summaryai_recommendations[]rag_enrichment_applied: true(for level 10)
Trigger a test alert in Wazuh:
# SSH brute force simulation (from external host)
for i in {1..6}; do
ssh invalid_user@wazuh-agent-host
done
# Or use Wazuh's built-in alert tester
/var/ossec/bin/wazuh-logtest
# Paste a sample log, check rule matchIntegration service:
docker logs -f wazuh-integrationWazuh Manager:
tail -f /var/ossec/logs/ossec.log | grep integration
tail -f /var/ossec/logs/alerts/alerts.jsonSymptoms:
ERROR: Failed to send alert to webhook: Connection refused
Solutions:
-
Verify service is running:
docker ps | grep wazuh-integration curl http://localhost:8002/health -
Check Docker networks:
docker network inspect ai-network # Verify wazuh-integration is listed -
Test connectivity from Wazuh Manager:
docker exec -it wazuh-manager curl http://wazuh-integration:8002/health
Symptoms:
{
"detail": "Alert severity 5 below minimum threshold 7"
}Solution:
Either:
- Lower
MIN_SEVERITYin.envto accept lower-severity alerts - Adjust Wazuh integration level:
<level>7</level>
Symptoms:
{
"rag_enrichment_applied": false
}Checklist:
-
Verify alert severity >= threshold:
# Check RAG_SEVERITY_THRESHOLD in .env (default: 8) # Ensure alert rule.level >= 8
-
Check RAG service health:
curl http://localhost:8300/health docker logs rag-service
-
RAG failures are non-fatal - triage will still complete
Symptoms: No alerts in integration logs, no webhook calls.
Debug steps:
-
Verify integration is configured:
docker exec -it wazuh-manager cat /var/ossec/etc/ossec.conf | grep -A 10 integration
-
Check Wazuh logs for integration errors:
docker exec -it wazuh-manager tail -f /var/ossec/logs/ossec.log -
Verify alerts are being generated:
docker exec -it wazuh-manager tail -f /var/ossec/logs/alerts/alerts.json -
Test integration manually:
docker exec -it wazuh-manager /var/ossec/bin/wazuh-integratord -t
Adjust worker processes in main.py:
if __name__ == "__main__":
import uvicorn
uvicorn.run(
"main:app",
host="0.0.0.0",
port=8002,
workers=4, # Increase for high load
log_level="info"
)Or via Docker Compose:
services:
wazuh-integration:
command: uvicorn main:app --host 0.0.0.0 --port 8002 --workers 4Prevent overwhelming the service:
<integration>
<name>custom-webhook</name>
<hook_url>http://wazuh-integration:8002/webhook</hook_url>
<level>7</level>
<max_log>100</max_log> <!-- Max alerts per timeframe -->
<alert_format>json</alert_format>
</integration>- Use internal Docker network (no external exposure)
- Enable HTTPS for production (add TLS termination proxy)
- Implement authentication (add API key validation)
- Audit logs regularly
- Rotate API credentials quarterly
Forward enriched alerts to TheHive:
# Add to main.py after enrichment
async def forward_to_thehive(enriched_alert):
thehive_url = "http://thehive:9000/api/alert"
headers = {"Authorization": f"Bearer {THEHIVE_API_KEY}"}
payload = {
"title": enriched_alert.ai_summary,
"severity": map_severity(enriched_alert.ai_severity),
"source": "Wazuh-AI",
"tags": [enriched_alert.ai_category],
"description": enriched_alert.ai_detailed_analysis
}
async with httpx.AsyncClient() as client:
await client.post(thehive_url, json=payload, headers=headers)- Configure Wazuh using Method 1 (native integration)
- Test with sample alerts
- Monitor logs for 24 hours
- Tune severity thresholds based on alert volume
- Integrate with incident response workflow (SOAR/TheHive)
For issues, check:
- Service logs:
docker logs wazuh-integration - Wazuh logs:
/var/ossec/logs/ossec.log - Health endpoint:
http://localhost:8002/health