poc2_worked
This commit is contained in:
@@ -1,7 +1,10 @@
|
||||
import os
|
||||
import subprocess
|
||||
import tempfile
|
||||
import time
|
||||
import unittest
|
||||
from types import SimpleNamespace
|
||||
from unittest.mock import patch
|
||||
|
||||
from app.rules import (
|
||||
RuleActionResult,
|
||||
@@ -25,10 +28,36 @@ class RuleManagerTests(unittest.TestCase):
|
||||
suricata_local_rules=local,
|
||||
suricata_extra_rules_glob=os.path.join(td, "*.rules"),
|
||||
suricata_config="/etc/suricata/suricata.yaml",
|
||||
suricata_output_config="/opt/ids/suricata/ids-output.yaml",
|
||||
suricata_home_net="[192.168.0.0/16]",
|
||||
suricata_persist_lib_dir=os.path.join(td, "lib", "suricata"),
|
||||
)
|
||||
return RuleManager(cfg, pid_provider=lambda: None, suricata_available=False)
|
||||
|
||||
|
||||
def test_validation_copies_managed_dataset_files_next_to_rules(self):
|
||||
from unittest.mock import patch
|
||||
import subprocess
|
||||
|
||||
with tempfile.TemporaryDirectory() as td:
|
||||
manager = self.make_manager(td)
|
||||
manager.suricata_available = True
|
||||
dataset = os.path.join(td, "ti-ja4.lst")
|
||||
with open(dataset, "w", encoding="ascii") as handle:
|
||||
handle.write("dDEzX3Rlc3Q=\n")
|
||||
seen = {}
|
||||
|
||||
def fake_run(cmd, **kwargs):
|
||||
rules_glob = cmd[cmd.index("-s") + 1]
|
||||
rules_dir = os.path.dirname(rules_glob)
|
||||
seen["dataset"] = open(os.path.join(rules_dir, "ti-ja4.lst"), encoding="ascii").read().strip()
|
||||
return subprocess.CompletedProcess(cmd, 0, stdout="ok")
|
||||
|
||||
with patch("app.rules.subprocess.run", side_effect=fake_run):
|
||||
result = manager.validate("", "")
|
||||
self.assertTrue(result.ok)
|
||||
self.assertEqual(seen["dataset"], "dDEzX3Rlc3Q=")
|
||||
|
||||
def test_scoped_suppression_uses_source_ip(self):
|
||||
with tempfile.TemporaryDirectory() as td:
|
||||
manager = self.make_manager(td)
|
||||
@@ -83,6 +112,86 @@ Enabled sources:
|
||||
{"oisf/trafficid", "sslbl/ssl-fp-blacklist"},
|
||||
)
|
||||
|
||||
def test_accepts_single_segment_official_source_names(self):
|
||||
self.assertIsNotNone(RuleManager.SOURCE_NAME_RE.fullmatch("pawpatrules"))
|
||||
output = """
|
||||
Enabled sources:
|
||||
- pawpatrules
|
||||
- oisf/trafficid
|
||||
"""
|
||||
self.assertEqual(_parse_enabled_sources(output), {"pawpatrules", "oisf/trafficid"})
|
||||
|
||||
def test_suricata_update_commands_use_persistent_data_directory(self):
|
||||
with tempfile.TemporaryDirectory() as td:
|
||||
manager = self.make_manager(td)
|
||||
manager.suricata_available = True
|
||||
with patch("app.rules.subprocess.run") as run:
|
||||
run.return_value = subprocess.CompletedProcess([], 0, stdout="ok")
|
||||
manager._run_suricata_update(["enable-source", "oisf/trafficid"], timeout=10)
|
||||
command = run.call_args.args[0]
|
||||
self.assertEqual(command[:3], ["suricata-update", "enable-source", "oisf/trafficid"])
|
||||
self.assertEqual(command[-2:], ["-D", os.path.join(td, "lib", "suricata")])
|
||||
|
||||
def test_source_queue_enables_many_then_rebuilds_once(self):
|
||||
with tempfile.TemporaryDirectory() as td:
|
||||
manager = self.make_manager(td)
|
||||
manager.suricata_available = True
|
||||
enabled = []
|
||||
rebuilds = []
|
||||
manager.source_catalog = lambda: {
|
||||
"ok": True,
|
||||
"sources": [
|
||||
{"name": "oisf/trafficid", "enabled": False, "parameters": []},
|
||||
{"name": "sslbl/ssl-fp-blacklist", "enabled": False, "parameters": []},
|
||||
],
|
||||
}
|
||||
|
||||
def fake_update(args, timeout):
|
||||
enabled.append(list(args))
|
||||
return subprocess.CompletedProcess(args, 0, stdout="enabled")
|
||||
|
||||
manager._run_suricata_update = fake_update
|
||||
manager._run_vendor_update_unlocked = lambda: (rebuilds.append(True) or RuleActionResult(True, "rebuilt"))
|
||||
result = manager.queue_sources(["oisf/trafficid", "sslbl/ssl-fp-blacklist"])
|
||||
self.assertTrue(result.ok)
|
||||
deadline = time.time() + 2
|
||||
while manager.source_queue_status()["status"] in {"queued", "running"} and time.time() < deadline:
|
||||
time.sleep(0.01)
|
||||
status = manager.source_queue_status()
|
||||
self.assertEqual(status["status"], "completed")
|
||||
self.assertEqual(status["completed"], 2)
|
||||
self.assertEqual(status["failed"], 0)
|
||||
self.assertEqual(len(rebuilds), 1)
|
||||
self.assertEqual(
|
||||
enabled,
|
||||
[
|
||||
["enable-source", "oisf/trafficid"],
|
||||
["enable-source", "sslbl/ssl-fp-blacklist"],
|
||||
],
|
||||
)
|
||||
|
||||
def test_adaptive_threshold_uses_global_limit_and_snapshot_is_persistent(self):
|
||||
with tempfile.TemporaryDirectory() as td:
|
||||
manager = self.make_manager(td)
|
||||
captured = {}
|
||||
|
||||
def replace(content):
|
||||
captured["content"] = content
|
||||
return RuleActionResult(True, "saved")
|
||||
|
||||
manager.replace_threshold_config = replace
|
||||
result = manager.add_threshold(2222, threshold_type="limit", track="by_src", count=3, seconds=60)
|
||||
self.assertTrue(result.ok)
|
||||
self.assertIn("threshold gen_id 1, sig_id 2222, type limit, track by_src, count 3, seconds 60", captured["content"])
|
||||
|
||||
with open(manager.config.suricata_custom_rules, "w", encoding="utf-8") as handle:
|
||||
handle.write('alert ip any any -> any any (msg:"snapshot"; sid:9900002;)\n')
|
||||
snap = manager.create_snapshot("unit")
|
||||
self.assertTrue(snap.ok)
|
||||
snapshots = manager.list_snapshots()
|
||||
self.assertEqual(len(snapshots), 1)
|
||||
self.assertTrue(snapshots[0]["id"].endswith(".tar.gz"))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
||||
Reference in New Issue
Block a user