mirror of
https://github.com/splunk/security_content
synced 2026-06-08 17:32:49 +00:00
add content_organizer
This commit is contained in:
@@ -27,5 +27,9 @@ class Adapter(abc.ABC):
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def writeObjects(self, objects: list) -> None:
|
||||
def writeObjectsInPlace(self, objects: list) -> None:
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def writeObjects(self, objects: list, security_content_folder: str) -> None:
|
||||
pass
|
||||
@@ -23,7 +23,7 @@ class ContentChanger:
|
||||
converter_func = getattr(self, input_dto.converter_func_name)
|
||||
converter_func(objects)
|
||||
|
||||
input_dto.adapter.writeObjects(objects)
|
||||
input_dto.adapter.writeObjectsInPlace(objects)
|
||||
|
||||
|
||||
# Define Converter Functions here
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
|
||||
from dataclasses import dataclass
|
||||
|
||||
from contentctl_core.application.factory.object_factory import ObjectFactory, ObjectFactoryInputDto
|
||||
from contentctl_core.application.adapter.adapter import Adapter
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class ContentOrganizerInputDto:
|
||||
adapter : Adapter
|
||||
factory_input_dto : ObjectFactoryInputDto
|
||||
output_path : str
|
||||
|
||||
|
||||
class ContentOrganizer:
|
||||
|
||||
def execute(self, input_dto: ContentOrganizerInputDto) -> None:
|
||||
objects = list()
|
||||
factory = ObjectFactory(objects)
|
||||
factory.execute(input_dto.factory_input_dto)
|
||||
|
||||
input_dto.adapter.writeObjects(objects, input_dto.output_path)
|
||||
@@ -93,5 +93,9 @@ class ObjToConfAdapter(Adapter):
|
||||
macros)
|
||||
|
||||
|
||||
def writeObjects(self, objects: list) -> None:
|
||||
def writeObjectsInPlace(self, objects: list) -> None:
|
||||
pass
|
||||
|
||||
|
||||
def writeObjects(self, objects: list, security_content_folder: str) -> None:
|
||||
pass
|
||||
@@ -34,12 +34,30 @@ class ObjToYmlAdapter(Adapter):
|
||||
object.pop('deprecated')
|
||||
YmlWriter.writeYmlFile(file_path, object)
|
||||
|
||||
# def convertNameToFileName(self, obj: dict):
|
||||
# file_name = obj['name'] \
|
||||
# .replace(' ', '_') \
|
||||
# .replace('-','_') \
|
||||
# .replace('.','_') \
|
||||
# .replace('/','_') \
|
||||
# .lower()
|
||||
# file_name = file_name + '.yml'
|
||||
# return file_name
|
||||
def writeObjects(self, objects: list, security_content_folder: str) -> None:
|
||||
for object in objects:
|
||||
if object['type'] == 'Investigation':
|
||||
file_name = self.convertNameToFileName(object)
|
||||
file_path = object['file_path']
|
||||
object.pop('file_path')
|
||||
object.pop('deprecated')
|
||||
YmlWriter.writeYmlFile(os.path.join(security_content_folder, 'investigations', file_name))
|
||||
os.remove(file_path)
|
||||
elif object['type'] == 'Baseline':
|
||||
file_name = self.convertNameToFileName(object)
|
||||
file_path = object['file_path']
|
||||
object.pop('file_path')
|
||||
object.pop('deprecated')
|
||||
YmlWriter.writeYmlFile(os.path.join(security_content_folder, 'baselines', file_name))
|
||||
os.remove(file_path)
|
||||
|
||||
|
||||
def convertNameToFileName(self, obj: dict):
|
||||
file_name = obj['name'] \
|
||||
.replace(' ', '_') \
|
||||
.replace('-','_') \
|
||||
.replace('.','_') \
|
||||
.replace('/','_') \
|
||||
.lower()
|
||||
file_name = file_name + '.yml'
|
||||
return file_name
|
||||
+1
-1
@@ -10,7 +10,7 @@ def test_read_and_write_yml():
|
||||
'obj_to_yml_data/attempted_credential_dump_from_registry_via_reg_exe.yml')
|
||||
yml_obj = YmlReader.load_file(file_path)
|
||||
adapter = ObjToYmlAdapter()
|
||||
adapter.writeObjects([yml_obj])
|
||||
adapter.writeObjectsInPlace([yml_obj])
|
||||
|
||||
ref_file_path = os.path.join(os.path.dirname(__file__),
|
||||
'obj_to_yml_data_ref/attempted_credential_dump_from_registry_via_reg_exe.yml')
|
||||
|
||||
@@ -3,6 +3,7 @@ import argparse
|
||||
import os
|
||||
|
||||
from contentctl_core.application.use_cases.content_changer import ContentChanger, ContentChangerInputDto
|
||||
from contentctl_core.application.use_cases.content_organizer import ContentOrganizer, ContentOrganizerInputDto
|
||||
from contentctl_core.application.factory.object_factory import ObjectFactoryInputDto
|
||||
from contentctl_infrastructure.builder.security_content_object_builder import SecurityContentObjectBuilder
|
||||
from contentctl_infrastructure.builder.security_content_director import SecurityContentDirector
|
||||
@@ -69,12 +70,27 @@ def content_changer(args) -> None:
|
||||
content_changer.execute(input_dto)
|
||||
|
||||
|
||||
def content_organizer(args) -> None:
|
||||
factory_input_dto = ObjectFactoryInputDto(
|
||||
os.path.abspath(args.path),
|
||||
SecurityContentObjectBuilder(),
|
||||
SecurityContentDirector()
|
||||
)
|
||||
|
||||
input_dto = ContentOrganizerInputDto(
|
||||
ObjToYmlAdapter(),
|
||||
factory_input_dto,
|
||||
os.path.abspath(args.security_content_path)
|
||||
)
|
||||
|
||||
content_organizer = ContentOrganizer()
|
||||
content_organizer.execute(input_dto)
|
||||
|
||||
|
||||
def main(args):
|
||||
# grab arguments
|
||||
parser = argparse.ArgumentParser(
|
||||
description="Use `contentctl.py action -h` to get help with any Splunk Security Content action")
|
||||
parser.add_argument("-p", "--path", required=False, default=".",
|
||||
help="path to the Splunk Security Content. Defaults to `.`")
|
||||
parser.set_defaults(func=lambda _: parser.print_help())
|
||||
|
||||
actions_parser = parser.add_subparsers(title="Splunk Security Content actions", dest="action")
|
||||
@@ -82,6 +98,7 @@ def main(args):
|
||||
#validate_parser = actions_parser.add_parser("validate", help="Validates written content")
|
||||
#generate_parser = actions_parser.add_parser("generate", help="Generates a deployment package for different platforms (splunk_app)")
|
||||
content_changer_parser = actions_parser.add_parser("content_changer", help="Change Security Content based on defined rules")
|
||||
content_organizer_parser = actions_parser.add_parser("content_organizer", help="Organize Security Content")
|
||||
|
||||
# # new arguments
|
||||
# new_parser.add_argument("-t", "--type", required=False, type=str, default="detection",
|
||||
@@ -102,11 +119,18 @@ def main(args):
|
||||
# generate_parser.set_defaults(func=generate)
|
||||
|
||||
content_changer_parser.add_argument("-p", "--path", required=True,
|
||||
help="path to the Splunk Security Content")
|
||||
help="path to the Splunk Security Content folder")
|
||||
content_changer_parser.add_argument("-cf", "--change_function", required=True, type=str,
|
||||
help="Define a change funtion defined in bin/contentctl_core/contentctl/application/use_cases/content_changer.py")
|
||||
content_changer_parser.set_defaults(func=content_changer)
|
||||
|
||||
content_organizer_parser.add_argument("-p", "--path", required=True,
|
||||
help="path to the Splunk Security Content folder")
|
||||
content_organizer_parser.add_argument("-scp", "--security_content_path", required=True,
|
||||
help="path to the Splunk Security Content")
|
||||
content_organizer_parser.set_defaults(func=content_organizer)
|
||||
|
||||
|
||||
# # parse them
|
||||
args = parser.parse_args()
|
||||
return args.func(args)
|
||||
|
||||
Reference in New Issue
Block a user