Initial curated EventLens source from 0d80d3b38dfb817285481665b9e71e4b8a0656a0
This commit is contained in:
commit
663ea8c829
85 files changed
+12395
No files matched your search
@@ -0,0 +1,88 @@
|
||||
from datetime import UTC, datetime, timedelta
|
||||
|
||||
import pytest
|
||||
|
||||
from app import parser
|
||||
from app.correlate import correlate
|
||||
from app.models import NormalizedEvent
|
||||
from app.normalize import normalize_record
|
||||
from app.parser import EvtxParseError, parse_evtx_bytes
|
||||
|
||||
|
||||
def test_corrupt_evtx_has_a_generic_error_without_parser_details():
|
||||
with pytest.raises(EvtxParseError, match="rejected the file"):
|
||||
parse_evtx_bytes(b"not-an-evtx")
|
||||
|
||||
|
||||
def test_oversized_parser_record_is_skipped_before_json_expansion(monkeypatch):
|
||||
class FakeParser:
|
||||
def __init__(self, *_args, **_kwargs):
|
||||
pass
|
||||
|
||||
def records_json(self):
|
||||
yield {"event_record_id": "9" * 5000, "data": "x" * (parser.MAX_RECORD_JSON_BYTES + 1)}
|
||||
|
||||
monkeypatch.setattr(parser, "PyEvtxParser", FakeParser)
|
||||
result = parse_evtx_bytes(b"ElfFile\x00synthetic")
|
||||
assert result.events == []
|
||||
assert result.issues[0].code == "record_json_limit_exceeded"
|
||||
assert result.issues[0].record_id is None
|
||||
|
||||
|
||||
def test_normalization_bounds_nested_and_textual_values():
|
||||
payload = {
|
||||
"Event": {
|
||||
"System": {
|
||||
"Provider": {"#attributes": {"Name": "P" * 500}},
|
||||
"EventID": 1,
|
||||
"Channel": "C" * 500,
|
||||
"Computer": "H" * 500,
|
||||
"TimeCreated": {"#attributes": {"SystemTime": "2026-09-09T08:00:00Z"}},
|
||||
},
|
||||
"EventData": {"value": "V" * 5000},
|
||||
}
|
||||
}
|
||||
event = normalize_record(payload, record_ordinal=1)
|
||||
assert len(event.provider) == 256
|
||||
assert len(event.channel) == 256
|
||||
assert len(event.computer) == 256
|
||||
assert len(event.fields["EventData.value"]) == 1000
|
||||
|
||||
|
||||
def test_records_without_event_record_ids_get_distinct_deterministic_ids():
|
||||
payload = {
|
||||
"Event": {
|
||||
"System": {
|
||||
"Provider": "Synthetic",
|
||||
"EventID": 1,
|
||||
"TimeCreated": {"#attributes": {"SystemTime": "2026-09-09T08:00:00Z"}},
|
||||
}
|
||||
}
|
||||
}
|
||||
first = normalize_record(payload, record_timestamp="2026-09-09T08:00:00Z", record_ordinal=0)
|
||||
second = normalize_record(payload, record_timestamp="2026-09-09T08:00:00Z", record_ordinal=1)
|
||||
repeat = normalize_record(payload, record_timestamp="2026-09-09T08:00:00Z", record_ordinal=0)
|
||||
assert first.id != second.id
|
||||
assert first.id == repeat.id
|
||||
|
||||
|
||||
def test_correlation_does_not_bridge_beyond_rule_window():
|
||||
start = datetime(2026, 9, 9, 8, 0, tzinfo=UTC)
|
||||
events = [
|
||||
NormalizedEvent(
|
||||
id=str(index),
|
||||
timestamp=start + timedelta(seconds=offset),
|
||||
provider="Microsoft-Windows-DNS-Client",
|
||||
event_id=1014,
|
||||
level="warning",
|
||||
channel="System",
|
||||
computer="LAB-PC",
|
||||
category="network",
|
||||
summary="DNS timeout",
|
||||
)
|
||||
for index, offset in enumerate((0, 119, 238))
|
||||
]
|
||||
incidents = correlate(events)
|
||||
assert len(incidents) == 2
|
||||
assert [incident.original_count for incident in incidents] == [2, 1]
|
||||
assert all(incident.end - incident.start <= timedelta(seconds=120) for incident in incidents)
|
||||
Reference in new issue
Block a user