Skip to content
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Update search query to KVStore
  • Loading branch information
xqi-splunk committed Oct 15, 2025
commit ab92eb07f672655fbcc94e1031dd62ebec35b742
47 changes: 39 additions & 8 deletions contentctl/objects/content_versioning_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
from contentctl.objects.detection import Detection

# Suppress logging by default; enable for local testing
ENABLE_LOGGING = False
ENABLE_LOGGING = True
LOG_LEVEL = logging.DEBUG
LOG_PATH = "content_versioning_service.log"

Expand Down Expand Up @@ -186,7 +186,7 @@ def cms_fields(self) -> list[str]:
"app_name",
"detection_id",
"version",
"action.correlationsearch.label",
"content",
"sourcetype",
]

Expand Down Expand Up @@ -293,15 +293,36 @@ def _query_cms_main(self, use_cache: bool = False) -> splunklib.Job:

# Construct the query looking for CMS events matching the content app name
query = (
f"search index=cms_main sourcetype=stash_common_detection_model "
f'app_name="{self.global_config.app.appid}" | fields {", ".join(self.cms_fields)}'
f"| inputlookup cms_content_lookup | search app_name={self.global_config.app.appid}"
f"| fields {', '.join(self.cms_fields)}"
)
self.logger.debug(
f"[{self.infrastructure.instance_name}] Query on cms_main: {query}"
)

# Get the job as a blocking operation, set the cache, and return
self._cms_main_job = self.service.search(query, exec_mode="blocking") # type: ignore
result_count = int(self._cms_main_job["resultCount"])
self.logger.debug(
f"[TESTING DEBUG INFO] cms_content_lookup search returned {result_count} results"
)

# Log a sample of the actual results (first 3)
if result_count > 0:
sample_results = []
iterator = ResultIterator(
response_reader=self._cms_main_job.results(
output_mode="json", count=3, offset=0
), # type: ignore
error_filters=[],
)
for result in iterator:
sample_results.append(result)

self.logger.debug(
f"[TESTING DEBUG INFO] Sample results (first {len(sample_results)}): "
f"{json.dumps(sample_results, indent=2)}"
)
return self._cms_main_job

def get_num_cms_events(self, use_cache: bool = False) -> int:
Expand Down Expand Up @@ -376,7 +397,15 @@ def validate_content_against_cms(self) -> None:
offset += 1

# Get the name of the search in the CMS event
cms_entry_name = cms_event["action.correlationsearch.label"]
content = json.loads(cms_event["content"])
self.logger.debug(
f"[TESTING DEBUG INFO] CMS Event content: {cms_event['content']}"
)
self.logger.debug(
f"[TESTING DEBUG INFO] CMS Event content after json load: {type(content)}"
)
# Get the name of the search in the CMS event
cms_entry_name = content["action.correlationsearch.label"]
self.logger.info(
f"[{self.infrastructure.instance_name}] {offset}: Matching cms_main entry "
f"'{cms_entry_name}' against detections"
Expand Down Expand Up @@ -477,12 +506,14 @@ def validate_detection_against_cms_event(
self.global_config.app
)

content = json.loads(cms_event["content"])
cms_entry_name = content["action.correlationsearch.label"]

# Compare the correlation search label
if cms_event["action.correlationsearch.label"] != rule_name_from_detection:
if cms_entry_name != rule_name_from_detection:
msg = (
f"[{self.infrastructure.instance_name}][{detection.name}]: Correlation search "
f"label in cms_event ('{cms_event['action.correlationsearch.label']}') does not "
"match detection name"
f"label in cms_event ('{cms_entry_name}') does not match detection name"
)
self.logger.error(msg)
return Exception(msg)
Expand Down