diff --git a/detection_rules/packaging.py b/detection_rules/packaging.py index 702ecbc28cd..0dda6b507c2 100644 --- a/detection_rules/packaging.py +++ b/detection_rules/packaging.py @@ -65,7 +65,7 @@ def filter_rule(rule: TOMLRule, config_filter: dict, exclude_fields: Optional[di unique_fields = get_unique_query_fields(rule) for index, fields in exclude_fields.items(): - if unique_fields and (rule.contents.data.index == index or index == 'any'): + if unique_fields and (rule.contents.data.index_or_dataview == index or index == 'any'): if set(unique_fields) & set(fields): return False diff --git a/detection_rules/rule.py b/detection_rules/rule.py index 7ea47e44ac0..f7c4b7f31a3 100644 --- a/detection_rules/rule.py +++ b/detection_rules/rule.py @@ -700,6 +700,16 @@ class QueryRuleData(BaseRuleData): language: definitions.FilterLanguages alert_suppression: Optional[AlertSuppressionMapping] = field(metadata=dict(metadata=dict(min_compat="8.8"))) + @cached_property + def index_or_dataview(self) -> list[str]: + """Return the index or dataview depending on which is set. If neither returns empty list.""" + if self.index is not None: + return self.index + elif self.dataview is not None: + return [self.dataview] + else: + return [] + @cached_property def validator(self) -> Optional[QueryValidator]: if self.language == "kuery": diff --git a/detection_rules/rule_validators.py b/detection_rules/rule_validators.py index 486dc3c56bc..4b00bb9a25c 100644 --- a/detection_rules/rule_validators.py +++ b/detection_rules/rule_validators.py @@ -147,7 +147,7 @@ def validate_stack_combos(self, data: QueryRuleData, meta: RuleMeta) -> Union[KQ ecs_version = mapping['ecs'] err_trailer = f'stack: {stack_version}, beats: {beats_version}, ecs: {ecs_version}' - beat_types, beat_schema, schema = self.get_beats_schema(data.index or [], + beat_types, beat_schema, schema = self.get_beats_schema(data.index_or_dataview, beats_version, ecs_version) try: @@ -195,12 +195,12 @@ def validate_integration( stack_version = integration_schema_data["stack_version"] # Add non-ecs-schema fields - for index_name in data.index: + for index_name in data.index_or_dataview: integration_schema.update(**ecs.flatten(ecs.get_index_schema(index_name))) # Add custom schema fields for appropriate stack version if data.index and CUSTOM_RULES_DIR: - for index_name in data.index: + for index_name in data.index_or_dataview: integration_schema.update(**ecs.flatten(ecs.get_custom_index_schema(index_name, stack_version))) # Add endpoint schema fields for multi-line fields @@ -338,9 +338,9 @@ def validate_stack_combos(self, data: QueryRuleData, meta: RuleMeta) -> Union[EQ err_trailer = f'stack: {stack_version}, beats: {beats_version},' \ f'ecs: {ecs_version}, endgame: {endgame_version}' - beat_types, beat_schema, schema = self.get_beats_schema(data.index or [], + beat_types, beat_schema, schema = self.get_beats_schema(data.index_or_dataview, beats_version, ecs_version) - endgame_schema = self.get_endgame_schema(data.index or [], endgame_version) + endgame_schema = self.get_endgame_schema(data.index_or_dataview, endgame_version) eql_schema = ecs.KqlSchema2Eql(schema) # validate query against the beats and eql schema @@ -389,13 +389,13 @@ def validate_integration(self, data: QueryRuleData, meta: RuleMeta, stack_version = integration_schema_data["stack_version"] # add non-ecs-schema fields for edge cases not added to the integration - if data.index: - for index_name in data.index: + if data.index_or_dataview: + for index_name in data.index_or_dataview: integration_schema.update(**ecs.flatten(ecs.get_index_schema(index_name))) # Add custom schema fields for appropriate stack version - if data.index and CUSTOM_RULES_DIR: - for index_name in data.index: + if data.index_or_dataview and CUSTOM_RULES_DIR: + for index_name in data.index_or_dataview: integration_schema.update(**ecs.flatten(ecs.get_custom_index_schema(index_name, stack_version))) # add endpoint schema fields for multi-line fields