From eda095ed94ed8645be53ac99d4d8fc6a2d78161d Mon Sep 17 00:00:00 2001 From: linuxdaemon Date: Tue, 22 Aug 2023 16:40:44 -0400 Subject: [PATCH] Add next steps for notables This allows the configuration of the Next steps field for a notable --- contentctl/input/detection_builder.py | 10 ++++++++++ contentctl/input/director.py | 1 + contentctl/input/new_content_generator.py | 1 + contentctl/input/new_content_questions.py | 6 ++++++ contentctl/objects/detection_tags.py | 1 + .../output/templates/savedsearches_detections.j2 | 1 + 6 files changed, 20 insertions(+) diff --git a/contentctl/input/detection_builder.py b/contentctl/input/detection_builder.py index bbd8d684..bffc08b5 100644 --- a/contentctl/input/detection_builder.py +++ b/contentctl/input/detection_builder.py @@ -1,3 +1,4 @@ +import json import sys import re import os @@ -6,6 +7,7 @@ from contentctl.input.yml_reader import YmlReader from contentctl.objects.detection import Detection +from contentctl.objects.detection_tags import DetectionTags from contentctl.objects.security_content_object import SecurityContentObject from contentctl.objects.macro import Macro from contentctl.objects.mitre_attack_enrichment import MitreAttackEnrichment @@ -24,6 +26,14 @@ def setObject(self, path: str) -> None: self.security_content_obj = Detection.parse_obj(yml_dict) self.security_content_obj.source = os.path.split(os.path.dirname(self.security_content_obj.file_path))[-1] + def addNextSteps(self): + if self.security_content_obj: + tags: DetectionTags = self.security_content_obj.tags + obj = { + "version": 1, + "data": tags.next_steps, + } + tags.next_steps = json.dumps(obj) def addDeployment(self, detection_configuration: ConfigDetectionConfiguration) -> None: if self.security_content_obj: diff --git a/contentctl/input/director.py b/contentctl/input/director.py index 7dbeadda..a8522ec7 100644 --- a/contentctl/input/director.py +++ b/contentctl/input/director.py @@ -186,6 +186,7 @@ def createSecurityContent(self, type: SecurityContentType) -> None: def constructDetection(self, builder: DetectionBuilder, file_path: str) -> None: builder.reset() builder.setObject(file_path) + builder.addNextSteps() builder.addDeployment(self.input_dto.config.detection_configuration) builder.addKillChainPhase() builder.addCIS() diff --git a/contentctl/input/new_content_generator.py b/contentctl/input/new_content_generator.py index 5e6b4ee1..f019662e 100644 --- a/contentctl/input/new_content_generator.py +++ b/contentctl/input/new_content_generator.py @@ -62,6 +62,7 @@ def execute(self, input_dto: NewContentGeneratorInputDto) -> None: self.output_dto.obj['tags']['security_domain'] = answers['security_domain'] #self.output_dto.obj['source'] = answers['detection_kind'] + self.output_dto.obj['tags']['next_steps'] = answers['next_steps'] elif input_dto.type == SecurityContentType.stories: questions = NewContentQuestions.get_questions_story() diff --git a/contentctl/input/new_content_questions.py b/contentctl/input/new_content_questions.py index b13cdf61..07bb4a05 100644 --- a/contentctl/input/new_content_questions.py +++ b/contentctl/input/new_content_questions.py @@ -91,6 +91,12 @@ def get_questions_detection(self) -> list: ], 'default': 'endpoint' }, + { + 'type': 'text', + 'message': 'Next steps', + 'name': 'next_steps', + 'multiline': True, + }, ] return questions diff --git a/contentctl/objects/detection_tags.py b/contentctl/objects/detection_tags.py index 18fd08d9..ce4a6105 100644 --- a/contentctl/objects/detection_tags.py +++ b/contentctl/objects/detection_tags.py @@ -28,6 +28,7 @@ class DetectionTags(BaseModel): atomic_guid: list = None drilldown_search: str = None manual_test: str = None + next_steps: str = None # enrichment diff --git a/contentctl/output/templates/savedsearches_detections.j2 b/contentctl/output/templates/savedsearches_detections.j2 index 6dcf7ecb..148e3d17 100644 --- a/contentctl/output/templates/savedsearches_detections.j2 +++ b/contentctl/output/templates/savedsearches_detections.j2 @@ -71,6 +71,7 @@ action.notable.param.rule_description = {{ detection.deployment.notable.rule_des action.notable.param.rule_title = {{ detection.deployment.notable.rule_title | custom_jinja2_enrichment_filter(detection) }} action.notable.param.security_domain = {{ detection.tags.security_domain }} action.notable.param.severity = high +action.notable.param.next_steps = {{ detection.tags.next_steps }} {% endif %} {% if detection.deployment.email.to is defined %} action.email.subject.alert = {{ detection.deployment.email.subject | custom_jinja2_enrichment_filter(detection) }}