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
},