|
|
|
@ -10,6 +10,7 @@ except ImportError:
|
|
|
|
|
|
|
|
|
|
import orjson
|
|
|
|
|
from asgiref.sync import async_to_sync
|
|
|
|
|
from siphashc import siphash
|
|
|
|
|
|
|
|
|
|
from core.lib.notify import sendmsg
|
|
|
|
|
from core.lib.parsing import parse_index, parse_source
|
|
|
|
@ -205,8 +206,13 @@ class NotificationRuleData(object):
|
|
|
|
|
Store a match result.
|
|
|
|
|
Accepts None for the index to set all indices.
|
|
|
|
|
:param index: the index to store the match for, can be None
|
|
|
|
|
:param match: True or False, indicating if the rule matched
|
|
|
|
|
:param match: the object that matched
|
|
|
|
|
"""
|
|
|
|
|
if match is not False:
|
|
|
|
|
# Dump match to JSON while sorting the keys
|
|
|
|
|
match_normalised = orjson.dumps(match, option=orjson.OPT_SORT_KEYS)
|
|
|
|
|
match = siphash(self.db.hash_key, match_normalised)
|
|
|
|
|
|
|
|
|
|
if self.object.match is None:
|
|
|
|
|
self.object.match = {}
|
|
|
|
|
if not isinstance(self.object.match, dict):
|
|
|
|
@ -220,7 +226,7 @@ class NotificationRuleData(object):
|
|
|
|
|
self.object.save()
|
|
|
|
|
log.debug(f"Stored match: {index} - {match}")
|
|
|
|
|
|
|
|
|
|
def get_match(self, index=None):
|
|
|
|
|
def get_match(self, index=None, match=None):
|
|
|
|
|
"""
|
|
|
|
|
Get a match result for an index.
|
|
|
|
|
If the index is None, it will return True if any index has a match.
|
|
|
|
@ -237,6 +243,13 @@ class NotificationRuleData(object):
|
|
|
|
|
# Check if we have any matches on all indices
|
|
|
|
|
return any(self.object.match.values())
|
|
|
|
|
|
|
|
|
|
# Check if it's the same hash
|
|
|
|
|
if match is not None:
|
|
|
|
|
match_normalised = orjson.dumps(match, option=orjson.OPT_SORT_KEYS)
|
|
|
|
|
match = siphash(self.db.hash_key, match_normalised)
|
|
|
|
|
hash_matches = self.object.match.get(index) == match
|
|
|
|
|
return hash_matches
|
|
|
|
|
|
|
|
|
|
return self.object.match.get(index)
|
|
|
|
|
|
|
|
|
|
def format_aggs(self, aggs):
|
|
|
|
@ -268,13 +281,13 @@ class NotificationRuleData(object):
|
|
|
|
|
:param message: the message object that matched
|
|
|
|
|
:param aggs: the aggregations that matched
|
|
|
|
|
"""
|
|
|
|
|
current_match = self.get_match(index)
|
|
|
|
|
current_match = self.get_match(index, message)
|
|
|
|
|
log.debug(f"Rule matched: {index} - current match: {current_match}")
|
|
|
|
|
if current_match is False:
|
|
|
|
|
# Matched now, but not before
|
|
|
|
|
meta["matched"] = self.format_aggs(meta["aggs"])
|
|
|
|
|
rule_notify(self.object, index, message, meta)
|
|
|
|
|
self.store_match(index, True)
|
|
|
|
|
self.store_match(index, message)
|
|
|
|
|
|
|
|
|
|
def rule_no_match(self, index=None):
|
|
|
|
|
"""
|
|
|
|
|