@@ -40,31 +40,36 @@ def validate(self, data: QueryRuleData, meta: RuleMeta) -> None:
40
40
packages_manifest = load_integrations_manifests ()
41
41
package_integrations = TOMLRuleContents .get_packaged_integrations (data , meta , packages_manifest )
42
42
43
+ # validate the query against fields within beats
44
+ self .validate_stack_combos (data , meta )
45
+
43
46
if package_integrations :
44
47
# validate the query against related integration fields
45
48
self .validate_integration (data , meta , package_integrations )
46
- else :
47
- for stack_version , mapping in meta .get_validation_stack_versions ().items ():
48
- beats_version = mapping ['beats' ]
49
- ecs_version = mapping ['ecs' ]
50
- err_trailer = f'stack: { stack_version } , beats: { beats_version } , ecs: { ecs_version } '
51
-
52
- beat_types , beat_schema , schema = self .get_beats_schema (data .index or [],
53
- beats_version , ecs_version )
54
-
55
- try :
56
- kql .parse (self .query , schema = schema )
57
- except kql .KqlParseError as exc :
58
- message = exc .error_msg
59
- trailer = err_trailer
60
- if "Unknown field" in message and beat_types :
61
- trailer = f"\n Try adding event.module or event.dataset to specify beats module\n \n { trailer } "
62
-
63
- raise kql .KqlParseError (exc .error_msg , exc .line , exc .column , exc .source ,
64
- len (exc .caret .lstrip ()), trailer = trailer ) from None
65
- except Exception :
66
- print (err_trailer )
67
- raise
49
+
50
+ def validate_stack_combos (self , data : QueryRuleData , meta : RuleMeta ) -> None :
51
+ """Validate the query against ECS and beats schemas across stack combinations."""
52
+ for stack_version , mapping in meta .get_validation_stack_versions ().items ():
53
+ beats_version = mapping ['beats' ]
54
+ ecs_version = mapping ['ecs' ]
55
+ err_trailer = f'stack: { stack_version } , beats: { beats_version } , ecs: { ecs_version } '
56
+
57
+ beat_types , beat_schema , schema = self .get_beats_schema (data .index or [],
58
+ beats_version , ecs_version )
59
+
60
+ try :
61
+ kql .parse (self .query , schema = schema )
62
+ except kql .KqlParseError as exc :
63
+ message = exc .error_msg
64
+ trailer = err_trailer
65
+ if "Unknown field" in message and beat_types :
66
+ trailer = f"\n Try adding event.module or event.dataset to specify beats module\n \n { trailer } "
67
+
68
+ raise kql .KqlParseError (exc .error_msg , exc .line , exc .column , exc .source ,
69
+ len (exc .caret .lstrip ()), trailer = trailer ) from None
70
+ except Exception :
71
+ print (err_trailer )
72
+ raise
68
73
69
74
def validate_integration (self , data : QueryRuleData , meta : RuleMeta , package_integrations : List [dict ]) -> None :
70
75
"""Validate the query, called from the parent which contains [metadata] information."""
@@ -105,7 +110,8 @@ def validate_integration(self, data: QueryRuleData, meta: RuleMeta, package_inte
105
110
f"{ stack_version = } , { ecs_version = } "
106
111
)
107
112
error_fields [field ] = {"error" : exc , "trailer" : trailer }
108
- print (f"\n Warning: `{ field } ` in `{ data .name } ` not found in schema. { trailer } " )
113
+ if data .get ("notify" , False ):
114
+ print (f"\n Warning: `{ field } ` in `{ data .name } ` not found in schema. { trailer } " )
109
115
else :
110
116
raise kql .KqlParseError (exc .error_msg , exc .line , exc .column , exc .source ,
111
117
len (exc .caret .lstrip ()), trailer = trailer ) from None
@@ -154,30 +160,34 @@ def validate(self, data: 'QueryRuleData', meta: RuleMeta) -> None:
154
160
packages_manifest = load_integrations_manifests ()
155
161
package_integrations = TOMLRuleContents .get_packaged_integrations (data , meta , packages_manifest )
156
162
163
+ # validate the query against fields within beats
164
+ self .validate_stack_combos (data , meta )
165
+
157
166
if package_integrations :
158
167
# validate the query against related integration fields
159
168
self .validate_integration (data , meta , package_integrations )
160
169
161
- else :
162
- for stack_version , mapping in meta .get_validation_stack_versions ().items ():
163
- beats_version = mapping ['beats' ]
164
- ecs_version = mapping ['ecs' ]
165
- endgame_version = mapping ['endgame' ]
166
- err_trailer = f'stack: { stack_version } , beats: { beats_version } ,' \
167
- f'ecs: { ecs_version } , endgame: { endgame_version } '
168
-
169
- beat_types , beat_schema , schema = self .get_beats_schema (data .index or [],
170
- beats_version , ecs_version )
171
- endgame_schema = self .get_endgame_schema (data .index , endgame_version )
172
- eql_schema = ecs .KqlSchema2Eql (schema )
170
+ def validate_stack_combos (self , data : QueryRuleData , meta : RuleMeta ) -> None :
171
+ """Validate the query against ECS and beats schemas across stack combinations."""
172
+ for stack_version , mapping in meta .get_validation_stack_versions ().items ():
173
+ beats_version = mapping ['beats' ]
174
+ ecs_version = mapping ['ecs' ]
175
+ endgame_version = mapping ['endgame' ]
176
+ err_trailer = f'stack: { stack_version } , beats: { beats_version } ,' \
177
+ f'ecs: { ecs_version } , endgame: { endgame_version } '
178
+
179
+ beat_types , beat_schema , schema = self .get_beats_schema (data .index or [],
180
+ beats_version , ecs_version )
181
+ endgame_schema = self .get_endgame_schema (data .index , endgame_version )
182
+ eql_schema = ecs .KqlSchema2Eql (schema )
173
183
174
- # validate query against the beats and eql schema
175
- self .validate_query_with_schema (data = data , schema = eql_schema , err_trailer = err_trailer ,
176
- beat_types = beat_types )
184
+ # validate query against the beats and eql schema
185
+ self .validate_query_with_schema (data = data , schema = eql_schema , err_trailer = err_trailer ,
186
+ beat_types = beat_types )
177
187
178
- if endgame_schema :
179
- # validate query against the endgame schema
180
- self .validate_query_with_schema (data = data , schema = endgame_schema , err_trailer = err_trailer )
188
+ if endgame_schema :
189
+ # validate query against the endgame schema
190
+ self .validate_query_with_schema (data = data , schema = endgame_schema , err_trailer = err_trailer )
181
191
182
192
def validate_integration (self , data : QueryRuleData , meta : RuleMeta , package_integrations : List [dict ]) -> None :
183
193
"""Validate an EQL query while checking TOMLRule against integration schemas."""
@@ -195,7 +205,6 @@ def validate_integration(self, data: QueryRuleData, meta: RuleMeta, package_inte
195
205
package_version = integration_schema_data ['package_version' ]
196
206
integration_schema = integration_schema_data ['schema' ]
197
207
stack_version = integration_schema_data ['stack_version' ]
198
- endgame_version = integration_schema_data ['endgame_version' ]
199
208
200
209
if stack_version != current_stack_version :
201
210
# reset the combined schema for each stack version
@@ -223,17 +232,11 @@ def validate_integration(self, data: QueryRuleData, meta: RuleMeta, package_inte
223
232
f"{ stack_version = } , { ecs_version = } "
224
233
)
225
234
error_fields [field ] = {"error" : exc , "trailer" : trailer }
226
- print (f"\n Warning: `{ field } ` in `{ data .name } ` not found in schema. { trailer } " )
235
+ if data .get ("notify" , False ):
236
+ print (f"\n Warning: `{ field } ` in `{ data .name } ` not found in schema. { trailer } " )
227
237
else :
228
238
raise exc
229
239
230
- # Still need to check endgame if it's in the index
231
- endgame_schema = self .get_endgame_schema (data .index , endgame_version )
232
- if endgame_schema :
233
- # validate query against the endgame schema
234
- err_trailer = f'stack: { stack_version } , endgame: { endgame_version } '
235
- self .validate_query_with_schema (data = data , schema = endgame_schema , err_trailer = err_trailer )
236
-
237
240
# don't error on fields that are in another integration schema
238
241
for field in list (error_fields .keys ()):
239
242
if field in combined_schema :
0 commit comments