|
|
@@ -640,6 +640,111 @@ This update documents production log sources and required fields for Appendix C
|
|
640
|
640
|
|
|
641
|
641
|
---
|
|
642
|
642
|
|
|
|
643
|
+Date: March 17, 2026
|
|
|
644
|
+Project: FoodProject SOC Platform (Wazuh + Shuffle + IRIS-web + SOC Integrator)
|
|
|
645
|
+
|
|
|
646
|
+## Incremental Progress Since March 4, 2026
|
|
|
647
|
+
|
|
|
648
|
+### 1) IRIS Stack Stabilization
|
|
|
649
|
+
|
|
|
650
|
+- Fixed Alembic DB revision mismatch caused by DB being initialized from a different branch:
|
|
|
651
|
+ - Identified correct head revision (`d5a720d1b99b`) and stamped the DB directly
|
|
|
652
|
+ - Fixed missing `ioc.case_id` column (`ALTER TABLE ioc ADD COLUMN IF NOT EXISTS case_id ...`) skipped by the migration
|
|
|
653
|
+- Fixed IRIS static file 404 errors (jQuery, Bootstrap, app JS):
|
|
|
654
|
+ - Root cause: Svelte/Vite frontend (`ui/dist`) had never been built
|
|
|
655
|
+ - Fix: ran `npm install && npm run build` inside the `iris-web/ui` container to produce `dist/`
|
|
|
656
|
+- All IRIS web UI pages now load correctly including case management and KPI dashboard
|
|
|
657
|
+
|
|
|
658
|
+### 2) KPI Dashboard (IRIS)
|
|
|
659
|
+
|
|
|
660
|
+- Added a custom KPI dashboard page to IRIS web (`/kpi`):
|
|
|
661
|
+ - Files: `iris-web/source/app/blueprints/pages/kpi_dashboard/`
|
|
|
662
|
+ - Registered in Flask app and added to sidebar navigation
|
|
|
663
|
+ - Frontend JS/CSS: `iris-web/ui/src/pages/kpi_dashboard.js`, `iris-web/ui/src/css/kpi_dashboard.css`
|
|
|
664
|
+- Added KPI test data seeder: `scripts/seed-kpi-test-data.py`
|
|
|
665
|
+- Updated `manage_cases.html` and `case.html` templates for KPI-related display fields
|
|
|
666
|
+
|
|
|
667
|
+### 3) Shuffle Credential Persistence
|
|
|
668
|
+
|
|
|
669
|
+- Investigated and resolved the Shuffle admin password being unknown after restarts:
|
|
|
670
|
+ - Password hash is stored in OpenSearch under `Password` (capital P) as bcrypt (`$2a$` prefix for Go compat)
|
|
|
671
|
+ - Root cause: `SHUFFLE_DEFAULT_PASSWORD` was blank; password was auto-generated and not saved
|
|
|
672
|
+ - Fix: set `SHUFFLE_DEFAULT_USERNAME`, `SHUFFLE_DEFAULT_PASSWORD`, and `SHUFFLE_DEFAULT_APIKEY` in `Shuffle/.env`
|
|
|
673
|
+ - API key is now fixed across restarts via `SHUFFLE_DEFAULT_APIKEY`
|
|
|
674
|
+- Created `pass.txt` at project root documenting all system credentials (IRIS, Shuffle, Wazuh, SOC Integrator, third-party API keys)
|
|
|
675
|
+
|
|
|
676
|
+### 4) SOC Integrator → Shuffle API Fix
|
|
|
677
|
+
|
|
|
678
|
+- Fixed `/shuffle/apps` and `/shuffle/workflows` returning 401:
|
|
|
679
|
+ - Root cause: container had an old API key baked from a previous creation — `docker restart` does NOT re-read `env_file`
|
|
|
680
|
+ - Fix: generated fresh Shuffle API key via session cookie, updated `soc-integrator/.env`, and used `--force-recreate` to pick up the new key
|
|
|
681
|
+- Both Shuffle proxy endpoints now return 200 from `soc-integrator`
|
|
|
682
|
+
|
|
|
683
|
+### 5) Wazuh Dashboard — Real-Data Filters
|
|
|
684
|
+
|
|
|
685
|
+- Fixed "Could not locate index-pattern" error on all custom dashboards:
|
|
|
686
|
+ - All 4 dashboard ndjson files had their own private index-pattern objects that conflicted with the canonical `wazuh-alerts-*` pattern
|
|
|
687
|
+ - Fix: removed private index-pattern objects from each ndjson; updated all `references[]` and `searchSourceJSON.indexRefName` entries to point to `wazuh-alerts-*`
|
|
|
688
|
+- Replaced simulation-era `full_log:*usecase_id*` filters across all dashboards with production-data filters:
|
|
|
689
|
+ - **Custom rules dashboard**: filter changed to `rule.groups: soc_prod*`
|
|
|
690
|
+ - Note: `rule.id` is a `keyword` field in OpenSearch — range queries are lexicographic, not numeric; ID-based range filtering is unreliable
|
|
|
691
|
+ - `rule.groups: soc_prod*` is the correct discriminator — all SOC custom rules carry this group; no built-in Wazuh rules do
|
|
|
692
|
+ - **Required/appendix dashboards**: all 51 usecase_id sub-filters remapped to actual `rule.id: 110xxx` values and `rule.groups: appendix_a/b` splits
|
|
|
693
|
+ - **Appendix A/B dashboard**: top filter `full_log:*usecase_id*` → `rule.groups: soc_prod*`; A/B panel splits use `rule.groups: appendix_a` and `rule.groups: appendix_b`
|
|
|
694
|
+ - 7 use cases with no implemented production rule set to `rule.id: __no_rule__` (intentional no-match)
|
|
|
695
|
+- All 4 dashboards imported and rendering correctly against live `wazuh-alerts-*` data
|
|
|
696
|
+
|
|
|
697
|
+### 6) Firewall Syslog Testing
|
|
|
698
|
+
|
|
|
699
|
+- Added `scripts/test-firewall-syslog.py`:
|
|
|
700
|
+ - Sends FortiGate-style syslog UDP to Wazuh port 514 with 10 test scenarios
|
|
|
701
|
+ - Supports `--via-docker` flag to preserve source IP through Docker NAT
|
|
|
702
|
+- Added 7 firewall source IPs to `wazuh_manager.conf` allowed list
|
|
|
703
|
+- Enabled `logall` and `logall_json` in Wazuh manager config for improved debug visibility
|
|
|
704
|
+
|
|
|
705
|
+### 7) Production Log Samples
|
|
|
706
|
+
|
|
|
707
|
+- Added production log sample files under `samples/`:
|
|
|
708
|
+ - `samples/appendix-a-production-samples.log`
|
|
|
709
|
+ - `samples/appendix-b-production-samples.log`
|
|
|
710
|
+ - `samples/appendix-c-production-samples.log`
|
|
|
711
|
+- Added `samples/README.md` documenting log format and usage
|
|
|
712
|
+
|
|
|
713
|
+### 8) Rule Match Evidence (Live Data, 2026-03-14 → 2026-03-17)
|
|
|
714
|
+
|
|
|
715
|
+- Queried all SOC custom rules against OpenSearch `wazuh-alerts-*` and generated `summary_rule_match.md`
|
|
|
716
|
+- Total events matched: **252,262** across 49 implemented rules
|
|
|
717
|
+
|
|
|
718
|
+Active rules with events:
|
|
|
719
|
+
|
|
|
720
|
+| Rule | Description | Events |
|
|
|
721
|
+|------|-------------|--------|
|
|
|
722
|
+| 110301 | A1-01 DNS query to malicious domain | 32 |
|
|
|
723
|
+| 110302 | A1-02 DNS IOC domain match | 32 |
|
|
|
724
|
+| 110312 | A2-02 FortiGate admin password changed | 32 |
|
|
|
725
|
+| 110313 | A2-03 FortiGate new admin account created | 32 |
|
|
|
726
|
+| 110315 | A2-05 FortiGate config file downloaded | 32 |
|
|
|
727
|
+| 110320 | A2-10 FortiGate traffic to known C2 | 32 |
|
|
|
728
|
+| 110341 | A4-01 Windows privileged account auth failure | 1 |
|
|
|
729
|
+| 110342 | A4-02 Windows service account auth failure | 38 |
|
|
|
730
|
+| 110354 | A4-13 Windows DC DSRM password set (4794) | 251,833 ⚠️ |
|
|
|
731
|
+| 110359 | A4-19 Windows authentication failure (4625) | 54 |
|
|
|
732
|
+| 110411 | B2-01 Log Monitor log loss detected | 16 |
|
|
|
733
|
+| 110501 | C1-01 VPN login geo context candidate | 97 |
|
|
|
734
|
+| 110502 | C1-01 Impossible travel confirmed | 31 |
|
|
|
735
|
+
|
|
|
736
|
+- ⚠️ Rule 110354 (DSRM / event 4794 via parent 60105) accounts for 99.8% of event volume — under investigation to confirm parent SID scope
|
|
|
737
|
+- Log sources not yet forwarding: FortiGate VPN (A3), VMware (B1), Sysmon/endpoints (B3), Windows 4624 auth success (C2/C3)
|
|
|
738
|
+
|
|
|
739
|
+### 9) Tooling and Documentation Updates
|
|
|
740
|
+
|
|
|
741
|
+- `run-combined-stack.sh`: added `dedup` command (fixed missing `elif` branch) and `recreate` command
|
|
|
742
|
+- `README.md`: full rewrite covering all stack commands, KPI dashboard, current endpoint list, and macOS bind-mount note
|
|
|
743
|
+- `scripts/README.md`: documented `test-firewall-syslog.py`, `seed-kpi-test-data.py`, and new dashboard ndjson files
|
|
|
744
|
+- `docs/wazuh-decoders-rules.md`: documentation for custom decoder/rule structure
|
|
|
745
|
+
|
|
|
746
|
+---
|
|
|
747
|
+
|
|
643
|
748
|
Date: March 4, 2026
|
|
644
|
749
|
Project: FoodProject SOC Platform (Wazuh + Shuffle + IRIS-web + SOC Integrator)
|
|
645
|
750
|
|