Make notification rules queryable

This commit is contained in:
Mark Veidemanis 2023-02-02 20:41:19 +00:00
parent df1e82c5f2
commit 81c8e34211
Signed by: m
GPG Key ID: 5ACFCEED46C0904F
11 changed files with 76 additions and 9 deletions

View File

@ -14,6 +14,7 @@ from core.lib.parsing import (
QueryError, QueryError,
parse_date_time, parse_date_time,
parse_index, parse_index,
parse_rule,
parse_sentiment, parse_sentiment,
parse_size, parse_size,
parse_sort, parse_sort,
@ -32,6 +33,7 @@ mapping = {
"ts": {"type": "date", "format": "epoch_second"}, "ts": {"type": "date", "format": "epoch_second"},
"match_ts": {"type": "date", "format": "iso8601"}, "match_ts": {"type": "date", "format": "iso8601"},
"file_tim": {"type": "date", "format": "epoch_millis"}, "file_tim": {"type": "date", "format": "epoch_millis"},
"rule_uuid": {"type": "keyword"},
} }
} }
} }
@ -271,7 +273,6 @@ class ElasticsearchBackend(StorageBackend):
if self.async_client is None: if self.async_client is None:
await self.async_initialise() await self.async_initialise()
for match in matches: for match in matches:
print("INDEXING", match)
result = await self.async_client.index( result = await self.async_client.index(
index=settings.INDEX_RULE_STORAGE, body=match index=settings.INDEX_RULE_STORAGE, body=match
) )
@ -439,6 +440,14 @@ class ElasticsearchBackend(StorageBackend):
if isinstance(size, dict): if isinstance(size, dict):
return size return size
rule_object = parse_rule(request.user, query_params)
if isinstance(rule_object, dict):
return rule_object
if rule_object is not None:
index = settings.INDEX_RULE_STORAGE
add_bool.append({"rule_uuid": str(rule_object.id)})
else:
# I - Index # I - Index
index = parse_index(request.user, query_params) index = parse_index(request.user, query_params)
if isinstance(index, dict): if isinstance(index, dict):

View File

@ -1,12 +1,40 @@
from datetime import datetime from datetime import datetime
from django.conf import settings from django.conf import settings
from django.core.exceptions import ValidationError
from core.models import NotificationRule
class QueryError(Exception): class QueryError(Exception):
pass pass
def parse_rule(user, query_params):
"""
Parse a rule query.
"""
if "rule" in query_params:
try:
rule_object = NotificationRule.objects.filter(id=query_params["rule"])
except ValidationError:
message = "Rule is not a valid UUID"
message_class = "danger"
return {"message": message, "class": message_class}
if not rule_object.exists():
message = "Rule does not exist"
message_class = "danger"
return {"message": message, "class": message_class}
rule_object = rule_object.first()
if not rule_object.user == user:
message = "Rule does not belong to you"
message_class = "danger"
return {"message": message, "class": message_class}
return rule_object
else:
return None
def parse_size(query_params, sizes): def parse_size(query_params, sizes):
if "size" in query_params: if "size" in query_params:
size = query_params["size"] size = query_params["size"]

View File

@ -284,7 +284,6 @@ class NotificationRuleData(object):
if not isinstance(matches, list): if not isinstance(matches, list):
matches = [matches] matches = [matches]
matches_copy = matches.copy() matches_copy = matches.copy()
print("MATHCES COPY: ", matches_copy)
match_ts = datetime.utcnow().isoformat() match_ts = datetime.utcnow().isoformat()
for match_index, _ in enumerate(matches_copy): for match_index, _ in enumerate(matches_copy):
matches_copy[match_index]["index"] = index matches_copy[match_index]["index"] = index

View File

@ -66,6 +66,10 @@ $(document).ready(function(){
"file_size": "off", "file_size": "off",
"lang_code": "off", "lang_code": "off",
"tokens": "off", "tokens": "off",
"rule_uuid": "off",
"index": "off",
"meta": "off",
"match_ts": "off",
//"lang_name": "off", //"lang_name": "off",
// "words_noun": "off", // "words_noun": "off",
// "words_adj": "off", // "words_adj": "off",

View File

@ -14,7 +14,9 @@
</span> </span>
{% endif %} {% endif %}
fetched {{ table.data|length }} hits in {{ took }}ms fetched {{ table.data|length }}
{% if params.rule is None %} hits {% else %} rule hits for {{ params.rule }}{% endif %}
in {{ took }}ms
{% if exemption is not None %} {% if exemption is not None %}
<span class="icon has-tooltip-bottom" data-tooltip="God mode"> <span class="icon has-tooltip-bottom" data-tooltip="God mode">

View File

@ -3,6 +3,7 @@
{% load static %} {% load static %}
{% load joinsep %} {% load joinsep %}
{% load urlsafe %} {% load urlsafe %}
{% load pretty %}
{% block table-wrapper %} {% block table-wrapper %}
<script src="{% static 'js/column-shifter.js' %}"></script> <script src="{% static 'js/column-shifter.js' %}"></script>
<div id="drilldown-table" class="column-shifter-container" style="position:relative; z-index:1;"> <div id="drilldown-table" class="column-shifter-container" style="position:relative; z-index:1;">
@ -373,6 +374,10 @@
{% endfor %} {% endfor %}
</div> </div>
</td> </td>
{% elif column.name == "meta" %}
<td class="{{ column.name }}">
<pre>{{ cell|pretty }}</pre>
</td>
{% else %} {% else %}
<td class="{{ column.name }}"> <td class="{{ column.name }}">
<a <a

View File

@ -22,7 +22,7 @@
</thead> </thead>
{% for item in object_list %} {% for item in object_list %}
<tr> <tr>
<td>{{ item.id }}</td> <td><a href="/search/?rule={{ item.id }}&query=*&source=all">{{ item.id }}</a></td>
<td>{{ item.user }}</td> <td>{{ item.user }}</td>
<td>{{ item.name }}</td> <td>{{ item.name }}</td>
<td>{{ item.interval }}s</td> <td>{{ item.interval }}s</td>

View File

@ -7,7 +7,9 @@
</span> </span>
{% endif %} {% endif %}
fetched {{ table.data|length }} hits in {{ took }}ms fetched {{ table.data|length }}
{% if params.rule is None %} hits {% else %} rule hits for {{ params.rule }}{% endif %}
in {{ took }}ms
{% if exemption is not None %} {% if exemption is not None %}
<span class="icon has-tooltip-bottom" data-tooltip="God mode"> <span class="icon has-tooltip-bottom" data-tooltip="God mode">

View File

@ -404,4 +404,9 @@
value="{{ params.tags }}"> value="{{ params.tags }}">
</div> </div>
<div class="is-hidden"></div> <div class="is-hidden"></div>
{% if params.rule is not None %}
<div style="display:none;">
<input name="rule" value="{{ params.rule }}">
</div>
{% endif %}
</form> </form>

View File

@ -0,0 +1,9 @@
import orjson
from django import template
register = template.Library()
@register.filter
def pretty(data):
return orjson.dumps(data, option=orjson.OPT_INDENT_2).decode("utf-8")

View File

@ -76,6 +76,10 @@ class DrilldownTable(Table):
file_md5 = Column() file_md5 = Column()
file_ext = Column() file_ext = Column()
file_size = Column() file_size = Column()
rule_uuid = Column()
index = Column()
meta = Column()
match_ts = Column()
template_name = "ui/drilldown/table_results.html" template_name = "ui/drilldown/table_results.html"
paginate_by = settings.DRILLDOWN_RESULTS_PER_PAGE paginate_by = settings.DRILLDOWN_RESULTS_PER_PAGE