@@ -58,7 +58,6 @@ class DirectorOutputDto:
58
58
deployments : list [Deployment ]
59
59
ssa_detections : list [SSADetection ]
60
60
data_sources : list [DataSource ]
61
- event_sources : list [EventSource ]
62
61
name_to_content_map : dict [str , SecurityContentObject ] = field (default_factory = dict )
63
62
uuid_to_content_map : dict [UUID , SecurityContentObject ] = field (default_factory = dict )
64
63
@@ -68,17 +67,19 @@ def addContentToDictMappings(self, content: SecurityContentObject):
68
67
# Since SSA detections may have the same name as ESCU detection,
69
68
# for this function we prepend 'SSA ' to the name.
70
69
content_name = f"SSA { content_name } "
70
+
71
71
if content_name in self .name_to_content_map :
72
72
raise ValueError (
73
73
f"Duplicate name '{ content_name } ' with paths:\n "
74
74
f" - { content .file_path } \n "
75
75
f" - { self .name_to_content_map [content_name ].file_path } "
76
76
)
77
- elif content .id in self .uuid_to_content_map :
77
+
78
+ if content .id in self .uuid_to_content_map :
78
79
raise ValueError (
79
80
f"Duplicate id '{ content .id } ' with paths:\n "
80
81
f" - { content .file_path } \n "
81
- f" - { self .name_to_content_map [ content_name ].file_path } "
82
+ f" - { self .uuid_to_content_map [ content . id ].file_path } "
82
83
)
83
84
84
85
if isinstance (content , Lookup ):
@@ -99,9 +100,10 @@ def addContentToDictMappings(self, content: SecurityContentObject):
99
100
self .detections .append (content )
100
101
elif isinstance (content , SSADetection ):
101
102
self .ssa_detections .append (content )
103
+ elif isinstance (content , DataSource ):
104
+ self .data_sources .append (content )
102
105
else :
103
- raise Exception (f"Unknown security content type: { type (content )} " )
104
-
106
+ raise Exception (f"Unknown security content type: { type (content )} " )
105
107
106
108
self .name_to_content_map [content_name ] = content
107
109
self .uuid_to_content_map [content .id ] = content
@@ -124,41 +126,27 @@ def execute(self, input_dto: validate) -> None:
124
126
self .createSecurityContent (SecurityContentType .stories )
125
127
self .createSecurityContent (SecurityContentType .baselines )
126
128
self .createSecurityContent (SecurityContentType .investigations )
127
- self .createSecurityContent (SecurityContentType .event_sources )
128
129
self .createSecurityContent (SecurityContentType .data_sources )
129
130
self .createSecurityContent (SecurityContentType .playbooks )
130
131
self .createSecurityContent (SecurityContentType .detections )
131
132
self .createSecurityContent (SecurityContentType .ssa_detections )
132
133
134
+
135
+ from contentctl .objects .abstract_security_content_objects .detection_abstract import MISSING_SOURCES
136
+ if len (MISSING_SOURCES ) > 0 :
137
+ missing_sources_string = "\n 🟡 " .join (sorted (list (MISSING_SOURCES )))
138
+ print ("WARNING: The following data_sources have been used in detections, but are not yet defined.\n "
139
+ "This is not yet an error since not all data_sources have been defined, but will be convered to an error soon:\n 🟡 "
140
+ f"{ missing_sources_string } " )
141
+ else :
142
+ print ("No missing data_sources!" )
143
+
133
144
def createSecurityContent (self , contentType : SecurityContentType ) -> None :
134
145
if contentType == SecurityContentType .ssa_detections :
135
146
files = Utils .get_all_yml_files_from_directory (
136
147
os .path .join (self .input_dto .path , "ssa_detections" )
137
148
)
138
149
security_content_files = [f for f in files if f .name .startswith ("ssa___" )]
139
-
140
- elif contentType == SecurityContentType .data_sources :
141
- security_content_files = (
142
- Utils .get_all_yml_files_from_directory_one_layer_deep (
143
- os .path .join (self .input_dto .path , "data_sources" )
144
- )
145
- )
146
-
147
- elif contentType == SecurityContentType .event_sources :
148
- security_content_files = Utils .get_all_yml_files_from_directory (
149
- os .path .join (self .input_dto .path , "data_sources" , "cloud" , "event_sources" )
150
- )
151
- security_content_files .extend (
152
- Utils .get_all_yml_files_from_directory (
153
- os .path .join (self .input_dto .path , "data_sources" , "endpoint" , "event_sources" )
154
- )
155
- )
156
- security_content_files .extend (
157
- Utils .get_all_yml_files_from_directory (
158
- os .path .join (self .input_dto .path , "data_sources" , "network" , "event_sources" )
159
- )
160
- )
161
-
162
150
elif contentType in [
163
151
SecurityContentType .deployments ,
164
152
SecurityContentType .lookups ,
@@ -168,6 +156,7 @@ def createSecurityContent(self, contentType: SecurityContentType) -> None:
168
156
SecurityContentType .investigations ,
169
157
SecurityContentType .playbooks ,
170
158
SecurityContentType .detections ,
159
+ SecurityContentType .data_sources ,
171
160
]:
172
161
files = Utils .get_all_yml_files_from_directory (
173
162
os .path .join (self .input_dto .path , str (contentType .name ))
@@ -190,54 +179,48 @@ def createSecurityContent(self, contentType: SecurityContentType) -> None:
190
179
modelDict = YmlReader .load_file (file )
191
180
192
181
if contentType == SecurityContentType .lookups :
193
- lookup = Lookup .model_validate (modelDict ,context = {"output_dto" :self .output_dto , "config" :self .input_dto })
194
- self .output_dto .addContentToDictMappings (lookup )
182
+ lookup = Lookup .model_validate (modelDict ,context = {"output_dto" :self .output_dto , "config" :self .input_dto })
183
+ self .output_dto .addContentToDictMappings (lookup )
195
184
196
185
elif contentType == SecurityContentType .macros :
197
- macro = Macro .model_validate (modelDict ,context = {"output_dto" :self .output_dto })
198
- self .output_dto .addContentToDictMappings (macro )
186
+ macro = Macro .model_validate (modelDict ,context = {"output_dto" :self .output_dto })
187
+ self .output_dto .addContentToDictMappings (macro )
199
188
200
189
elif contentType == SecurityContentType .deployments :
201
- deployment = Deployment .model_validate (modelDict ,context = {"output_dto" :self .output_dto })
202
- self .output_dto .addContentToDictMappings (deployment )
190
+ deployment = Deployment .model_validate (modelDict ,context = {"output_dto" :self .output_dto })
191
+ self .output_dto .addContentToDictMappings (deployment )
203
192
204
193
elif contentType == SecurityContentType .playbooks :
205
- playbook = Playbook .model_validate (modelDict ,context = {"output_dto" :self .output_dto })
206
- self .output_dto .addContentToDictMappings (playbook )
194
+ playbook = Playbook .model_validate (modelDict ,context = {"output_dto" :self .output_dto })
195
+ self .output_dto .addContentToDictMappings (playbook )
207
196
208
197
elif contentType == SecurityContentType .baselines :
209
- baseline = Baseline .model_validate (modelDict ,context = {"output_dto" :self .output_dto })
210
- self .output_dto .addContentToDictMappings (baseline )
198
+ baseline = Baseline .model_validate (modelDict ,context = {"output_dto" :self .output_dto })
199
+ self .output_dto .addContentToDictMappings (baseline )
211
200
212
201
elif contentType == SecurityContentType .investigations :
213
- investigation = Investigation .model_validate (modelDict ,context = {"output_dto" :self .output_dto })
214
- self .output_dto .addContentToDictMappings (investigation )
202
+ investigation = Investigation .model_validate (modelDict ,context = {"output_dto" :self .output_dto })
203
+ self .output_dto .addContentToDictMappings (investigation )
215
204
216
205
elif contentType == SecurityContentType .stories :
217
- story = Story .model_validate (modelDict ,context = {"output_dto" :self .output_dto })
218
- self .output_dto .addContentToDictMappings (story )
206
+ story = Story .model_validate (modelDict ,context = {"output_dto" :self .output_dto })
207
+ self .output_dto .addContentToDictMappings (story )
219
208
220
209
elif contentType == SecurityContentType .detections :
221
- detection = Detection .model_validate (modelDict ,context = {"output_dto" :self .output_dto , "app" :self .input_dto .app })
222
- self .output_dto .addContentToDictMappings (detection )
210
+ detection = Detection .model_validate (modelDict ,context = {"output_dto" :self .output_dto , "app" :self .input_dto .app })
211
+ self .output_dto .addContentToDictMappings (detection )
223
212
224
213
elif contentType == SecurityContentType .ssa_detections :
225
- self .constructSSADetection (self .ssa_detection_builder , self .output_dto ,str (file ))
226
- ssa_detection = self .ssa_detection_builder .getObject ()
227
- if ssa_detection .status in [DetectionStatus .production .value , DetectionStatus .validation .value ]:
228
- self .output_dto .addContentToDictMappings (ssa_detection )
214
+ self .constructSSADetection (self .ssa_detection_builder , self .output_dto ,str (file ))
215
+ ssa_detection = self .ssa_detection_builder .getObject ()
216
+ if ssa_detection .status in [DetectionStatus .production .value , DetectionStatus .validation .value ]:
217
+ self .output_dto .addContentToDictMappings (ssa_detection )
229
218
230
219
elif contentType == SecurityContentType .data_sources :
231
220
data_source = DataSource .model_validate (
232
221
modelDict , context = {"output_dto" : self .output_dto }
233
222
)
234
- self .output_dto .data_sources .append (data_source )
235
-
236
- elif contentType == SecurityContentType .event_sources :
237
- event_source = EventSource .model_validate (
238
- modelDict , context = {"output_dto" : self .output_dto }
239
- )
240
- self .output_dto .event_sources .append (event_source )
223
+ self .output_dto .addContentToDictMappings (data_source )
241
224
242
225
else :
243
226
raise Exception (f"Unsupported type: [{ contentType } ]" )
0 commit comments