@cryptotaxi247 / CoPilot / commits / 1087e11b

POST for all alert related endpoints (#61)

modified to post so the end user could specify what the alert field and value need to be

taylor_socfortress committed Jul 25, 2023 at 09:51 UTC 1087e11b4e9a7d2d6f4cda83ce0d620b7a4241f0
3 files changed +210 -90
backend/app/routes/alerts.py
+21 -12
@@ -94,7 +94,7 @@ def get_alerts_by_index() -> jsonify:
94 return jsonify(alerts)
95
96
97 -@bp.route("/alerts/hosts", methods=["GET"])
97 +@bp.route("/alerts/hosts", methods=["POST"])
98 def get_hosts() -> jsonify:
99 """
100 Retrieves all hosts from the AlertsService that have an alert.
@@ -107,14 +107,17 @@ def get_hosts() -> jsonify:
107 jsonify: A JSON response containing a list of hosts. Each item in the list is a dictionary representing a host,
108 containing all its associated data.
109 """
110 - size = request.args.get("size", default=10, type=int)
111 - timerange = request.args.get("timerange", default="24h", type=str)
110 + data = request.json
111 + size = int(data.get("size", 10))
112 + timerange = str(data.get("timerange", "24h"))
113 + alert_field = str(data.get("alert_field", "syslog_level"))
114 + alert_value = str(data.get("alert_value", "ALERT"))
115 service = AlertsService()
113 - hosts = service.collect_alerts_by_host(size=size, timerange=timerange)
116 + hosts = service.collect_alerts_by_host(size=size, timerange=timerange, alert_field=alert_field, alert_value=alert_value)
117 return jsonify(hosts)
118
119
117 -@bp.route("/alerts/rules", methods=["GET"])
120 +@bp.route("/alerts/rules", methods=["POST"])
121 def get_rules() -> jsonify:
122 """
123 Retrieves all rules from the AlertsService that have an alert.
@@ -127,14 +130,17 @@ def get_rules() -> jsonify:
130 jsonify: A JSON response containing a list of rules. Each item in the list is a dictionary representing a rule,
131 containing all its associated data.
132 """
130 - size = request.args.get("size", default=10, type=int)
131 - timerange = request.args.get("timerange", default="24h", type=str)
133 + data = request.json
134 + size = int(data.get("size", 10))
135 + timerange = str(data.get("timerange", "24h"))
136 + alert_field = str(data.get("alert_field", "syslog_level"))
137 + alert_value = str(data.get("alert_value", "ALERT"))
138 service = AlertsService()
133 - rules = service.collect_alerts_by_rule(size=size, timerange=timerange)
139 + rules = service.collect_alerts_by_rule(size=size, timerange=timerange, alert_field=alert_field, alert_value=alert_value)
140 return jsonify(rules)
141
142
137 -@bp.route("/alerts/rules/host", methods=["GET"])
143 +@bp.route("/alerts/rules/host", methods=["POST"])
144 def get_rules_by_host() -> jsonify:
145 """
146 Retrieves all rules from the AlertsService that have an alert and organizes by host.
@@ -147,10 +153,13 @@ def get_rules_by_host() -> jsonify:
153 jsonify: A JSON response containing a list of rules. Each item in the list is a dictionary representing a rule,
154 containing all its associated data.
155 """
150 - size = request.args.get("size", default=10, type=int)
151 - timerange = request.args.get("timerange", default="24h", type=str)
156 + data = request.json
157 + size = int(data.get("size", 10))
158 + timerange = str(data.get("timerange", "24h"))
159 + alert_field = str(data.get("alert_field", "syslog_level"))
160 + alert_value = str(data.get("alert_value", "ALERT"))
161 service = AlertsService()
153 - rules = service.collect_alerts_by_rule_per_host(size=size, timerange=timerange)
162 + rules = service.collect_alerts_by_rule_per_host(size=size, timerange=timerange, alert_field=alert_field, alert_value=alert_value)
163 return jsonify(rules)
164
165
backend/app/services/WazuhIndexer/alerts.py
+15 -6
@@ -205,13 +205,15 @@ class AlertsService:
205 "alerts_by_agent": alerts_by_agent_list,
206 }
207
208 - def collect_alerts_by_host(self, size: int, timerange: str) -> Dict[str, int]:
208 + def collect_alerts_by_host(self, size: int, timerange: str, alert_field: str, alert_value: str) -> Dict[str, int]:
209 """
210 Collects the number of alerts per host.
211
212 Args:
213 size (int): The maximum number of alerts to return.
214 timerange (str): The time range to collect alerts from. This is a string like "24h", "1w", etc.
215 + alert_field (str): The field to match.
216 + alert_value (str): The value to match.
217
218 Returns:
219 Dict[str, int]: A dictionary containing success status and the number of alerts per host or an error message.
@@ -221,8 +223,9 @@ class AlertsService:
223 return indices_validation
224
225 alerts_by_host_dict = {}
226 + matches = [(alert_field, alert_value)]
227 for index_name in indices_validation["indices"]:
225 - alerts = self._collect_alerts(index_name=index_name, size=size, timerange=timerange)
228 + alerts = self._collect_alerts(index_name=index_name, size=size, timerange=timerange, matches=matches)
229 if alerts["success"]:
230 for alert in alerts["alerts"]:
231 host = alert["_source"]["agent_name"]
@@ -236,13 +239,15 @@ class AlertsService:
239 "alerts_by_host": alerts_by_host_list,
240 }
241
239 - def collect_alerts_by_rule(self, size: int, timerange: str) -> Dict[str, int]:
242 + def collect_alerts_by_rule(self, size: int, timerange: str, alert_field: str, alert_value: str) -> Dict[str, int]:
243 """
244 Collects the number of alerts per rule.
245
246 Args:
247 size (int): The maximum number of alerts to return.
248 timerange (str): The time range to collect alerts from. This is a string like "24h", "1w", etc.
249 + alert_field (str): The field to match.
250 + alert_value (str): The value to match.
251
252 Returns:
253 Dict[str, int]: A dictionary containing success status and the number of alerts per rule or an error message.
@@ -252,8 +257,9 @@ class AlertsService:
257 return indices_validation
258
259 alerts_by_rule_dict = {}
260 + matches = [(alert_field, alert_value)]
261 for index_name in indices_validation["indices"]:
256 - alerts = self._collect_alerts(index_name=index_name, size=size, timerange=timerange)
262 + alerts = self._collect_alerts(index_name=index_name, size=size, timerange=timerange, matches=matches)
263 if alerts["success"]:
264 for alert in alerts["alerts"]:
265 rule = alert["_source"]["rule_description"]
@@ -267,13 +273,15 @@ class AlertsService:
273 "alerts_by_rule": alerts_by_rule_list,
274 }
275
270 - def collect_alerts_by_rule_per_host(self, size: int, timerange: str) -> Dict[str, int]:
276 + def collect_alerts_by_rule_per_host(self, size: int, timerange: str, alert_field: str, alert_value: str) -> Dict[str, int]:
277 """
278 Collects the number of alerts per rule per host.
279
280 Args:
281 size (int): The maximum number of alerts to return.
282 timerange (str): The time range to collect alerts from. This is a string like "24h", "1w", etc.
283 + alert_field (str): The field to match.
284 + alert_value (str): The value to match.
285
286 Returns:
287 Dict[str, int]: A dictionary containing success status and the number of alerts per rule per host or an error message.
@@ -283,8 +291,9 @@ class AlertsService:
291 return indices_validation
292
293 alerts_by_rule_per_host_dict = {}
294 + matches = [(alert_field, alert_value)]
295 for index_name in indices_validation["indices"]:
287 - alerts = self._collect_alerts(index_name=index_name, size=size, timerange=timerange)
296 + alerts = self._collect_alerts(index_name=index_name, size=size, timerange=timerange, matches=matches)
297 if alerts["success"]:
298 for alert in alerts["alerts"]:
299 rule = alert["_source"]["rule_description"]
backend/app/static/swagger.json
+174 -72
@@ -1242,31 +1242,41 @@
1242 }
1243 },
1244 "/alerts/hosts": {
1245 - "get": {
1246 - "summary": "Get hosts with alerts",
1247 - "description": "Endpoint to get hosts with alerts.",
1248 - "parameters": [
1249 - {
1250 - "name": "size",
1251 - "in": "query",
1252 - "description": "The number of alerts to return. Defaults to 10.",
1253 - "required": false,
1254 - "schema": {
1255 - "type": "integer",
1256 - "default": 10
1257 - }
1258 - },
1259 - {
1260 - "name": "timerange",
1261 - "in": "query",
1262 - "description": "The time range to consider for alerts. Defaults to '24h'.",
1263 - "required": false,
1264 - "schema": {
1265 - "type": "string",
1266 - "default": "24h"
1245 + "post": {
1246 + "summary": "Create and get hosts with alerts",
1247 + "description": "Endpoint to create and get hosts with alerts. Retrieves all available hosts from the AlertsService based on the provided parameters.",
1248 + "requestBody": {
1249 + "content": {
1250 + "application/json": {
1251 + "schema": {
1252 + "type": "object",
1253 + "properties": {
1254 + "size": {
1255 + "type": "integer",
1256 + "default": 10,
1257 + "description": "The number of alerts to return. Defaults to 10."
1258 + },
1259 + "timerange": {
1260 + "type": "string",
1261 + "default": "24h",
1262 + "description": "The time range to consider for alerts. Defaults to '24h'."
1263 + },
1264 + "alert_field": {
1265 + "type": "string",
1266 + "default": "syslog_level",
1267 + "description": "Field to filter alerts on. Defaults to 'syslog_level'."
1268 + },
1269 + "alert_value": {
1270 + "type": "string",
1271 + "default": "ALERT",
1272 + "description": "Value to filter alerts on. Defaults to 'ALERT'."
1273 + }
1274 + },
1275 + "required": []
1276 + }
1277 }
1278 }
1269 - ],
1279 + },
1280 "responses": {
1281 "200": {
1282 "description": "Successful operation",
@@ -1287,6 +1297,42 @@
1297 }
1298 }
1299 },
1300 + "400": {
1301 + "description": "Bad request",
1302 + "content": {
1303 + "application/json": {
1304 + "schema": {
1305 + "type": "object",
1306 + "properties": {
1307 + "message": {
1308 + "type": "string"
1309 + },
1310 + "success": {
1311 + "type": "boolean"
1312 + }
1313 + }
1314 + }
1315 + }
1316 + }
1317 + },
1318 + "404": {
1319 + "description": "Index not found",
1320 + "content": {
1321 + "application/json": {
1322 + "schema": {
1323 + "type": "object",
1324 + "properties": {
1325 + "message": {
1326 + "type": "string"
1327 + },
1328 + "success": {
1329 + "type": "boolean"
1330 + }
1331 + }
1332 + }
1333 + }
1334 + }
1335 + },
1336 "default": {
1337 "description": "Unexpected error",
1338 "content": {
@@ -1298,36 +1344,46 @@
1344 }
1345 }
1346 },
1301 - "operationId": "getHostsWithAlerts",
1347 + "operationId": "createAndGetHostsWithAlerts",
1348 "tags": ["Wazuh-Indexer"]
1349 }
1350 },
1351 "/alerts/rules": {
1306 - "get": {
1307 - "summary": "Get rules with alerts",
1308 - "description": "Endpoint to get rules with alerts.",
1309 - "parameters": [
1310 - {
1311 - "name": "size",
1312 - "in": "query",
1313 - "description": "The number of alerts to return. Defaults to 10.",
1314 - "required": false,
1315 - "schema": {
1316 - "type": "integer",
1317 - "default": 10
1318 - }
1319 - },
1320 - {
1321 - "name": "timerange",
1322 - "in": "query",
1323 - "description": "The time range to consider for alerts. Defaults to '24h'.",
1324 - "required": false,
1325 - "schema": {
1326 - "type": "string",
1327 - "default": "24h"
1352 + "post": {
1353 + "summary": "Create and get rules with alerts",
1354 + "description": "Endpoint to create and get rules with alerts. Retrieves all available rules from the AlertsService based on the provided parameters.",
1355 + "requestBody": {
1356 + "content": {
1357 + "application/json": {
1358 + "schema": {
1359 + "type": "object",
1360 + "properties": {
1361 + "size": {
1362 + "type": "integer",
1363 + "default": 10,
1364 + "description": "The number of alerts to return. Defaults to 10."
1365 + },
1366 + "timerange": {
1367 + "type": "string",
1368 + "default": "24h",
1369 + "description": "The time range to consider for alerts. Defaults to '24h'."
1370 + },
1371 + "alert_field": {
1372 + "type": "string",
1373 + "default": "syslog_level",
1374 + "description": "Field to filter alerts on. Defaults to 'syslog_level'."
1375 + },
1376 + "alert_value": {
1377 + "type": "string",
1378 + "default": "ALERT",
1379 + "description": "Value to filter alerts on. Defaults to 'ALERT'."
1380 + }
1381 + },
1382 + "required": []
1383 + }
1384 }
1385 }
1330 - ],
1386 + },
1387 "responses": {
1388 "200": {
1389 "description": "Successful operation",
@@ -1348,6 +1404,42 @@
1404 }
1405 }
1406 },
1407 + "400": {
1408 + "description": "Bad request",
1409 + "content": {
1410 + "application/json": {
1411 + "schema": {
1412 + "type": "object",
1413 + "properties": {
1414 + "message": {
1415 + "type": "string"
1416 + },
1417 + "success": {
1418 + "type": "boolean"
1419 + }
1420 + }
1421 + }
1422 + }
1423 + }
1424 + },
1425 + "404": {
1426 + "description": "Index not found",
1427 + "content": {
1428 + "application/json": {
1429 + "schema": {
1430 + "type": "object",
1431 + "properties": {
1432 + "message": {
1433 + "type": "string"
1434 + },
1435 + "success": {
1436 + "type": "boolean"
1437 + }
1438 + }
1439 + }
1440 + }
1441 + }
1442 + },
1443 "default": {
1444 "description": "Unexpected error",
1445 "content": {
@@ -1359,36 +1451,46 @@
1451 }
1452 }
1453 },
1362 - "operationId": "getRulesWithAlerts",
1454 + "operationId": "createAndGetRulesWithAlerts",
1455 "tags": ["Wazuh-Indexer"]
1456 }
1457 },
1458 "/alerts/rules/host": {
1367 - "get": {
1368 - "summary": "Get rules with alerts per host",
1369 - "description": "Endpoint to get rules with alerts per host",
1370 - "parameters": [
1371 - {
1372 - "name": "size",
1373 - "in": "query",
1374 - "description": "The number of alerts to return. Defaults to 10.",
1375 - "required": false,
1376 - "schema": {
1377 - "type": "integer",
1378 - "default": 10
1379 - }
1380 - },
1381 - {
1382 - "name": "timerange",
1383 - "in": "query",
1384 - "description": "The time range to consider for alerts. Defaults to '24h'.",
1385 - "required": false,
1386 - "schema": {
1387 - "type": "string",
1388 - "default": "24h"
1459 + "post": {
1460 + "summary": "Create and get rules with alerts per host",
1461 + "description": "Endpoint to create and get rules with alerts per host. Retrieves all available rules from the AlertsService based on the provided parameters and organizes them by host.",
1462 + "requestBody": {
1463 + "content": {
1464 + "application/json": {
1465 + "schema": {
1466 + "type": "object",
1467 + "properties": {
1468 + "size": {
1469 + "type": "integer",
1470 + "default": 10,
1471 + "description": "The number of alerts to return. Defaults to 10."
1472 + },
1473 + "timerange": {
1474 + "type": "string",
1475 + "default": "24h",
1476 + "description": "The time range to consider for alerts. Defaults to '24h'."
1477 + },
1478 + "alert_field": {
1479 + "type": "string",
1480 + "default": "syslog_level",
1481 + "description": "Field to filter alerts on. Defaults to 'syslog_level'."
1482 + },
1483 + "alert_value": {
1484 + "type": "string",
1485 + "default": "ALERT",
1486 + "description": "Value to filter alerts on. Defaults to 'ALERT'."
1487 + }
1488 + },
1489 + "required": []
1490 + }
1491 }
1492 }
1391 - ],
1493 + },
1494 "responses": {
1495 "200": {
1496 "description": "Successful operation",
@@ -1456,7 +1558,7 @@
1558 }
1559 }
1560 },
1459 - "operationId": "getRulesWithAlertsFromHost",
1561 + "operationId": "createAndGetRulesWithAlertsFromHost",
1562 "tags": ["Wazuh-Indexer"]
1563 }
1564 },