https://github.com/jnthans/wazuh-cortex-xdr
Wazuh SIEM wodle that ingests alerts and incidents from Palo Alto's Cortex XDR via the Cortex XDR REST API.
https://github.com/jnthans/wazuh-cortex-xdr
cortex-xdr security siem wazuh xdr
Last synced: about 2 months ago
JSON representation
Wazuh SIEM wodle that ingests alerts and incidents from Palo Alto's Cortex XDR via the Cortex XDR REST API.
- Host: GitHub
- URL: https://github.com/jnthans/wazuh-cortex-xdr
- Owner: jnthans
- Created: 2026-03-01T18:37:57.000Z (3 months ago)
- Default Branch: master
- Last Pushed: 2026-03-26T15:59:46.000Z (2 months ago)
- Last Synced: 2026-03-27T00:51:31.628Z (2 months ago)
- Topics: cortex-xdr, security, siem, wazuh, xdr
- Language: Python
- Homepage:
- Size: 303 KB
- Stars: 0
- Watchers: 2
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# Cortex XDR - Wazuh Integration
Wazuh wodle that ingests **alerts** and **incidents** from Palo Alto Networks Cortex XDR into Wazuh SIEM via the Cortex XDR REST API.
---
## Dashboard

*Custom Cortex XDR dashboard showing alert counts by severity, event type word cloud, category breakdown, top endpoints, MITRE tactic mappings, and other metrics.*

*Wazuh Threat Hunting dashboard filtered by integration `cortex-xdr`, showing ingested incidents with severity levels, rule IDs, and descriptions.*
---
## Features
- **Single wodle block** — one scheduled command captures both alerts and incidents, including the full incident lifecycle: new, under investigation, and closed.
- **Stateful** — bookmarks last-seen timestamps per data stream. Each run only pulls what changed.
- **Long-term archival** — Cortex does not retain data indefinitely. This integration persists all events in OpenSearch for compliance, forensics, and historical investigation.
- **MITRE ATT&CK tactic tagging** — incidents with tactic mappings are tagged with `mitre_*` groups for custom dashboard filtering.
- **Closed incident tracking** — resolved incidents are ingested as level 3 archival records.
- **Secure credential management** — FQDN, API key, and key ID stored in a restricted secrets file or systemd encrypted credentials.
- **Multi-tenant** — deploy a separate directory and `run.sh` per tenant.
- **Zero external Python dependencies** — stdlib only.
---
## Installation
1. Copy `wodle/*` to `/var/ossec/wodles/cortex-xdr/` on the Wazuh manager (or agent host).
2. Create `.secrets` from `.secrets.example` — set `XDR_FQDN`, `XDR_API_KEY`, `XDR_API_KEY_ID`. Set permissions `chmod 640, chown root:wazuh`.
3. Copy `rules/cortex_xdr_rules.xml` to `/var/ossec/etc/rules/` and `rules/cortex_xdr_decoder.xml` to `/var/ossec/etc/decoders/`.
4. Add a wodle stanza to `/var/ossec/etc/ossec.conf` using the example in [artifacts/configs/ossec_cortex_xdr.conf](artifacts/configs/ossec_cortex_xdr.conf).
5. Restart Wazuh manager.
See [artifacts/configs/](artifacts/configs/) for ossec.conf examples and systemd credential configuration.
---
## Repository structure
```
wazuh-cortex-xdr/
├── wodle/
│ ├── cortex_xdr.py ← Entry point, CLI, orchestration
│ ├── cortex_xdr_alerts.py ← Alert fetch and pagination
│ ├── cortex_xdr_incidents.py ← Incident fetch and pagination
│ ├── cortex_xdr_utils.py ← Auth, HTTP, atomic state, emit, logging, secrets
│ ├── run.sh ← Runtime config wrapper (ossec.conf target)
│ └── .secrets.example ← Credentials template (copy to .secrets)
├── rules/
│ ├── cortex_xdr_rules.xml ← Custom Wazuh rules (IDs 100500–100599)
│ └── cortex_xdr_decoder.xml ← JSON decoder registration
├── artifacts/
│ ├── configs/
│ │ ├── ossec_cortex_xdr.conf ← ossec.conf wodle stanza examples
│ │ └── cortex-xdr-credentials.conf ← systemd drop-in for encrypted credentials
│ ├── guides/
│ │ ├── configuration.md ← All env vars, CLI flags, multi-tenant
│ │ ├── rules-reference.md ← Rule families, severity mapping, MITRE, compliance
│ │ └── troubleshooting.md ← Test commands, common errors, reset / backfill
│ ├── images/
│ │ ├── wazuh_cortex_xdr_dash_pv.png ← Cortex XDR dashboard screenshot
│ │ └── wazuh_xdr_th_pv.png ← Wazuh Threat Hunting dashboard screenshot
│ └── objects/
│ └── Cortex XDR.ndjson ← OpenSearch Dashboards saved object (importable)
├── .gitignore
└── README.md
```
---
## How it works
```
ossec.conf
└─► run.sh (sets runtime config; execs cortex_xdr.py)
└─► cortex_xdr.py (parses args, loads state, orchestrates fetchers)
├─► cortex_xdr_alerts.py → xdr_api_post() → emit() → stdout
└─► cortex_xdr_incidents.py → xdr_api_post() → emit() → stdout
↑
cortex_xdr_utils.py
(auth headers, HTTP, atomic state, emit, secrets)
↑
Secret priority chain (first match wins):
[systemd $CREDENTIALS_DIRECTORY]
> [.secrets file]
> [environment variable]
stdout ──► Wazuh wodle manager ──► cortex_xdr_decoder.xml ──► cortex_xdr_rules.xml
↓
OpenSearch / Dashboard
```
Each event is emitted as a single JSON line. All XDR API fields are nested under the `xdr` key to avoid collisions with Wazuh's reserved field names. Wazuh's JSON decoder maps nested fields as `xdr.field_name` for rule matching and `data.xdr.field_name` in OpenSearch.
Epoch-millisecond timestamp fields returned by the Cortex XDR API are converted to ISO 8601 strings before emission (e.g. `1706540499609` → `"2024-01-29T18:41:39.609Z"`). This causes OpenSearch's dynamic field mapping to detect them as date fields automatically — no custom index template is required.
### Deployment topology
The wodle can run on three different hosts — the choice does not affect the wodle code itself:
- **Manager / master node** (default) — simplest to deploy.
- **Dedicated Wazuh agent host** — credentials never touch the manager; polling is independent of manager restarts and cluster failovers.
- **Existing agent on a connected host** — any agent host with network access to the Cortex XDR API can run the wodle with no additional infrastructure.
---
## Reference docs
- [Configuration reference](artifacts/guides/configuration.md) — all environment variables, CLI flags, multi-tenant setup
- [Rules reference](artifacts/guides/rules-reference.md) — rule families, severity mapping, MITRE ATT&CK, compliance groups
- [Troubleshooting](artifacts/guides/troubleshooting.md) — test commands, common errors, state reset, backfill