1616from contentctl .objects .correlation_search import ResultIterator
1717from contentctl .helper .utils import Utils
1818
19+ # TODO (cmcginley):
20+ # - [x] version naming scheme seems to have changed from X - X to X.X
21+ # - [x] sourcetype no longer holds detection name but instead is stash_common_detection_model
22+ # - [ ] action.escu.full_search_name no longer available
23+ # - [ ] check to see if we can get "name"
24+ # - [ ] move strings to enums
25+ # - [ ] additionally, timeout for cms_parser seems to need more time
26+
1927# TODO (cmcginley): suppress logging
2028# Suppress logging by default; enable for local testing
2129ENABLE_LOGGING = True
@@ -55,6 +63,15 @@ class ContentVersioningService(BaseModel):
5563 )
5664 )
5765
66+ def model_post_init (self , __context : Any ) -> None :
67+ super ().model_post_init (__context )
68+
69+ # Log instance details
70+ self .logger .info (
71+ f"[{ self .infrastructure .instance_name } ({ self .infrastructure .instance_address } )] "
72+ "Initing ContentVersioningService"
73+ )
74+
5875 # The cached job on the splunk instance of the cms events
5976 _cms_main_job : splunklib .Job | None = PrivateAttr (default = None )
6077
@@ -167,6 +184,10 @@ def activate_versioning(self) -> None:
167184 if not self .is_versioning_activated :
168185 raise Exception ("Something went wrong, content versioning is still disabled." )
169186
187+ self .logger .info (
188+ f"[{ self .infrastructure .instance_name } ] Versioning service successfully activated"
189+ )
190+
170191 @computed_field
171192 @cached_property
172193 def cms_fields (self ) -> list [str ]:
@@ -178,7 +199,6 @@ def cms_fields(self) -> list[str]:
178199 """
179200 return [
180201 "app_name" ,
181- f"action.{ self .global_config .app .label .lower ()} .full_search_name" ,
182202 "detection_id" ,
183203 "version" ,
184204 "action.correlationsearch.label" ,
@@ -214,6 +234,10 @@ def force_cms_parser(self) -> None:
214234 if not self .is_cms_parser_enabled :
215235 raise Exception ("Something went wrong, cms_parser is still disabled." )
216236
237+ self .logger .info (
238+ f"[{ self .infrastructure .instance_name } ] cms_parser successfully toggled to force run"
239+ )
240+
217241 def wait_for_cms_main (self ) -> None :
218242 """
219243 Checks the cms_main index until it has the expected number of events, or it times out.
@@ -225,27 +249,36 @@ def wait_for_cms_main(self) -> None:
225249 elapsed_sleep_time = 0
226250 num_tries = 0
227251 time_to_sleep = 2 ** num_tries
228- max_sleep = 300
252+ max_sleep = 480
229253
230254 # Loop until timeout
231255 while elapsed_sleep_time < max_sleep :
232256 # Sleep, and add the time to the elapsed counter
233- self .logger .info (f"Waiting { time_to_sleep } for cms_parser to finish" )
257+ self .logger .info (
258+ f"[{ self .infrastructure .instance_name } ] Waiting { time_to_sleep } for cms_parser to "
259+ "finish"
260+ )
234261 time .sleep (time_to_sleep )
235262 elapsed_sleep_time += time_to_sleep
236263 self .logger .info (
237- f"Checking cms_main (attempt #{ num_tries + 1 } - { elapsed_sleep_time } seconds elapsed of "
238- f"{ max_sleep } max)"
264+ f"[ { self . infrastructure . instance_name } ] Checking cms_main (attempt #{ num_tries + 1 } "
265+ f" - { elapsed_sleep_time } seconds elapsed of { max_sleep } max)"
239266 )
240267
241268 # Check if the number of CMS events matches or exceeds the number of detections
242269 if self .get_num_cms_events () >= len (self .detections ):
243270 self .logger .info (
244- f"Found { self .get_num_cms_events (use_cache = True )} events in cms_main which "
271+ f"[{ self .infrastructure .instance_name } ] Found "
272+ f"{ self .get_num_cms_events (use_cache = True )} events in cms_main which "
245273 f"meets or exceeds the expected { len (self .detections )} ."
246274 )
247275 break
248-
276+ else :
277+ self .logger .info (
278+ f"[{ self .infrastructure .instance_name } ] Found "
279+ f"{ self .get_num_cms_events (use_cache = True )} matching events in cms_main; "
280+ f"expecting { len (self .detections )} . Continuing to wait..."
281+ )
249282 # Update the number of times we've tried, and increment the time to sleep
250283 num_tries += 1
251284 time_to_sleep = 2 ** num_tries
@@ -278,7 +311,7 @@ def _query_cms_main(self, use_cache: bool = False) -> splunklib.Job:
278311 f"search index=cms_main app_name=\" { self .global_config .app .appid } \" | "
279312 f"fields { ', ' .join (self .cms_fields )} "
280313 )
281- self .logger .debug (f"Query on cms_main: { query } " )
314+ self .logger .debug (f"[ { self . infrastructure . instance_name } ] Query on cms_main: { query } " )
282315
283316 # Get the job as a blocking operation, set the cache, and return
284317 self ._cms_main_job = self .service .search (query , exec_mode = "blocking" ) # type: ignore
@@ -317,14 +350,14 @@ def validate_content_against_cms(self) -> None:
317350 # Generate an error for the count mismatch
318351 if result_count != len (self .detections ):
319352 msg = (
320- f"Expected { len (self .detections )} matching events in cms_main, but "
321- f"found { result_count } ."
353+ f"[ { self . infrastructure . instance_name } ] Expected { len (self .detections )} matching "
354+ f"events in cms_main, but found { result_count } ."
322355 )
323356 self .logger .error (msg )
324357 exceptions .append (Exception (msg ))
325358 self .logger .info (
326- f"Expecting { len (self .detections )} matching events in cms_main, "
327- f"found { result_count } ."
359+ f"[ { self . infrastructure . instance_name } ] Expecting { len (self .detections )} matching "
360+ f"events in cms_main, found { result_count } ."
328361 )
329362
330363 # Init some counters and a mapping of detections to their names
@@ -351,30 +384,34 @@ def validate_content_against_cms(self) -> None:
351384 # Get the name of the search in the CMS event and attempt to use pattern matching
352385 # to strip the prefix and suffix used for the savedsearches.conf name so we can
353386 # compare to the detection
354- cms_entry_name = cms_event ["sourcetype" ]
355- self .logger .info (f"{ offset } : Matching cms_main entry '{ cms_entry_name } ' against detections" )
356- ptrn = re .compile (r"^" + self .global_config .app .label + r" - (?P<cms_entry_name>.+) - Rule$" )
357- match = ptrn .match (cms_event ["sourcetype" ])
387+ cms_entry_name = cms_event ["action.correlationsearch.label" ]
388+ self .logger .info (
389+ f"[{ self .infrastructure .instance_name } ] { offset } : Matching cms_main entry "
390+ f"'{ cms_entry_name } ' against detections"
391+ )
392+ ptrn = re .compile (r"^" + self .global_config .app .label + r" - (?P<stripped_cms_entry_name>.+) - Rule$" )
393+ match = ptrn .match (cms_event ["action.correlationsearch.label" ])
358394
359395 # Report any errors extracting the detection name from the longer rule name
360396 if match is None :
361397 msg = (
362- f"[{ cms_entry_name } ]: Entry in cms_main did not match the expected naming "
363- "scheme; cannot compare to our detections."
398+ f"[{ self .infrastructure .instance_name } ] [{ cms_entry_name } ]: Entry in "
399+ "cms_main did not match the expected naming scheme; cannot compare to our "
400+ "detections."
364401 )
365402 self .logger .error (msg )
366403 exceptions .append (Exception (msg ))
367404 continue
368405
369406 # Extract the detection name if matching was successful
370- cms_entry_name = match .group ("cms_entry_name " )
407+ stripped_cms_entry_name = match .group ("stripped_cms_entry_name " )
371408
372409 # If CMS entry name matches one of the detections already matched, we've got an
373410 # unexpected repeated entry
374- if cms_entry_name in matched_detections :
411+ if stripped_cms_entry_name in matched_detections :
375412 msg = (
376- f"[{ cms_entry_name } ] : Detection appears more than once in the cms_main "
377- " index."
413+ f"[{ self . infrastructure . instance_name } ] [ { stripped_cms_entry_name } ] : Detection "
414+ f"appears more than once in the cms_main index."
378415 )
379416 self .logger .error (msg )
380417 exceptions .append (Exception (msg ))
@@ -385,10 +422,10 @@ def validate_content_against_cms(self) -> None:
385422 for detection_name in remaining_detections :
386423 # If we find a match, break this loop, set the found flag and move the detection
387424 # from those that still need to matched to those already matched
388- if cms_entry_name == detection_name :
425+ if stripped_cms_entry_name == detection_name :
389426 self .logger .info (
390- f"{ offset } : Succesfully matched cms_main entry against detection "
391- f"('{ detection_name } ')!"
427+ f"[ { self . infrastructure . instance_name } ] { offset } : Succesfully matched "
428+ f"cms_main entry against detection ('{ detection_name } ')!"
392429 )
393430
394431 # Validate other fields of the cms_event against the detection
@@ -410,8 +447,8 @@ def validate_content_against_cms(self) -> None:
410447 # Generate an exception if we couldn't match the CMS main entry to a detection
411448 if result_matches_detection is False :
412449 msg = (
413- f"[{ cms_entry_name } ] : Could not match entry in cms_main against any "
414- "of the expected detections."
450+ f"[{ self . infrastructure . instance_name } ] [ { stripped_cms_entry_name } ] : Could not "
451+ "match entry in cms_main against any of the expected detections."
415452 )
416453 self .logger .error (msg )
417454 exceptions .append (Exception (msg ))
@@ -422,8 +459,8 @@ def validate_content_against_cms(self) -> None:
422459 # Generate exceptions for the unmatched detections
423460 for detection_name in remaining_detections :
424461 msg = (
425- f"[{ detection_name } ]: Detection not found in cms_main; there may be an "
426- "issue with savedsearches.conf"
462+ f"[{ self . infrastructure . instance_name } ] [ { detection_name } ]: Detection not "
463+ "found in cms_main; there may be an issue with savedsearches.conf"
427464 )
428465 self .logger .error (msg )
429466 exceptions .append (Exception (msg ))
@@ -436,7 +473,10 @@ def validate_content_against_cms(self) -> None:
436473 )
437474
438475 # Else, we've matched/validated all detections against cms_main
439- self .logger .info ("Matched and validated all detections against cms_main!" )
476+ self .logger .info (
477+ f"[{ self .infrastructure .instance_name } ] Matched and validated all detections against "
478+ "cms_main!"
479+ )
440480
441481 def validate_detection_against_cms_event (
442482 self ,
@@ -458,47 +498,41 @@ def validate_detection_against_cms_event(
458498 # TODO (cmcginley): validate additional fields between the cms_event and the detection
459499
460500 cms_uuid = uuid .UUID (cms_event ["detection_id" ])
461- full_search_key = f"action.{ self .global_config .app .label .lower ()} .full_search_name"
462501 rule_name_from_detection = f"{ self .global_config .app .label } - { detection .name } - Rule"
463502
464503 # Compare the UUIDs
465504 if cms_uuid != detection .id :
466505 msg = (
467- f"[{ detection .name } ]: UUID in cms_event (' { cms_uuid } ') does not match UUID in "
468- f"detection ('{ detection .id } ')"
506+ f"[{ self . infrastructure . instance_name } ] [ { detection .name } ]: UUID in cms_event "
507+ f"(' { cms_uuid } ') does not match UUID in detection ('{ detection .id } ')"
469508 )
470509 self .logger .error (msg )
471510 return Exception (msg )
472- elif cms_event ["version" ] != f"{ detection .version } - 1" :
473- # Compare the versions (we append '- 1' to the detection version to be in line w/ the
511+ elif cms_event ["version" ] != f"{ detection .version } . 1" :
512+ # Compare the versions (we append '. 1' to the detection version to be in line w/ the
474513 # internal representation in ES)
475514 msg = (
476- f"[{ detection .name } ]: Version in cms_event ('{ cms_event ['version' ]} ') does not "
477- f"match version in detection ('{ detection .version } -1')"
478- )
479- self .logger .error (msg )
480- return Exception (msg )
481- elif cms_event [full_search_key ] != rule_name_from_detection :
482- # Compare the full search name
483- msg = (
484- f"[{ detection .name } ]: Full search name in cms_event "
485- f"('{ cms_event [full_search_key ]} ') does not match detection name"
515+ f"[{ self .infrastructure .instance_name } ] [{ detection .name } ]: Version in cms_event "
516+ f"('{ cms_event ['version' ]} ') does not match version in detection "
517+ f"('{ detection .version } .1')"
486518 )
487519 self .logger .error (msg )
488520 return Exception (msg )
489- elif cms_event ["action.correlationsearch.label" ] != f" { self . global_config . app . label } - { detection . name } - Rule" :
521+ elif cms_event ["action.correlationsearch.label" ] != rule_name_from_detection :
490522 # Compare the correlation search label
491523 msg = (
492- f"[{ detection .name } ]: Correlation search label in cms_event "
493- f"('{ cms_event ['action.correlationsearch.label' ]} ') does not match detection name"
524+ f"[{ self .infrastructure .instance_name } ][{ detection .name } ]: Correlation search "
525+ f"label in cms_event ('{ cms_event ['action.correlationsearch.label' ]} ') does not "
526+ "match detection name"
494527 )
495528 self .logger .error (msg )
496529 return Exception (msg )
497- elif cms_event ["sourcetype" ] != f" { self . global_config . app . label } - { detection . name } - Rule " :
530+ elif cms_event ["sourcetype" ] != "stash_common_detection_model " :
498531 # Compare the full search name
499532 msg = (
500- f"[{ detection .name } ]: Sourcetype in cms_event ('{ cms_event [f'sourcetype' ]} ') does "
501- f"not match detection name"
533+ f"[{ self .infrastructure .instance_name } ] [{ detection .name } ]: Unexpected sourcetype "
534+ f"in cms_event ('{ cms_event [f'sourcetype' ]} '); expected "
535+ "'stash_common_detection_model'"
502536 )
503537 self .logger .error (msg )
504538 return Exception (msg )
0 commit comments