Skip to content

Commit bdaaf14

Browse files
authored
Merge branch 'main' into dependabot/pip/setuptools-gte-69.5.1-and-lt-74.0.0
2 parents c23f129 + 3e4532a commit bdaaf14

File tree

16 files changed

+143
-1186
lines changed

16 files changed

+143
-1186
lines changed

contentctl/actions/build.py

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
from contentctl.input.director import Director, DirectorOutputDto
99
from contentctl.output.conf_output import ConfOutput
1010
from contentctl.output.conf_writer import ConfWriter
11-
from contentctl.output.ba_yml_output import BAYmlOutput
1211
from contentctl.output.api_json_output import ApiJsonOutput
1312
from contentctl.output.data_source_writer import DataSourceWriter
1413
from contentctl.objects.lookup import Lookup
@@ -86,17 +85,4 @@ def execute(self, input_dto: BuildInputDto) -> DirectorOutputDto:
8685

8786
print(f"Build of '{input_dto.config.app.title}' API successful to {input_dto.config.getAPIPath()}")
8887

89-
if input_dto.config.build_ssa:
90-
91-
srs_path = input_dto.config.getSSAPath() / 'srs'
92-
complex_path = input_dto.config.getSSAPath() / 'complex'
93-
shutil.rmtree(srs_path, ignore_errors=True)
94-
shutil.rmtree(complex_path, ignore_errors=True)
95-
srs_path.mkdir(parents=True)
96-
complex_path.mkdir(parents=True)
97-
ba_yml_output = BAYmlOutput()
98-
ba_yml_output.writeObjects(input_dto.director_output_dto.ssa_detections, str(input_dto.config.getSSAPath()))
99-
100-
print(f"Build of 'SSA' successful to {input_dto.config.getSSAPath()}")
101-
10288
return input_dto.director_output_dto

contentctl/actions/convert.py

Lines changed: 0 additions & 25 deletions
This file was deleted.

contentctl/actions/detection_testing/infrastructures/DetectionTestingInfrastructure.py

Lines changed: 60 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1060,15 +1060,20 @@ def retry_search_until_timeout(
10601060
results = JSONResultsReader(job.results(output_mode="json"))
10611061

10621062
# Consolidate a set of the distinct observable field names
1063-
observable_fields_set = set([o.name for o in detection.tags.observable])
1063+
observable_fields_set = set([o.name for o in detection.tags.observable]) # keeping this around for later
1064+
risk_object_fields_set = set([o.name for o in detection.tags.observable if "Victim" in o.role ]) # just the "Risk Objects"
1065+
threat_object_fields_set = set([o.name for o in detection.tags.observable if "Attacker" in o.role]) # just the "threat objects"
10641066

10651067
# Ensure the search had at least one result
10661068
if int(job.content.get("resultCount", "0")) > 0:
10671069
# Initialize the test result
10681070
test.result = UnitTestResult()
10691071

10701072
# Initialize the collection of fields that are empty that shouldn't be
1073+
present_threat_objects: set[str] = set()
10711074
empty_fields: set[str] = set()
1075+
1076+
10721077

10731078
# Filter out any messages in the results
10741079
for result in results:
@@ -1077,30 +1082,50 @@ def retry_search_until_timeout(
10771082

10781083
# If not a message, it is a dict and we will process it
10791084
results_fields_set = set(result.keys())
1085+
# Guard against first events (relevant later)
10801086

1081-
# Identify any observable fields that are not available in the results
1082-
missing_fields = observable_fields_set - results_fields_set
1083-
if len(missing_fields) > 0:
1087+
# Identify any risk object fields that are not available in the results
1088+
missing_risk_objects = risk_object_fields_set - results_fields_set
1089+
if len(missing_risk_objects) > 0:
10841090
# Report a failure in such cases
1085-
e = Exception(f"The observable field(s) {missing_fields} are missing in the detection results")
1091+
e = Exception(f"The observable field(s) {missing_risk_objects} are missing in the detection results")
10861092
test.result.set_job_content(
10871093
job.content,
10881094
self.infrastructure,
1089-
TestResultStatus.ERROR,
1095+
TestResultStatus.FAIL,
10901096
exception=e,
10911097
duration=time.time() - search_start_time,
10921098
)
10931099

1094-
return
1100+
return
10951101

1096-
# If we find one or more fields that contain the string "null" then they were
1102+
# If we find one or more risk object fields that contain the string "null" then they were
10971103
# not populated and we should throw an error. This can happen if there is a typo
10981104
# on a field. In this case, the field will appear but will not contain any values
1099-
current_empty_fields = set()
1105+
current_empty_fields: set[str] = set()
1106+
11001107
for field in observable_fields_set:
11011108
if result.get(field, 'null') == 'null':
1102-
current_empty_fields.add(field)
1103-
1109+
if field in risk_object_fields_set:
1110+
e = Exception(f"The risk object field {field} is missing in at least one result.")
1111+
test.result.set_job_content(
1112+
job.content,
1113+
self.infrastructure,
1114+
TestResultStatus.FAIL,
1115+
exception=e,
1116+
duration=time.time() - search_start_time,
1117+
)
1118+
return
1119+
else:
1120+
if field in threat_object_fields_set:
1121+
current_empty_fields.add(field)
1122+
else:
1123+
if field in threat_object_fields_set:
1124+
present_threat_objects.add(field)
1125+
continue
1126+
1127+
1128+
11041129
# If everything succeeded up until now, and no empty fields are found in the
11051130
# current result, then the search was a success
11061131
if len(current_empty_fields) == 0:
@@ -1114,21 +1139,32 @@ def retry_search_until_timeout(
11141139

11151140
else:
11161141
empty_fields = empty_fields.union(current_empty_fields)
1117-
1118-
# Report a failure if there were empty fields in all results
1119-
e = Exception(
1120-
f"One or more required observable fields {empty_fields} contained 'null' values. Is the "
1121-
"data being parsed correctly or is there an error in the naming of a field?"
1142+
1143+
1144+
missing_threat_objects = threat_object_fields_set - present_threat_objects
1145+
# Report a failure if there were empty fields in a threat object in all results
1146+
if len(missing_threat_objects) > 0:
1147+
e = Exception(
1148+
f"One or more required threat object fields {missing_threat_objects} contained 'null' values in all events. "
1149+
"Is the data being parsed correctly or is there an error in the naming of a field?"
11221150
)
1123-
test.result.set_job_content(
1124-
job.content,
1125-
self.infrastructure,
1126-
TestResultStatus.ERROR,
1127-
exception=e,
1128-
duration=time.time() - search_start_time,
1129-
)
1151+
test.result.set_job_content(
1152+
job.content,
1153+
self.infrastructure,
1154+
TestResultStatus.FAIL,
1155+
exception=e,
1156+
duration=time.time() - search_start_time,
1157+
)
1158+
return
1159+
11301160

1131-
return
1161+
test.result.set_job_content(
1162+
job.content,
1163+
self.infrastructure,
1164+
TestResultStatus.PASS,
1165+
duration=time.time() - search_start_time,
1166+
)
1167+
return
11321168

11331169
else:
11341170
# Report a failure if there were no results at all

contentctl/actions/validate.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@ def execute(self, input_dto: validate) -> DirectorOutputDto:
3030
[],
3131
[],
3232
[],
33-
[],
3433
)
3534

3635
director = Director(director_output_dto)

contentctl/input/backend_splunk_ba.py

Lines changed: 0 additions & 144 deletions
This file was deleted.

0 commit comments

Comments
 (0)