# Wazuh SIEM Integrations - Connectors and Forwarding

> Wazuh 4.14 built-in integrations - Slack, PagerDuty, VirusTotal, Shuffle, TheHive, syslog forwarding, custom webhooks, and Splunk/ELK connectivity

Source: https://opennix.org/en/docs/wazuh/integrations/wazuh-siem-integrations/


Wazuh 4.14 ships with the `wazuh-integratord` daemon that handles alert forwarding to external security and monitoring platforms. Built-in integrations are configured through the `<integration>` block in the `ossec.conf` file on the Wazuh Manager server. In addition to native connectors, the platform supports syslog forwarding and custom webhook integrations.

## The wazuh-integratord Daemon

The `wazuh-integratord` daemon starts automatically with Wazuh Manager and processes alerts in real time. For each configured integration, the daemon evaluates filter conditions and, when matched, constructs a JSON payload for delivery to the external system.

### Integration Block Structure

All built-in integrations are configured in `/var/ossec/etc/ossec.conf` within the `<ossec_config>` block:

```xml
<integration>
  <name>integration-name</name>
  <hook_url>https://endpoint.example.com/webhook</hook_url>
  <api_key>YOUR_API_KEY</api_key>
  <level>7</level>
  <rule_id>100001,100002</rule_id>
  <group>authentication_failed,</group>
  <alert_format>json</alert_format>
</integration>
```

Filter parameters:

| Parameter | Description | Example |
|---|---|---|
| `<level>` | Minimum alert level for forwarding | `7` - forward alerts level 7 and above |
| `<rule_id>` | Comma-separated list of rule IDs | `100001,100002` |
| `<group>` | Rule group (with trailing comma) | `authentication_failed,` |
| `<event_location>` | Filter by event source | `/var/log/auth.log` |

When multiple filter parameters are specified, they are combined with logical AND - the alert must match all conditions simultaneously.

## Slack Integration

The Slack integration sends alert notifications to a designated channel via Incoming Webhook.

### Configuring the Slack Webhook

1. Navigate to Slack app settings: **Apps** - **Manage** - **Custom Integrations** - **Incoming WebHooks**
2. Create a new webhook and copy the URL (format: `https://hooks.slack.com/services/T00/B00/XXXX`)
3. Add the configuration to `ossec.conf`:

```xml
<integration>
  <name>slack</name>
  <hook_url>https://hooks.slack.com/services/T00/B00/XXXX</hook_url>
  <level>10</level>
  <alert_format>json</alert_format>
</integration>
```

### Filtering Alerts for Slack

In high-volume environments, limit notifications to critical alerts only:

```xml
<integration>
  <name>slack</name>
  <hook_url>https://hooks.slack.com/services/T00/B00/XXXX</hook_url>
  <level>12</level>
  <group>attack,exploit,</group>
  <alert_format>json</alert_format>
</integration>
```

This configuration forwards only alerts at level 12 or above that belong to the `attack` or `exploit` groups.

### Notification Format

Wazuh constructs a Slack message containing the alert level, rule description, agent ID, timestamp, and event source. Messages are color-coded based on severity level.

## PagerDuty Integration

PagerDuty handles critical incident escalation with automatic on-call team notification.

### Configuring PagerDuty

1. Create a service in PagerDuty with the **Events API v2** integration type
2. Copy the Integration Key (Routing Key)
3. Add the configuration:

```xml
<integration>
  <name>pagerduty</name>
  <api_key>YOUR_PAGERDUTY_INTEGRATION_KEY</api_key>
  <level>12</level>
  <alert_format>json</alert_format>
</integration>
```

### Priority Mapping

The PagerDuty integration automatically maps Wazuh alert levels to PagerDuty severity:

| Wazuh Level | PagerDuty Severity |
|---|---|
| 1-4 | info |
| 5-7 | warning |
| 8-11 | error |
| 12-15 | critical |

Alerts at level 12 and above create a Critical-priority incident with immediate on-call notification. For fine-grained mapping adjustments, modify the integration script at `/var/ossec/integrations/pagerduty`.

## VirusTotal Integration

The VirusTotal integration automatically checks file hashes detected by the FIM (File Integrity Monitoring) module against the VirusTotal database.

### Configuring VirusTotal

1. Register at [virustotal.com](https://www.virustotal.com) and obtain an API key
2. Add the configuration:

```xml
<integration>
  <name>virustotal</name>
  <api_key>YOUR_VIRUSTOTAL_API_KEY</api_key>
  <group>syscheck,</group>
  <alert_format>json</alert_format>
</integration>
```

### How the Lookup Works

1. The FIM module detects a file change and computes its hash (MD5, SHA1, SHA256)
2. `wazuh-integratord` submits the hash to the VirusTotal API
3. VirusTotal returns the scan result: number of antivirus engines that flagged the file
4. Wazuh generates a supplementary alert with the lookup results

### Free API Limitations

The free VirusTotal API is limited to 4 requests per minute and 500 per day. For production environments with high FIM event volume, consider the Premium API or filter requests to critical directories only.

```xml
<integration>
  <name>virustotal</name>
  <api_key>YOUR_VIRUSTOTAL_API_KEY</api_key>
  <rule_id>554</rule_id>
  <alert_format>json</alert_format>
</integration>
```

Rule 554 fires only when a new file is added, significantly reducing API call volume.

## Shuffle Integration

[Shuffle](https://shuffler.io/) is an open-source SOAR platform that enables automated workflows for processing Wazuh alerts.

### Configuring Shuffle

1. Deploy Shuffle and create a new Workflow
2. Add a **Webhook** trigger and copy the URL
3. Configure the integration in `ossec.conf`:

```xml
<integration>
  <name>shuffle</name>
  <hook_url>https://shuffle.example.com/api/v1/hooks/HOOK_ID</hook_url>
  <level>5</level>
  <alert_format>json</alert_format>
</integration>
```

### Example Workflow

A typical Shuffle workflow for Wazuh alert processing:

1. Receive the alert via webhook
2. Enrich data (IP reputation, WHOIS, geolocation)
3. Classify by severity
4. Create a ticket in Jira or ServiceNow
5. Send a notification to Slack
6. For severity 12+, trigger Active Response via the Wazuh API

For more on SOAR integrations, see the [Third-Party Integrations](/docs/wazuh/integrations/wazuh-third-party-integrations/) section.

## TheHive Integration

[TheHive](https://thehive-project.org/) is an incident management platform that integrates with Wazuh for automated case creation from alerts.

### Configuring TheHive

TheHive integration is implemented through a custom integration script:

1. Generate an API key in TheHive: **Organization** - **Users** - **API Key**
2. Install the integration script:

```bash
cp custom-thehive /var/ossec/integrations/
chmod 750 /var/ossec/integrations/custom-thehive
chown root:wazuh /var/ossec/integrations/custom-thehive
```

3. Add the configuration:

```xml
<integration>
  <name>custom-thehive</name>
  <hook_url>http://thehive.example.com:9000/api/alert</hook_url>
  <api_key>YOUR_THEHIVE_API_KEY</api_key>
  <level>10</level>
  <alert_format>json</alert_format>
</integration>
```

### Field Mapping

The integration script converts a Wazuh alert into a TheHive Alert object:

| Wazuh Field | TheHive Field |
|---|---|
| `rule.description` | `title` |
| `rule.level` | `severity` (1-4) |
| `rule.mitre.id` | `tags` |
| `agent.name` | `sourceRef` |
| `full_log` | `description` |

## Custom Webhook Integrations

For systems without built-in support, Wazuh allows creating arbitrary webhook integrations.

### Building a Custom Integration

1. Write the integration script in Python:

```python
#!/usr/bin/env python3
import sys
import json
import requests

def main():
    # wazuh-integratord passes 4 arguments:
    # 1: path to alert file (JSON)
    # 2: API key (from <api_key>)
    # 3: hook URL (from <hook_url>)
    # 4: path to full alert file

    alert_file = sys.argv[1]
    api_key = sys.argv[2]
    hook_url = sys.argv[3]

    with open(alert_file) as f:
        alert = json.load(f)

    payload = {
        "source": "wazuh",
        "rule_id": alert.get("rule", {}).get("id"),
        "level": alert.get("rule", {}).get("level"),
        "description": alert.get("rule", {}).get("description"),
        "agent": alert.get("agent", {}).get("name"),
        "timestamp": alert.get("timestamp"),
    }

    headers = {
        "Content-Type": "application/json",
        "Authorization": f"Bearer {api_key}",
    }

    response = requests.post(hook_url, json=payload, headers=headers)
    response.raise_for_status()

if __name__ == "__main__":
    main()
```

2. Install the script:

```bash
cp custom-webhook /var/ossec/integrations/
chmod 750 /var/ossec/integrations/custom-webhook
chown root:wazuh /var/ossec/integrations/custom-webhook
```

3. Configure in `ossec.conf`:

```xml
<integration>
  <name>custom-webhook</name>
  <hook_url>https://api.example.com/wazuh-alerts</hook_url>
  <api_key>YOUR_API_KEY</api_key>
  <level>7</level>
  <alert_format>json</alert_format>
</integration>
```

## Syslog Forwarding

Syslog forwarding enables sending Wazuh alerts to other SIEM platforms (Splunk, QRadar, ArcSight, ELK) over the syslog protocol.

### Configuring Syslog Output

The configuration is defined in the `<syslog_output>` block of `ossec.conf`:

```xml
<syslog_output>
  <server>192.168.1.100</server>
  <port>514</port>
  <format>json</format>
  <level>5</level>
</syslog_output>
```

### Supported Formats

| Format | Description | Recommended Use |
|---|---|---|
| `default` | Standard syslog (RFC 3164) | Legacy SIEM compatibility |
| `json` | JSON alert format | Splunk, ELK, modern SIEMs |
| `cef` | Common Event Format | ArcSight, QRadar |

### Filtering by Group and Level

```xml
<syslog_output>
  <server>splunk.example.com</server>
  <port>1514</port>
  <format>json</format>
  <level>7</level>
  <group>authentication_failed,attack,</group>
</syslog_output>
```

### Syslog over TLS

For secure forwarding, use rsyslog or syslog-ng as an intermediary layer with TLS encryption:

```bash
# /etc/rsyslog.d/wazuh-forward.conf
module(load="imudp")
input(type="imudp" port="514")

action(
  type="omfwd"
  target="siem.example.com"
  port="6514"
  protocol="tcp"
  StreamDriver="gtls"
  StreamDriverMode="1"
  StreamDriverAuthMode="x509/name"
)
```

## Wazuh as a Data Source for Splunk

Wazuh provides an official Splunk application that enables bidirectional integration.

### Integration Architecture

```
Wazuh Manager --> syslog/json --> Splunk Universal Forwarder --> Splunk Indexer
                                                                     |
                                                              Wazuh App for Splunk
```

### Configuring the Splunk Forwarder

1. Install Splunk Universal Forwarder on the Wazuh Manager server
2. Configure alert file monitoring:

```ini
# /opt/splunkforwarder/etc/system/local/inputs.conf
[monitor:///var/ossec/logs/alerts/alerts.json]
disabled = false
index = wazuh
sourcetype = wazuh-alerts
```

3. Install the Wazuh App for Splunk on the Search Head for data visualization

### Wazuh Standalone vs Splunk/ELK Complement

| Criterion | Wazuh Standalone | Wazuh + Splunk/ELK |
|---|---|---|
| Data storage | OpenSearch (Wazuh Indexer) | Splunk/Elasticsearch |
| Visualization | Wazuh Dashboard | Splunk/Kibana + Wazuh App |
| Correlation | Wazuh rules | Wazuh rules + SPL/KQL |
| Scaling | OpenSearch cluster | Splunk/ELK infrastructure |
| Cost | Free | Splunk license / ELK resources |

For organizations already running Splunk or ELK, a hybrid approach is recommended: Wazuh handles data collection and primary endpoint analysis, while the SIEM performs centralized correlation and long-term storage.

## Elastic Stack (ELK) Integration

Wazuh supports Elasticsearch integration through Filebeat.

### Configuring Filebeat

```yaml
# /etc/filebeat/filebeat.yml
filebeat.modules:
  - module: wazuh
    alerts:
      enabled: true

output.elasticsearch:
  hosts: ["https://elasticsearch.example.com:9200"]
  index: "wazuh-alerts-%{+yyyy.MM.dd}"
  username: "elastic"
  password: "${ES_PASSWORD}"
  ssl.certificate_authorities: ["/etc/filebeat/certs/ca.pem"]
```

For detailed Filebeat configuration, refer to the [official Wazuh documentation](https://documentation.wazuh.com/current/deployment-options/elastic-stack/index.html).

## Troubleshooting

### Alerts Not Reaching the External System

1. Check the integratord daemon status:

```bash
/var/ossec/bin/wazuh-control status | grep integratord
```

2. Review integration logs:

```bash
tail -f /var/ossec/logs/integrations.log
```

3. Verify the integration script has correct permissions:

```bash
ls -la /var/ossec/integrations/
# Expected permissions: -rwxr-x--- root wazuh
```

### Authentication Errors

- **Slack**: verify the webhook URL is active and the app has not been deactivated
- **PagerDuty**: confirm the Integration Key matches the Events API v2 service
- **VirusTotal**: check the API request quota in the [VirusTotal Dashboard](https://www.virustotal.com/gui/my-apikey)

### High integratord Load

With a large number of alerts, the daemon may build up a queue. Recommendations:

- Raise the `<level>` threshold to filter out non-critical alerts
- Use `<rule_id>` or `<group>` for targeted forwarding
- Monitor queue size via `/var/ossec/var/run/wazuh-integratord.state`

### Syslog Forwarding Not Working

1. Verify network connectivity:

```bash
nc -zv siem.example.com 514
```

2. Confirm the `<syslog_output>` block is inside `<ossec_config>`:

```bash
/var/ossec/bin/wazuh-logtest -t
```

3. Ensure the server was restarted after configuration changes:

```bash
/var/ossec/bin/wazuh-control restart
```

For guidance on writing custom integration scripts, see the [Custom Integration Development](/docs/wazuh/development/wazuh-custom-integrations/) section.

