soc-integrator
FastAPI service that bridges Wazuh, IRIS, Shuffle, PagerDuty, VirusTotal, and AbuseIPDB.
Getting Started
cp .env.example .env
# edit .env — fill in API keys and passwords
docker compose up -d
Environment Variables (.env)
A fully annotated sample is in .env.example. The table below describes every key.
Core
| Variable |
Default |
Description |
APP_ENV |
dev |
Environment label (dev / prod) |
LOG_LEVEL |
INFO |
Python log level |
SOC_INTEGRATOR_INTERNAL_KEY |
dev-internal-key |
API key required on internal endpoints (X-Internal-API-Key header) |
Database
| Variable |
Default |
Description |
SOC_INTEGRATOR_DB_HOST |
soc-integrator-db |
Postgres hostname |
SOC_INTEGRATOR_DB_PORT |
5432 |
Postgres port |
SOC_INTEGRATOR_DB_NAME |
soc_integrator |
Database name |
SOC_INTEGRATOR_DB_USER |
soc_integrator |
Database user |
SOC_INTEGRATOR_DB_PASSWORD |
soc_integrator_password |
Database password |
Wazuh
| Variable |
Default |
Description |
WAZUH_BASE_URL |
https://wazuh.manager:55000 |
Wazuh manager REST API URL |
WAZUH_USERNAME |
wazuh-wui |
Wazuh API username |
WAZUH_PASSWORD |
MyS3cr37P450r.*- |
Wazuh API password |
WAZUH_INDEXER_URL |
https://wazuh.indexer:9200 |
OpenSearch/Wazuh indexer URL |
WAZUH_INDEXER_USERNAME |
admin |
Indexer username |
WAZUH_INDEXER_PASSWORD |
SecretPassword |
Indexer password |
Wazuh Auto-Sync
Background loop that pulls Wazuh alerts and creates IRIS alerts automatically.
| Variable |
Default |
Description |
WAZUH_AUTO_SYNC_ENABLED |
true |
Enable/disable background sync loop |
WAZUH_AUTO_SYNC_INTERVAL_SECONDS |
60 |
How often to run sync (seconds) |
WAZUH_AUTO_SYNC_QUERY |
* |
OpenSearch query string filter |
WAZUH_AUTO_SYNC_LIMIT |
50 |
Max alerts per sync cycle |
WAZUH_AUTO_SYNC_MINUTES |
120 |
Lookback window per sync cycle (minutes) |
Shuffle
| Variable |
Default |
Description |
SHUFFLE_BASE_URL |
http://shuffle-backend:5001 |
Shuffle API base URL |
SHUFFLE_API_KEY |
(empty) |
Shuffle API key |
SHUFFLE_USERNAME |
(empty) |
Shuffle username (if using basic auth) |
SHUFFLE_PASSWORD |
(empty) |
Shuffle password |
PagerDuty
| Variable |
Default |
Description |
PAGERDUTY_BASE_URL |
http://pagerduty-stub |
PagerDuty API base URL (stub in MVP) |
PAGERDUTY_API_KEY |
(empty) |
PagerDuty integration key |
IRIS
| Variable |
Default |
Description |
IRIS_BASE_URL |
https://iriswebapp_nginx:8443 |
IRIS web app base URL |
IRIS_API_KEY |
(empty) |
IRIS API key (from IRIS user settings) |
IRIS_DEFAULT_CUSTOMER_ID |
1 |
Customer ID used when creating IRIS alerts/cases |
IRIS_DEFAULT_SOC_ID |
(empty) |
Default SOC user ID for assignment |
Threat Intelligence (IOC Enrichment)
| Variable |
Default |
Description |
VIRUSTOTAL_BASE_URL |
https://www.virustotal.com/api/v3 |
VirusTotal API base URL |
VIRUSTOTAL_API_KEY |
(empty) |
VirusTotal API key |
ABUSEIPDB_BASE_URL |
https://api.abuseipdb.com/api/v2 |
AbuseIPDB API base URL |
ABUSEIPDB_API_KEY |
(empty) |
AbuseIPDB API key |
IOC CDB List Refresh
Background loop that fetches public threat feeds, merges with locally confirmed IOCs, writes Wazuh CDB list files, and restarts the Wazuh manager to recompile them.
Feeds: Feodo Tracker (C2 IPs), URLhaus (malware domains), ThreatFox (IPs/domains/hashes), MalwareBazaar (SHA256 hashes), plus high-confidence hits from the local ioc_trace table.
Shared volume: wazuh-docker/single-node/config/wazuh_cluster/lists/malicious-ioc/ is bind-mounted into both containers:
- Wazuh manager →
/var/ossec/etc/lists/malicious-ioc
- soc-integrator →
/ioc-lists
| Variable |
Default |
Description |
IOC_REFRESH_ENABLED |
false |
Enable/disable background refresh loop |
IOC_REFRESH_INTERVAL_SECONDS |
14400 |
Refresh interval (seconds). Default = 4 hours. Minimum enforced: 300s |
IOC_REFRESH_CONFIDENCE_THRESHOLD |
0.7 |
Minimum confidence (0–1) for a local ioc_trace hit to be included in CDB lists |
IOC_REFRESH_LOOKBACK_DAYS |
30 |
How many days back to query ioc_trace for confirmed local hits |
WAZUH_LISTS_PATH |
/ioc-lists |
Container path where CDB list files are written (must match bind-mount destination) |
Manual trigger:
curl -X POST http://localhost:8088/wazuh/ioc-lists/refresh \
-H 'X-Internal-API-Key: dev-internal-key'
Status:
curl http://localhost:8088/wazuh/ioc-lists/status
Log Loss Monitor
Background loop that checks Wazuh alert ingestion rate and optionally creates an IRIS ticket when no logs arrive within the window.
| Variable |
Default |
Description |
LOG_LOSS_MONITOR_ENABLED |
false |
Enable/disable background monitor loop |
LOG_LOSS_MONITOR_INTERVAL_SECONDS |
60 |
How often to check (seconds) |
LOG_LOSS_MONITOR_WINDOW_MINUTES |
5 |
Sliding window to count alerts (minutes) |
LOG_LOSS_MONITOR_CREATE_IRIS_TICKET |
false |
Create IRIS alert when log loss detected |
LOG_LOSS_MONITOR_TICKET_COOLDOWN_SECONDS |
900 |
Minimum time between consecutive IRIS tickets (seconds) |
GeoIP
| Variable |
Default |
Description |
GEOIP_PROVIDER |
ipwhois |
GeoIP backend (ipwhois uses free ipwhois.app API) |
GEOIP_CACHE_TTL_SECONDS |
21600 |
How long to cache GeoIP results (seconds). Default = 6 hours |
Correlation / C-Detection
| Variable |
Default |
Description |
C_DETECTION_ENABLED |
true |
Enable/disable correlation engine |
C_DETECTION_WINDOW_MINUTES |
30 |
Sliding time window for correlation checks (minutes) |
C_DETECTION_CREATE_IRIS_TICKET |
true |
Create IRIS alert on correlation hit |
C_DETECTION_TICKET_COOLDOWN_SECONDS |
900 |
Minimum time between IRIS tickets for the same entity (seconds) |
C1_MAX_TRAVEL_SPEED_KMPH |
900 |
C1 impossible travel: max plausible speed (km/h) |
C2_OFFHOURS_START_UTC |
20 |
C2 off-hours login: day end hour (UTC, 0–23) |
C2_OFFHOURS_END_UTC |
6 |
C2 off-hours login: day start hour (UTC, 0–23) |
C3_HOST_SPREAD_THRESHOLD |
5 |
C3 lateral movement: unique destination hosts threshold |
C3_SCAN_PORT_THRESHOLD |
20 |
C3 lateral movement: unique destination ports threshold |