From e7bb76fc54862c2a9bcae2bba5c95d29aae50224 Mon Sep 17 00:00:00 2001 From: Eric McGinnis Date: Wed, 28 May 2025 16:00:21 -0700 Subject: [PATCH] include tests and their info in detections_v2.json for experimental purposes --- .../detection_abstract.py | 2 ++ contentctl/objects/test_attack_data.py | 11 +++++++++++ contentctl/objects/unit_test.py | 18 +++++++++++++++--- contentctl/output/api_json_output.py | 1 + 4 files changed, 29 insertions(+), 3 deletions(-) diff --git a/contentctl/objects/abstract_security_content_objects/detection_abstract.py b/contentctl/objects/abstract_security_content_objects/detection_abstract.py index 81e8f737..cdbf909e 100644 --- a/contentctl/objects/abstract_security_content_objects/detection_abstract.py +++ b/contentctl/objects/abstract_security_content_objects/detection_abstract.py @@ -16,6 +16,7 @@ model_validator, ) +from contentctl.objects.base_test import TestType from contentctl.objects.lookup import FileBackedLookup, KVStoreLookup, Lookup from contentctl.objects.macro import Macro @@ -512,6 +513,7 @@ def serialize_model(self): "source": self.source, "nes_fields": self.nes_fields, "rba": self.rba or {}, + "tests": [t for t in self.tests if t.test_type == TestType.UNIT], } if self.deployment.alert_action.notable: model["risk_severity"] = self.severity diff --git a/contentctl/objects/test_attack_data.py b/contentctl/objects/test_attack_data.py index c06bb14b..9aa835f2 100644 --- a/contentctl/objects/test_attack_data.py +++ b/contentctl/objects/test_attack_data.py @@ -13,6 +13,7 @@ HttpUrl, ValidationInfo, field_validator, + model_serializer, ) @@ -46,3 +47,13 @@ def check_for_existence_of_attack_data_repo( raise ValueError( "config not passed to TestAttackData constructor in context" ) + + @model_serializer + def serialize_model(self) -> dict[str, str]: + return { + "data": str(self.data), + "source": self.source, + "sourcetype": self.sourcetype, + "custom_index": self.custom_index or "", + "host": self.host or "", + } diff --git a/contentctl/objects/unit_test.py b/contentctl/objects/unit_test.py index 1bfc6308..2d060b6a 100644 --- a/contentctl/objects/unit_test.py +++ b/contentctl/objects/unit_test.py @@ -1,11 +1,13 @@ from __future__ import annotations -from pydantic import Field +from typing import Any + +from pydantic import Field, model_serializer -from contentctl.objects.test_attack_data import TestAttackData -from contentctl.objects.unit_test_result import UnitTestResult from contentctl.objects.base_test import BaseTest, TestType from contentctl.objects.base_test_result import TestResultStatus +from contentctl.objects.test_attack_data import TestAttackData +from contentctl.objects.unit_test_result import UnitTestResult class UnitTest(BaseTest): @@ -32,3 +34,13 @@ def skip(self, message: str) -> None: self.result = UnitTestResult( # type: ignore message=message, status=TestResultStatus.SKIP ) + + @model_serializer + def serialize_model(self) -> dict[str, Any]: + return { + "name": self.name, + "test_type": self.test_type.value, + "attack_data": [ + attack_data.model_dump() for attack_data in self.attack_data + ], + } diff --git a/contentctl/output/api_json_output.py b/contentctl/output/api_json_output.py index dabf18fd..97dd5456 100644 --- a/contentctl/output/api_json_output.py +++ b/contentctl/output/api_json_output.py @@ -52,6 +52,7 @@ def writeDetections( "lookups", "source", "nes_fields", + "tests", ] ) )