#!/usr/bin/env python3 import importlib.util import sys from pathlib import Path MODULE_PATH = Path(__file__).with_name("dlp-health-check.py") SPEC = importlib.util.spec_from_file_location("dlp_health_check", MODULE_PATH) MODULE = importlib.util.module_from_spec(SPEC) sys.modules[SPEC.name] = MODULE SPEC.loader.exec_module(MODULE) def test_endpoint_signals_ok_when_no_active_managed_hosts(monkeypatch): buckets = { "aw-worktime-sessions_SHARKON2025": {"metadata": {"end": "2026-05-30T12:00:00Z"}}, "aw-dlp-endpoint-signals_SHARKON2025": {"metadata": {"end": "2026-05-30T07:00:00Z"}}, } monkeypatch.setattr(MODULE, "_now_utc", lambda: MODULE._parse_ts("2026-05-30T12:00:10Z")) monkeypatch.setattr( MODULE, "_http_json", lambda url: [{"timestamp": "2026-05-30T12:00:00Z", "data": {"active": False}}] if "aw-worktime-sessions_SHARKON2025/events" in url else [], ) report = MODULE.HealthReport() MODULE.check_endpoint_signal_buckets(report, "http://127.0.0.1:5600/api/0", buckets, 900) result = report.results[0] assert result.name == "buckets:endpoint-signals" assert result.status == "ok" assert result.summary == "no active managed hosts require endpoint-signals freshness" assert result.details["ignored_inactive"] == ["aw-dlp-endpoint-signals_SHARKON2025"] def test_endpoint_self_test_metrics_reports_transport_counters(monkeypatch): buckets = {"aw-dlp-endpoint-signals_SHARKON2025": {"metadata": {"end": "2026-05-30T12:00:00Z"}}} monkeypatch.setattr(MODULE, "_now_utc", lambda: MODULE._parse_ts("2026-05-30T12:01:00Z")) monkeypatch.setattr( MODULE, "_http_json", lambda url, **kwargs: [ { "timestamp": "2026-05-30T11:59:00Z", "data": { "signalType": "self_test", "queueDepth": 8, "eventsEnqueued": 100, "eventsFlushed": 92, "sendFailures": 0, }, }, { "timestamp": "2026-05-30T12:00:30Z", "data": { "signalType": "self_test", "queueDepth": "3", "eventsEnqueued": "120", "eventsFlushed": "117", "sendFailures": "0", }, }, ], ) report = MODULE.HealthReport() MODULE.check_endpoint_self_test_metrics(report, "http://127.0.0.1:5600/api/0", buckets) result = report.results[0] assert result.name == "endpoint-self-test-metrics" assert result.status == "ok" latest = result.details["latest_self_tests"][0] assert latest["bucket"] == "aw-dlp-endpoint-signals_SHARKON2025" assert latest["timestamp"] == "2026-05-30T12:00:30Z" assert latest["age_seconds"] == 30 assert latest["queueDepth"] == 3 assert latest["eventsEnqueued"] == 120 assert latest["eventsFlushed"] == 117 assert latest["sendFailures"] == 0 assert latest["sendFailuresDelta"] == 0 def test_endpoint_self_test_metrics_warns_on_transport_counters(monkeypatch): buckets = {"aw-dlp-endpoint-signals_SHARKON2025": {"metadata": {"end": "2026-05-30T12:00:00Z"}}} monkeypatch.setattr(MODULE, "_now_utc", lambda: MODULE._parse_ts("2026-05-30T12:01:00Z")) monkeypatch.setattr( MODULE, "_http_json", lambda url, **kwargs: [ { "timestamp": "2026-05-30T12:00:30Z", "data": { "signalType": "self_test", "queueDepth": 101, "eventsEnqueued": 120, "eventsFlushed": 19, "sendFailures": 1, }, } ], ) report = MODULE.HealthReport() MODULE.check_endpoint_self_test_metrics( report, "http://127.0.0.1:5600/api/0", buckets, queue_warn_depth=100, send_failure_warn_count=1, ) result = report.results[0] assert result.status == "warn" assert result.summary == "endpoint transport counters outside thresholds" assert result.details["warnings"] == [ {"bucket": "aw-dlp-endpoint-signals_SHARKON2025", "metric": "queueDepth", "value": 101, "threshold": 100}, { "bucket": "aw-dlp-endpoint-signals_SHARKON2025", "metric": "sendFailuresDelta", "value": 1, "current": 1, "previous": None, "threshold": 1, }, ] def test_file_operations_runtime_reports_health_and_latest_operations(monkeypatch): buckets = {"aw-file-operations_SHARKON2025": {"metadata": {"end": "2026-05-30T12:00:00Z"}}} monkeypatch.setattr(MODULE, "_now_utc", lambda: MODULE._parse_ts("2026-05-30T12:01:00Z")) monkeypatch.setattr( MODULE, "_http_json", lambda url: [ { "timestamp": "2026-05-30T12:00:30Z", "data": { "signalType": "collector_health", "queueDepth": "0", "eventsEnqueued": "5", "eventsFlushed": "5", "sendFailures": "0", "username": "USER1", "hostname": "SHARKON2025", "sessionId": "3", }, }, { "timestamp": "2026-05-30T12:00:20Z", "data": { "operation": "Created", "path": "C:\\Users\\USER1\\Downloads\\report.zip", "extension": ".zip", "archiveHint": True, "username": "USER1", "hostname": "SHARKON2025", "size": "42", }, }, ], ) report = MODULE.HealthReport() MODULE.check_file_operations_runtime(report, "http://127.0.0.1:5600/api/0", buckets) result = report.results[0] assert result.name == "file-operations-runtime" assert result.status == "ok" assert result.details["latest_health"][0]["queueDepth"] == 0 assert result.details["latest_health"][0]["eventsEnqueued"] == 5 assert result.details["latest_health"][0]["sendFailuresDelta"] == 0 latest_op = result.details["latest_operations"][0] assert latest_op["operation"] == "Created" assert latest_op["extension"] == ".zip" assert latest_op["archiveHint"] is True assert latest_op["path_tail"] == "Downloads/report.zip" assert latest_op["size"] == 42 assert result.details["sampled"][0]["operation_counts"] == {"Created": 1} def test_file_operations_runtime_warns_on_transport_counters(monkeypatch): buckets = {"aw-file-operations_SHARKON2025": {"metadata": {"end": "2026-05-30T12:00:00Z"}}} monkeypatch.setattr(MODULE, "_now_utc", lambda: MODULE._parse_ts("2026-05-30T12:01:00Z")) monkeypatch.setattr( MODULE, "_http_json", lambda url: [ { "timestamp": "2026-05-30T12:00:30Z", "data": { "signalType": "collector_health", "queueDepth": 101, "eventsEnqueued": 5, "eventsFlushed": 2, "sendFailures": 1, "username": "USER1", "hostname": "SHARKON2025", "sessionId": 3, }, } ], ) report = MODULE.HealthReport() MODULE.check_file_operations_runtime( report, "http://127.0.0.1:5600/api/0", buckets, queue_warn_depth=100, send_failure_warn_count=1, ) result = report.results[0] assert result.status == "warn" assert result.summary == "file-operations runtime counters outside expectations" assert result.details["warnings"] == [ {"bucket": "aw-file-operations_SHARKON2025", "metric": "queueDepth", "value": 101, "threshold": 100}, { "bucket": "aw-file-operations_SHARKON2025", "metric": "sendFailuresDelta", "value": 1, "current": 1, "previous": None, "threshold": 1, }, ] def test_endpoint_send_failures_uses_delta_baseline(monkeypatch): buckets = {"aw-dlp-endpoint-signals_SHARKON2025": {"metadata": {"end": "2026-05-30T12:00:00Z"}}} state = {"counters": {}} monkeypatch.setattr(MODULE, "_now_utc", lambda: MODULE._parse_ts("2026-05-30T12:01:00Z")) values = [12, 12, 13] def fake_http(url, **kwargs): value = values.pop(0) return [ { "timestamp": "2026-05-30T12:00:30Z", "data": { "signalType": "self_test", "queueDepth": 0, "eventsEnqueued": 120, "eventsFlushed": 117, "sendFailures": value, }, } ] monkeypatch.setattr(MODULE, "_http_json", fake_http) first = MODULE.HealthReport() MODULE.check_endpoint_self_test_metrics(first, "http://127.0.0.1:5600/api/0", buckets, counter_state=state) assert first.results[0].status == "ok" assert first.results[0].details["latest_self_tests"][0]["sendFailuresPrevious"] is None assert first.results[0].details["latest_self_tests"][0]["sendFailuresDelta"] == 0 second = MODULE.HealthReport() MODULE.check_endpoint_self_test_metrics(second, "http://127.0.0.1:5600/api/0", buckets, counter_state=state) assert second.results[0].status == "ok" assert second.results[0].details["latest_self_tests"][0]["sendFailuresPrevious"] == 12 assert second.results[0].details["latest_self_tests"][0]["sendFailuresDelta"] == 0 third = MODULE.HealthReport() MODULE.check_endpoint_self_test_metrics(third, "http://127.0.0.1:5600/api/0", buckets, counter_state=state) assert third.results[0].status == "warn" assert third.results[0].details["warnings"] == [ { "bucket": "aw-dlp-endpoint-signals_SHARKON2025", "metric": "sendFailuresDelta", "value": 1, "current": 13, "previous": 12, "threshold": 1, } ] def test_file_operations_send_failures_uses_delta_baseline(monkeypatch): buckets = {"aw-file-operations_SHARKON2025": {"metadata": {"end": "2026-05-30T12:00:00Z"}}} state = {"counters": {}} monkeypatch.setattr(MODULE, "_now_utc", lambda: MODULE._parse_ts("2026-05-30T12:01:00Z")) values = [28, 28, 29] def fake_http(url, **kwargs): value = values.pop(0) return [ { "timestamp": "2026-05-30T12:00:30Z", "data": { "signalType": "collector_health", "queueDepth": 0, "eventsEnqueued": 120, "eventsFlushed": 117, "sendFailures": value, }, } ] monkeypatch.setattr(MODULE, "_http_json", fake_http) first = MODULE.HealthReport() MODULE.check_file_operations_runtime(first, "http://127.0.0.1:5600/api/0", buckets, counter_state=state) assert first.results[0].status == "ok" assert first.results[0].details["latest_health"][0]["sendFailuresPrevious"] is None assert first.results[0].details["latest_health"][0]["sendFailuresDelta"] == 0 second = MODULE.HealthReport() MODULE.check_file_operations_runtime(second, "http://127.0.0.1:5600/api/0", buckets, counter_state=state) assert second.results[0].status == "ok" assert second.results[0].details["latest_health"][0]["sendFailuresPrevious"] == 28 assert second.results[0].details["latest_health"][0]["sendFailuresDelta"] == 0 third = MODULE.HealthReport() MODULE.check_file_operations_runtime(third, "http://127.0.0.1:5600/api/0", buckets, counter_state=state) assert third.results[0].status == "warn" assert third.results[0].details["warnings"] == [ { "bucket": "aw-file-operations_SHARKON2025", "metric": "sendFailuresDelta", "value": 1, "current": 29, "previous": 28, "threshold": 1, } ] def test_incident_runtime_reports_counts_and_latest_real_incidents(monkeypatch): buckets = {"aw-dlp-incidents_SHARKON2025": {"metadata": {"end": "2026-05-30T12:00:00Z"}}} monkeypatch.setattr(MODULE, "_now_utc", lambda: MODULE._parse_ts("2026-05-30T12:01:00Z")) monkeypatch.setattr( MODULE, "_http_json", lambda url, **kwargs: [ { "timestamp": "2026-05-30T12:00:30Z", "data": { "ruleId": "usb-archive-copy", "severity": "high", "action": "alert", "message": "Archive copied to removable device with a long message that should not leak full raw content.", "username": "USER1", "hostname": "SHARKON2025", "source": "endpoint", }, }, { "timestamp": "2026-05-30T12:00:00Z", "data": { "ruleId": "selftest-dlp-incident", "severity": "low", "action": "alert", "message": "Self-test DLP incident from validation", "signalType": "self_test", "source": "self-test", }, }, ], ) report = MODULE.HealthReport() MODULE.check_incident_runtime(report, "http://127.0.0.1:5600/api/0", buckets, sample_limit=20) result = report.results[0] assert result.name == "incident-runtime" assert result.status == "ok" assert result.summary == "1 real incidents in sampled events" assert result.details["totals"] == {"sampled_events": 2, "real_incidents": 1, "self_tests": 1} assert result.details["severity_counts"] == {"high": 1} assert result.details["action_counts"] == {"alert": 1} assert result.details["rule_counts"] == {"usb-archive-copy": 1} latest = result.details["latest_incidents"][0] assert latest["age_seconds"] == 30 assert latest["ruleId"] == "usb-archive-copy" assert latest["message_excerpt"].endswith(".") def test_incident_runtime_defaults_to_metadata_without_event_sampling(monkeypatch): buckets = {"aw-dlp-incidents_SHARKON2025": {"metadata": {"end": "2026-05-30T12:00:00Z"}}} monkeypatch.setattr(MODULE, "_now_utc", lambda: MODULE._parse_ts("2026-05-30T12:01:00Z")) def fail_if_called(url, **kwargs): raise AssertionError("event sampling should stay disabled") monkeypatch.setattr(MODULE, "_http_json", fail_if_called) report = MODULE.HealthReport() MODULE.check_incident_runtime(report, "http://127.0.0.1:5600/api/0", buckets, sample_limit=0) result = report.results[0] assert result.name == "incident-runtime" assert result.status == "ok" assert result.summary == "incident event sampling disabled" assert result.details["metadata"] == [ { "bucket": "aw-dlp-incidents_SHARKON2025", "end": "2026-05-30T12:00:00Z", "age_seconds": 60, } ] def test_incident_runtime_warns_on_read_failure(monkeypatch): buckets = {"aw-dlp-incidents_SHARKON2025": {"metadata": {"end": "2026-05-30T12:00:00Z"}}} def fail_http(url, **kwargs): raise RuntimeError("timeout") monkeypatch.setattr(MODULE, "_http_json", fail_http) report = MODULE.HealthReport() MODULE.check_incident_runtime(report, "http://127.0.0.1:5600/api/0", buckets, sample_limit=20) result = report.results[0] assert result.name == "incident-runtime" assert result.status == "warn" assert result.summary == "1 incident buckets failed to sample" assert result.details["read_failed"] == [{"bucket": "aw-dlp-incidents_SHARKON2025", "error": "timeout"}]