Skip to content

Commit 887efd9

Browse files
committed
rebase - allowing any order and structure
1 parent 1e416b6 commit 887efd9

File tree

1 file changed

+13
-3
lines changed

1 file changed

+13
-3
lines changed

detection_rules/rule.py

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -935,8 +935,15 @@ def validates_esql_data(self, data: dict[str, Any], **_: Any) -> None:
935935
query_lower = data["query"].lower()
936936

937937
# Combine both patterns using an OR operator and compile the regex
938+
# The first part matches the metadata fields in the from clause by allowing one or
939+
# multiple indices and any order of the metadata fields
940+
# The second part matches the stats command with the by clause
938941
combined_pattern = re.compile(
939-
r"(from\s+\S+\s+metadata\s+_id,\s*_version,\s*_index)|(\bstats\b.*?\bby\b)", re.DOTALL
942+
r"(from\s+(?:\S+\s*,\s*)*\S+\s+metadata\s+"
943+
r"(_id,\s*_version,\s*_index|_id,\s*_index,\s*_version|_version,\s*_id,\s*_index|"
944+
r"_version,\s*_index,\s*_id|_index,\s*_id,\s*_version|_index,\s*_version,\s*_id))"
945+
r"|(\bstats\b.*?\bby\b)",
946+
re.DOTALL
940947
)
941948

942949
# Ensure that non-aggregate queries have metadata
@@ -948,9 +955,12 @@ def validates_esql_data(self, data: dict[str, Any], **_: Any) -> None:
948955
)
949956

950957
# Enforce KEEP command for ESQL rules
951-
if "| keep" not in query_lower:
958+
# Match | followed by optional whitespace/newlines and then 'keep'
959+
keep_pattern = re.compile(r"\|\s*keep\b", re.IGNORECASE | re.DOTALL)
960+
if not keep_pattern.search(query_lower):
952961
raise ValidationError(
953-
f"Rule: {data['name']} does not contain a 'keep' command -> Add a 'keep' command to the query."
962+
f"Rule: {data['name']} does not contain a 'keep' command ->"
963+
f" Add a 'keep' command to the query."
954964
)
955965

956966

0 commit comments

Comments
 (0)