# soc-integrator FastAPI service that bridges Wazuh, IRIS, Shuffle, PagerDuty, VirusTotal, and AbuseIPDB. ## Getting Started ```bash 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`](.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:** ```bash curl -X POST http://localhost:8088/wazuh/ioc-lists/refresh \ -H 'X-Internal-API-Key: dev-internal-key' ``` **Status:** ```bash 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 |