CategorySOC Automation · AI Security · Python
ToolsPython, OpenAI API, Wazuh Indexer (OpenSearch), Rocky Linux, PowerShell
RoleDesigned, built, troubleshot, and documented end-to-end
StatusFunctional - Run on demand
SkillsSIEM integration, API auth, JSON parsing, Python automation, AI triage, Linux admin, networking

Problem

The goal was to build a practical cybersecurity project that combines real SIEM telemetry with AI-assisted alert triage. Rather than simulate data, the project required connecting to a real SIEM environment and automating the analyst workflow: retrieve an alert, understand its context, and produce a structured triage report.

The specific challenge: how do you take raw security event data from a live SIEM, extract the meaningful fields, and produce something that reads like a trained analyst's assessment - automatically, on demand?

The secondary challenge was infrastructure. Before any code could run, the lab environment needed to be fully operational - which required real troubleshooting.

Environment

  • Windows PC (analyst workstation) - 172.22.2.119
  • Wazuh server VM running Rocky Linux - wazuh1 · 172.22.3.49
  • Xen Orchestra (XOA) managing the virtualized environment
  • Multiple Wazuh agents reporting telemetry (Windows and Linux endpoints)
  • Wazuh Indexer (OpenSearch) on port 9200 storing alert documents
  • OpenAI API for AI-assisted triage
  • Python project folder on the Windows analyst workstation

The SIEM dashboard showed 8 agents (6 active, 2 disconnected) with real security events including authentication failures, MITRE ATT&CK-mapped alerts, and Windows/Linux log entries.

Final Architecture

The completed pipeline operates as a run-on-demand script that pulls the most recent security alert and produces a structured triage report:

Windows/Linux HostsWazuh Agents reporting telemetry
Wazuh Managerwazuh1 · Rocky Linux · 172.22.3.49
Wazuh IndexerPort 9200 · wazuh-alerts-* index
Python Scripttriage_latest_wazuh_alert.py
OpenAI APIGPT-based SOC analysis
SOC Triage ReportMarkdown saved to reports/

The script is run manually: python triage_latest_wazuh_alert.py

It connects to the Wazuh Indexer, queries the latest alert, extracts key fields, sends a structured summary to OpenAI, prints the triage output, and saves both the report and raw alert JSON to disk.

Infrastructure Setup & Discovery

The project didn't begin with coding - it began with infrastructure troubleshooting. The only starting information was a sticky note with IP addresses: the Wazuh server at 172.22.3.49, managed through Xen Orchestra.

Initial problem: Every connection attempt to the Wazuh server failed - ping, SSH, and browser access all returned unreachable errors.

The troubleshooting process followed a deliberate layer-by-layer approach:

  1. Checked Xen Orchestra - found the Wazuh VM existed but was powered off. Started it.
  2. Opened the VM console - logged in as user shamar on Rocky Linux (hostname: wazuh1). Confirmed sudo access.
  3. Ran ip addr - the eth0 interface was present but had no IPv4 address assigned.
  4. Ran ip route - the routing table was completely empty.
  5. Checked NetworkManager - nmcli device status showed eth0 as "disconnected". A saved profile named "eth0" existed but wasn't active.
  6. Inspected the profile - nmcli connection show eth0 | grep ipv4 revealed a valid static config: 172.22.3.49/22, gateway 172.22.0.1. The configuration was correct - just inactive.
Rocky Linux - NetworkManager
# Activate the existing connection profile sudo nmcli connection up eth0 Connection successfully activated # Verify IP assignment ip addr show eth0 inet 172.22.3.49/22 brd 172.22.3.255 scope global eth0 # Set autoconnect so it survives reboots sudo nmcli connection modify eth0 connection.autoconnect yes

After restoring the network, the Wazuh dashboard became accessible at https://172.22.3.49. It showed 8 agents reporting telemetry and existing security events with MITRE ATT&CK technique mappings.

Python Automation

The Python project was created at C:\Users\shamar\ai-wazuh-triage with a virtual environment to isolate dependencies.

Phase 1 - Manual JSON triage: The first working script (triage_alert.py) loaded a manually exported Wazuh alert JSON, parsed key fields, sent a structured summary to OpenAI, printed the triage analysis, and saved a Markdown report to reports/.

triage_alert.py - core workflow
# Load alert with open("alert.json", "r") as f: alert = json.load(f) # Extract key fields summary = { "agent": alert.get("agent", {}).get("name"), "rule_desc": alert["rule"]["description"], "level": alert["rule"]["level"], "mitre": alert.get("rule", {}).get("mitre", {}) } # Send to OpenAI response = client.chat.completions.create( model="gpt-4o-mini", messages=[ {"role": "system", "content": "You are a SOC analyst..."}, {"role": "user", "content": json.dumps(summary)} ] )

Phase 2 - Automated alert retrieval: The manual export step was eliminated. The script was rewritten to connect directly to the Wazuh Indexer, query the wazuh-alerts-* index, retrieve the most recent alert by timestamp, and run the same triage process automatically.

Wazuh Indexer Integration

The Wazuh dashboard stores alert documents in the Wazuh Indexer (OpenSearch), accessible on port 9200. The Python script queries this directly to pull the latest alert:

Indexer query - latest alert
query = { "size": 1, "sort": [{"@timestamp": {"order": "desc"}}], "query": {"match_all": {}} } response = requests.post( f"{INDEXER_URL}/wazuh-alerts-*/_search", auth=(INDEXER_USER, INDEXER_PASS), json=query, verify=False # self-signed cert in lab )

The Indexer was initially bound only to localhost (127.0.0.1:9200). It had to be exposed to the LAN by updating /etc/wazuh-indexer/opensearch.yml to network.host: 0.0.0.0 and restarting the service. This is only appropriate in a trusted lab environment - not production.

Credentials for the Indexer were separate from the Wazuh API credentials. The correct admin credentials came from the installer-generated file at /root/wazuh-install-files/wazuh-passwords.txt.

Challenges & Fixes

Problem

Wazuh VM unreachable - ping, SSH, and browser access all failed.

Fix

VM was powered off. Started via Xen Orchestra, then activated the inactive NetworkManager profile with nmcli connection up eth0.

Problem

Network fix didn't survive reboot - Wazuh became unreachable again after restart.

Fix

Set connection.autoconnect yes on the eth0 profile so it activates automatically at boot.

Problem

PowerShell blocked venv activation: "running scripts is disabled on this system."

Fix

Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass - changes only the current session.

Problem

OpenAI returned RateLimitError: insufficient_quota immediately after first request.

Fix

ChatGPT Plus and the OpenAI API are billed separately. Added API credits to the account - resolved immediately.

Problem

Port 9200 timed out from Windows - the Indexer was bound only to localhost.

Fix

Confirmed with ss -lntp | grep 9200 showing 127.0.0.1:9200. Updated opensearch.yml to network.host: 0.0.0.0, restarted service.

Problem

Wazuh API credentials (port 55000) kept returning 401 despite multiple credential attempts.

Fix

Found installer-generated credentials at /root/wazuh-install-files/wazuh-passwords.txt. The dashboard config credentials were not valid for direct API auth.

Results

8 Wazuh Agents Reporting Telemetry
100% Automated - No Manual Alert Export
2 Scripts (Manual & Automated)

The final script successfully:

  • Connects to the Wazuh Indexer and retrieves the latest alert from wazuh-alerts-*
  • Extracts agent name, rule description, severity level, MITRE ATT&CK IDs and techniques
  • Handles both Windows alerts (Event ID, logon type, process name) and Linux alerts (PAM, SSH, syslog)
  • Sends a structured summary to OpenAI and receives an analyst-style triage
  • Saves the triage report as Markdown and the raw alert as JSON to reports/
Example output: For a PAM login session alert (Rule Level 3, MITRE T1078 Valid Accounts), the AI correctly classified the event as likely benign, explained the process context, noted the MITRE technique relevance, and provided recommended next verification steps.

Skills Demonstrated

Linux Administration NetworkManager / nmcli IP Addressing & Routing Virtualization (Xen) SIEM Concepts Wazuh Indexer API Python REST API Integration JSON Parsing OpenAI API Alert Triage MITRE ATT&CK Python venv SQLite (RBAC inspection) Credential Management Methodical Troubleshooting

Planned Next Steps

  • Add --limit N option to triage the latest N alerts in one run
  • Add severity filtering - only analyze alerts above a rule level threshold
  • Track analyzed alert IDs locally to avoid duplicate triage
  • Separate Windows vs. Linux alert parsing for better field coverage
  • Build a simple Streamlit or Flask dashboard to browse alerts and view reports
  • Add email or Slack notification for high-severity findings