Skip to content

Commit

Permalink
add timestamp field to POST request (#63)
Browse files Browse the repository at this point in the history
  • Loading branch information
taylorwalton authored Jul 25, 2023
1 parent 1964489 commit c21cc94
Show file tree
Hide file tree
Showing 4 changed files with 134 additions and 18 deletions.
40 changes: 36 additions & 4 deletions backend/app/routes/alerts.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,16 @@ def get_alerts() -> jsonify:
timerange = str(data.get("timerange", "24h"))
alert_field = str(data.get("alert_field", "syslog_level"))
alert_value = str(data.get("alert_value", "ALERT"))
timestamp_field = str(data.get("timestamp_field", "timestamp_utc"))

service = AlertsService()
alerts = service.collect_alerts(size=size, timerange=timerange, alert_field=alert_field, alert_value=alert_value)
alerts = service.collect_alerts(
size=size,
timerange=timerange,
alert_field=alert_field,
alert_value=alert_value,
timestamp_field=timestamp_field,
)
return jsonify(alerts)


Expand All @@ -51,6 +58,7 @@ def get_alerts_by_agent() -> jsonify:
agent_name = str(data.get("agent_name", "WIN-HFOU106TD7K"))
alert_field = str(data.get("alert_field", "syslog_level"))
alert_value = str(data.get("alert_value", "ALERT"))
timestamp_field = str(data.get("timestamp_field", "timestamp_utc"))
service = AlertsService()
# size = request.args.get("size", default=10, type=int)
# timerange = request.args.get("timerange", default="24h", type=str)
Expand All @@ -60,6 +68,7 @@ def get_alerts_by_agent() -> jsonify:
timerange=timerange,
alert_field=alert_field,
alert_value=alert_value,
timestamp_field=timestamp_field,
)
return jsonify(alerts)

Expand All @@ -83,13 +92,15 @@ def get_alerts_by_index() -> jsonify:
index_name = str(data.get("index_name", "wazuh*"))
alert_field = str(data.get("alert_field", "syslog_level"))
alert_value = str(data.get("alert_value", "ALERT"))
timestamp_field = str(data.get("timestamp_field", "timestamp_utc"))
service = AlertsService()
alerts = service.collect_alerts_by_index(
index_name=index_name,
size=size,
timerange=timerange,
alert_field=alert_field,
alert_value=alert_value,
timestamp_field=timestamp_field,
)
return jsonify(alerts)

Expand All @@ -112,8 +123,15 @@ def get_hosts() -> jsonify:
timerange = str(data.get("timerange", "24h"))
alert_field = str(data.get("alert_field", "syslog_level"))
alert_value = str(data.get("alert_value", "ALERT"))
timestamp_field = str(data.get("timestamp_field", "timestamp_utc"))
service = AlertsService()
hosts = service.collect_alerts_by_host(size=size, timerange=timerange, alert_field=alert_field, alert_value=alert_value)
hosts = service.collect_alerts_by_host(
size=size,
timerange=timerange,
alert_field=alert_field,
alert_value=alert_value,
timestamp_field=timestamp_field,
)
return jsonify(hosts)


Expand All @@ -135,8 +153,15 @@ def get_rules() -> jsonify:
timerange = str(data.get("timerange", "24h"))
alert_field = str(data.get("alert_field", "syslog_level"))
alert_value = str(data.get("alert_value", "ALERT"))
timestamp_field = str(data.get("timestamp_field", "timestamp_utc"))
service = AlertsService()
rules = service.collect_alerts_by_rule(size=size, timerange=timerange, alert_field=alert_field, alert_value=alert_value)
rules = service.collect_alerts_by_rule(
size=size,
timerange=timerange,
alert_field=alert_field,
alert_value=alert_value,
timestamp_field=timestamp_field,
)
return jsonify(rules)


Expand All @@ -158,8 +183,15 @@ def get_rules_by_host() -> jsonify:
timerange = str(data.get("timerange", "24h"))
alert_field = str(data.get("alert_field", "syslog_level"))
alert_value = str(data.get("alert_value", "ALERT"))
timestamp_field = str(data.get("timestamp_field", "timestamp_utc"))
service = AlertsService()
rules = service.collect_alerts_by_rule_per_host(size=size, timerange=timerange, alert_field=alert_field, alert_value=alert_value)
rules = service.collect_alerts_by_rule_per_host(
size=size,
timerange=timerange,
alert_field=alert_field,
alert_value=alert_value,
timestamp_field=timestamp_field,
)
return jsonify(rules)


Expand Down
78 changes: 66 additions & 12 deletions backend/app/services/WazuhIndexer/alerts.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ def _collect_indices_and_validate(self) -> Dict[str, Any]:

return {"success": True, "indices": valid_indices}

def collect_alerts(self, size: int, timerange: str, alert_field: str, alert_value: str) -> Dict[str, object]:
def collect_alerts(self, size: int, timerange: str, alert_field: str, alert_value: str, timestamp_field: str) -> Dict[str, object]:
"""
Collects alerts from the Wazuh-Indexer.
Expand All @@ -82,6 +82,7 @@ def collect_alerts(self, size: int, timerange: str, alert_field: str, alert_valu
timerange (str): The time range to collect alerts from. This is a string like "24h", "1w", etc.
alert_field (str): The field to match.
alert_value (str): The value to match.
timestamp_field (str): The timestamp field to sort by.
Returns:
Dict[str, object]: A dictionary containing success status and alerts or an error message.
"""
Expand All @@ -94,7 +95,7 @@ def collect_alerts(self, size: int, timerange: str, alert_field: str, alert_valu
# matches = [("syslog_level", "ALERT")]
matches = [(alert_field, alert_value)]
for index_name in indices_validation["indices"]:
alerts = self._collect_alerts(index_name, size=size, timerange=timerange, matches=matches)
alerts = self._collect_alerts(index_name, size=size, timerange=timerange, matches=matches, timestamp_field=timestamp_field)
if alerts["success"] and len(alerts["alerts"]) > 0:
alerts_summary.append(
{
Expand Down Expand Up @@ -134,7 +135,15 @@ def collect_alerts_last_24_hours(self, size: int) -> Dict[str, object]:
"alerts_summary": alerts_summary,
}

def collect_alerts_by_index(self, index_name: str, size: int, timerange: str, alert_field: str, alert_value: str) -> Dict[str, Any]:
def collect_alerts_by_index(
self,
index_name: str,
size: int,
timerange: str,
alert_field: str,
alert_value: str,
timestamp_field: str,
) -> Dict[str, Any]:
"""
Collects alerts from the given index.
Expand All @@ -144,6 +153,7 @@ def collect_alerts_by_index(self, index_name: str, size: int, timerange: str, al
timerange (str): The time range to collect alerts from. This is a string like "24h", "1w", etc.
alert_field (str): The field to match.
alert_value (str): The value to match.
timestamp_field (str): The timestamp field to sort by.
Returns:
Dict[str, Any]: A dictionary containing success status, a message, and potentially the alerts from the given index.
Expand All @@ -152,7 +162,13 @@ def collect_alerts_by_index(self, index_name: str, size: int, timerange: str, al
return self._error_response("Invalid index name")

matches = [(alert_field, alert_value)]
alerts = self._collect_alerts(index_name=index_name, size=size, timerange=timerange, matches=matches)
alerts = self._collect_alerts(
index_name=index_name,
size=size,
timerange=timerange,
matches=matches,
timestamp_field=timestamp_field,
)
if not alerts["success"]:
return alerts

Expand All @@ -170,6 +186,7 @@ def collect_alerts_by_agent_name(
timerange: str,
alert_field: str,
alert_value: str,
timestamp_field: str,
) -> Dict[str, Any]:
"""
Collects alerts associated with a given agent name.
Expand All @@ -180,6 +197,7 @@ def collect_alerts_by_agent_name(
timerange (str): The time range to collect alerts from. This is a string like "24h", "1w", etc.
alert_field (str): The field to match.
alert_value (str): The value to match.
timestamp_field (str): The timestamp field to sort by.
Returns:
Dict[str, Any]: A dictionary containing success status, a message, and potentially the alerts associated with the agent.
Expand All @@ -191,7 +209,13 @@ def collect_alerts_by_agent_name(
alerts_by_agent_dict = {}
matches = [(alert_field, alert_value), ("agent_name", f"{agent_name}")]
for index_name in indices_validation["indices"]:
alerts = self._collect_alerts(index_name=index_name, size=size, timerange=timerange, matches=matches)
alerts = self._collect_alerts(
index_name=index_name,
size=size,
timerange=timerange,
matches=matches,
timestamp_field=timestamp_field,
)
if alerts["success"]:
for alert in alerts["alerts"]:
if alert["_source"]["agent_name"] == agent_name:
Expand All @@ -205,7 +229,7 @@ def collect_alerts_by_agent_name(
"alerts_by_agent": alerts_by_agent_list,
}

def collect_alerts_by_host(self, size: int, timerange: str, alert_field: str, alert_value: str) -> Dict[str, int]:
def collect_alerts_by_host(self, size: int, timerange: str, alert_field: str, alert_value: str, timestamp_field: str) -> Dict[str, int]:
"""
Collects the number of alerts per host.
Expand All @@ -214,6 +238,7 @@ def collect_alerts_by_host(self, size: int, timerange: str, alert_field: str, al
timerange (str): The time range to collect alerts from. This is a string like "24h", "1w", etc.
alert_field (str): The field to match.
alert_value (str): The value to match.
timestamp_field (str): The timestamp field to sort by.
Returns:
Dict[str, int]: A dictionary containing success status and the number of alerts per host or an error message.
Expand All @@ -225,7 +250,13 @@ def collect_alerts_by_host(self, size: int, timerange: str, alert_field: str, al
alerts_by_host_dict = {}
matches = [(alert_field, alert_value)]
for index_name in indices_validation["indices"]:
alerts = self._collect_alerts(index_name=index_name, size=size, timerange=timerange, matches=matches)
alerts = self._collect_alerts(
index_name=index_name,
size=size,
timerange=timerange,
matches=matches,
timestamp_field=timestamp_field,
)
if alerts["success"]:
for alert in alerts["alerts"]:
host = alert["_source"]["agent_name"]
Expand All @@ -239,7 +270,7 @@ def collect_alerts_by_host(self, size: int, timerange: str, alert_field: str, al
"alerts_by_host": alerts_by_host_list,
}

def collect_alerts_by_rule(self, size: int, timerange: str, alert_field: str, alert_value: str) -> Dict[str, int]:
def collect_alerts_by_rule(self, size: int, timerange: str, alert_field: str, alert_value: str, timestamp_field: str) -> Dict[str, int]:
"""
Collects the number of alerts per rule.
Expand All @@ -248,6 +279,7 @@ def collect_alerts_by_rule(self, size: int, timerange: str, alert_field: str, al
timerange (str): The time range to collect alerts from. This is a string like "24h", "1w", etc.
alert_field (str): The field to match.
alert_value (str): The value to match.
timestamp_field (str): The timestamp field to sort by.
Returns:
Dict[str, int]: A dictionary containing success status and the number of alerts per rule or an error message.
Expand All @@ -259,7 +291,13 @@ def collect_alerts_by_rule(self, size: int, timerange: str, alert_field: str, al
alerts_by_rule_dict = {}
matches = [(alert_field, alert_value)]
for index_name in indices_validation["indices"]:
alerts = self._collect_alerts(index_name=index_name, size=size, timerange=timerange, matches=matches)
alerts = self._collect_alerts(
index_name=index_name,
size=size,
timerange=timerange,
matches=matches,
timestamp_field=timestamp_field,
)
if alerts["success"]:
for alert in alerts["alerts"]:
rule = alert["_source"]["rule_description"]
Expand All @@ -273,7 +311,14 @@ def collect_alerts_by_rule(self, size: int, timerange: str, alert_field: str, al
"alerts_by_rule": alerts_by_rule_list,
}

def collect_alerts_by_rule_per_host(self, size: int, timerange: str, alert_field: str, alert_value: str) -> Dict[str, int]:
def collect_alerts_by_rule_per_host(
self,
size: int,
timerange: str,
alert_field: str,
alert_value: str,
timestamp_field: str,
) -> Dict[str, int]:
"""
Collects the number of alerts per rule per host.
Expand All @@ -282,6 +327,7 @@ def collect_alerts_by_rule_per_host(self, size: int, timerange: str, alert_field
timerange (str): The time range to collect alerts from. This is a string like "24h", "1w", etc.
alert_field (str): The field to match.
alert_value (str): The value to match.
timestamp_field (str): The timestamp field to sort by.
Returns:
Dict[str, int]: A dictionary containing success status and the number of alerts per rule per host or an error message.
Expand All @@ -293,7 +339,13 @@ def collect_alerts_by_rule_per_host(self, size: int, timerange: str, alert_field
alerts_by_rule_per_host_dict = {}
matches = [(alert_field, alert_value)]
for index_name in indices_validation["indices"]:
alerts = self._collect_alerts(index_name=index_name, size=size, timerange=timerange, matches=matches)
alerts = self._collect_alerts(
index_name=index_name,
size=size,
timerange=timerange,
matches=matches,
timestamp_field=timestamp_field,
)
if alerts["success"]:
for alert in alerts["alerts"]:
rule = alert["_source"]["rule_description"]
Expand Down Expand Up @@ -325,6 +377,7 @@ def _collect_alerts(
size: int = None,
timerange: str = "24h",
matches: Iterable[Tuple[str, str]] = None,
timestamp_field: str = None,
) -> Dict[str, object]:
"""
Elasticsearch query to get the most recent alerts where the `rule_level` is 12 or higher or the
Expand All @@ -337,6 +390,7 @@ def _collect_alerts(
timerange (str, optional): The time range to collect alerts from. This is a string like "24h", "1w", etc.
matches (Iterable[Tuple[str, str]], optional): A list of tuples representing the field and value to match.
I.E: [("syslog_level", "ALERT"), ("agent_name", "WIN-39O01J5F7G5")]
timestamp_field (str, optional): The timestamp field to sort by.
Returns:
Dict[str, object]: A dictionary containing success status and alerts or an error message.
Expand All @@ -345,7 +399,7 @@ def _collect_alerts(

# Use QueryBuilder to construct the query
query_builder = QueryBuilder()
query_builder.add_time_range(timerange)
query_builder.add_time_range(timerange, timestamp_field=timestamp_field)
if matches is not None:
query_builder.add_matches(matches)
else:
Expand Down
4 changes: 2 additions & 2 deletions backend/app/services/WazuhIndexer/universal.py
Original file line number Diff line number Diff line change
Expand Up @@ -192,9 +192,9 @@ def __init__(self):
"sort": [],
}

def add_time_range(self, timerange: str):
def add_time_range(self, timerange: str, timestamp_field: str):
start = self._get_time_range_start(timerange)
self.query["query"]["bool"]["must"].append({"range": {"timestamp_utc": {"gte": start, "lte": "now"}}})
self.query["query"]["bool"]["must"].append({"range": {timestamp_field: {"gte": start, "lte": "now"}}})
return self

def add_matches(self, matches: Iterable[Tuple[str, str]]):
Expand Down
Loading

0 comments on commit c21cc94

Please sign in to comment.