-
Notifications
You must be signed in to change notification settings - Fork 518
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add EQL rules and schema validation #297
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@rw-access I hope that I understood your request; let me know if that's not true!
detection_rules/rule.py
Outdated
# validate against all specified schemas or the latest if none specified | ||
parsed = eql.parse_query(query) | ||
beat_types = [index.split("-")[0] for index in indexes if "beat-*" in index] | ||
beat_schema = beats.get_schema_from_kql(parsed, beat_types) if beat_types else None |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this be get_schema_from_eql
?
detection_rules/schemas/v7_10.py
Outdated
eql_scope.index = jsl.ArrayField(jsl.StringField(), required=False) | ||
eql_scope.query = jsl.StringField(required=True) | ||
eql_scope.language = jsl.StringField(enum=[EQL], required=True) | ||
eql_scope.type = jsl.StringField(enum=[EQL], required=True) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@rw-access I believe this is what you wanted 👀 on, schema-wise? I can confirm that these are the EQL-specific fields and their correct types 👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yep, thanks!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is great, thanks! Can you create a rule with create-rule
too, just to make sure everything seamlessly applied.
Also, (not specifically related to EQL) one thing to note about module-specific validation is rules using/targeting the integrations on the elastic-agent with logs-*
indexes. Those would not be recognized as beats and so wouldn't know to associate the schemas. We are ok today since all those rules overlap with a beat index anyway. Retrieving these schemas may differ too.
@cached | ||
def _validate_eql(ecs_versions, indexes, query, name): | ||
# validate against all specified schemas or the latest if none specified | ||
parsed = eql.parse_query(query) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can you change the parsed_kql
property to
def parsed_query(self):
language = self.contents.get('language')
if self.query and language in ('kuery', 'eql'):
return kql.parse(self.query) if language == 'kuery' else eql.parse_query(self.query)
Then you can use that here (and more consistently as needed)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i can't use it here because this is a static method and needs to be for caching to work.
but i did update the method regardless, even though it's never used
$ python -m detection_rules create-rule x.toml -t eql
█▀▀▄ ▄▄▄ ▄▄▄ ▄▄▄ ▄▄▄ ▄▄▄ ▄▄▄ ▄▄▄ ▄ ▄ █▀▀▄ ▄ ▄ ▄ ▄▄▄ ▄▄▄
█ █ █▄▄ █ █▄▄ █ █ █ █ █ █▀▄ █ █▄▄▀ █ █ █ █▄▄ █▄▄
█▄▄▀ █▄▄ █ █▄▄ █▄▄ █ ▄█▄ █▄█ █ ▀▄█ █ ▀▄ █▄▄█ █▄▄ █▄▄ ▄▄█
rule_id [fa8d139a-4075-4ae9-a198-305fd0a88450] ("n/a" to leave blank) (required):
actions (multi, comma separated):
description (required): Test rule description.
enabled [false] ("n/a" to leave blank):
from [now-6m] ("n/a" to leave blank):
false_positives (multi, comma separated):
filters (multi, comma separated):
interval [5m] ("n/a" to leave blank):
max_signals [100] ("n/a" to leave blank):
meta:
name (required): Test EQL rule
note:
references (multi, comma separated):
risk_score [21] ("n/a" to leave blank) (required):
severity [low] ("n/a" to leave blank) (required):
tags (multi, comma separated):
throttle:
timeline_id:
timeline_title:
to [now] ("n/a" to leave blank):
add mitre tactic? [y/N]:
index (multi, comma separated):
language [eql] ("n/a" to leave blank) (required):
query (required): process where true
author (required) (multi, comma separated): Elastic
building_block_type:
exceptions_list (multi, comma separated):
license [Elastic License] ("n/a" to leave blank) (required):
risk_score_mapping (multi, comma separated):
rule_name_override:
severity_mapping (multi, comma separated):
timestamp_override:
ecs_version (multi, comma separated):
Rule Test EQL rule saved to x.toml
Did not set the following values because they are un-required when set to the default value
- from
- interval
- max_signals
- to |
Issues
Closes #285
Summary
Added EQL to the schema for 7.10.
Also added EQL syntax/schema validation.
@rylnd I added you to this PR as a reviewer. Can you double check that everything looks good on the schema side?