1
1
"""
2
2
Graylog Provider is a class that allows to install webhooks in Graylog.
3
3
"""
4
+ # Documentation for older versions of graylog: https://github.com/Graylog2/documentation
4
5
5
6
import dataclasses
6
7
import math
@@ -67,6 +68,8 @@ class GraylogProvider(BaseProvider):
67
68
2. Click "Create Notification".
68
69
3. In the New Notification form, configure:
69
70
71
+ **Note**: For Graylog v4.x please set the **URL** to `{keep_webhook_api_url}?api_key={api_key}`.
72
+
70
73
- **Display Name**: keep-graylog-webhook-integration
71
74
- **Title**: keep-graylog-webhook-integration
72
75
- **Notification Type**: Custom HTTP Notification
@@ -105,6 +108,7 @@ def __init__(
105
108
):
106
109
super ().__init__ (context_manager , provider_id , config )
107
110
self ._host = None
111
+ self .is_v4 = self .__get_graylog_version ().startswith ("4" )
108
112
109
113
def dispose (self ):
110
114
"""
@@ -224,6 +228,22 @@ def validate_scopes(self) -> dict[str, bool | str]:
224
228
"authorized" : authorized ,
225
229
}
226
230
231
+ def __get_graylog_version (self ) -> str :
232
+ self .logger .info ("Getting graylog version info" )
233
+ try :
234
+ version_response = requests .get (
235
+ url = self .__get_url (),
236
+ headers = self ._headers
237
+ )
238
+ if version_response .status_code != 200 :
239
+ raise Exception (version_response .text )
240
+ version = version_response .json ()["version" ].strip ()
241
+ self .logger .info (f"We are working with Graylog version: { version } " )
242
+ return version
243
+ except Exception as e :
244
+ self .logger .error ("Error while getting Graylog Version" , extra = {"exception" : str (e )})
245
+
246
+
227
247
def __get_url_whitelist (self ):
228
248
try :
229
249
self .logger .info ("Fetching URL Whitelist" )
@@ -410,6 +430,16 @@ def setup_webhook(
410
430
self , tenant_id : str , keep_api_url : str , api_key : str , setup_alerts : bool = True
411
431
):
412
432
self .logger .info ("Setting up webhook in Graylog" )
433
+
434
+ # Extracting provider_id from the keep_api_url
435
+ parsed_url = urlparse (keep_api_url )
436
+ query_params = parsed_url .query
437
+ provider_id = query_params .split ("provider_id=" )[- 1 ]
438
+ notification_name = f"Keep-{ provider_id } "
439
+
440
+ if self .is_v4 :
441
+ keep_api_url = f"{ keep_api_url } &api_key={ api_key } "
442
+
413
443
try :
414
444
event_definitions = []
415
445
events_1 = self .__get_events (page = 1 , per_page = 100 )
@@ -422,12 +452,6 @@ def setup_webhook(
422
452
self .__get_events (page = page , per_page = 100 )["event_definitions" ]
423
453
)
424
454
425
- # Extracting provider_id from the keep_api_url
426
- parsed_url = urlparse (keep_api_url )
427
- query_params = parsed_url .query
428
- provider_id = query_params .split ("provider_id=" )[- 1 ]
429
- notification_name = f"Keep-{ provider_id } "
430
-
431
455
# Whitelist URL
432
456
url_whitelist = self .__get_url_whitelist ()
433
457
url_found = False
@@ -452,17 +476,27 @@ def setup_webhook(
452
476
notification = self .__get_notification (
453
477
page = 1 , per_page = 1 , notification_name = notification_name
454
478
)
479
+
480
+ existing_notification_id = None
481
+
455
482
if int (notification ["count" ]) > 0 :
456
483
self .logger .info ("Notification already exists, deleting it" )
484
+
485
+ # We need to clean up the previously installed notification
486
+ existing_notification_id = notification ["notifications" ][0 ]["id" ]
487
+
457
488
self .__delete_notification (
458
- notification_id = notification [ "notifications" ][ 0 ][ "id" ]
489
+ notification_id = existing_notification_id
459
490
)
460
491
461
492
self .logger .info ("Creating new notification" )
462
- notification_body = {
463
- "title" : notification_name ,
464
- "description" : "Hello, this Notification is created by Keep, please do not change the title." ,
465
- "config" : {
493
+ if self .is_v4 :
494
+ config = {
495
+ "type" : "http-notification-v1" ,
496
+ "url" : keep_api_url
497
+ }
498
+ else :
499
+ config = {
466
500
"type" : "http-notification-v2" ,
467
501
"basic_auth" : None ,
468
502
"api_key_as_header" : False ,
@@ -475,17 +509,28 @@ def setup_webhook(
475
509
"content_type" : "JSON" ,
476
510
"headers" : f"X-API-KEY:{ api_key } " ,
477
511
"body_template" : "" ,
478
- },
512
+ }
513
+ notification_body = {
514
+ "title" : notification_name ,
515
+ "description" : "Hello, this Notification is created by Keep, please do not change the title." ,
516
+ "config" : config ,
479
517
}
480
518
new_notification = self .__create_notification (
481
519
notification_name = notification_name , notification_body = notification_body
482
520
)
483
521
484
522
for event_definition in event_definitions :
485
- if event_definition ["_scope" ] == "SYSTEM_NOTIFICATION_EVENT" :
523
+ if not self . is_v4 and event_definition ["_scope" ] == "SYSTEM_NOTIFICATION_EVENT" :
486
524
self .logger .info ("Skipping SYSTEM_NOTIFICATION_EVENT" )
487
525
continue
488
526
self .logger .info (f"Updating event with ID: { event_definition ['id' ]} " )
527
+
528
+ # Attempting to clean up the deleted notification from the event, it is not handled well in Graylog v4.
529
+ for ind , notification in enumerate (event_definition ["notifications" ]):
530
+ if notification ["notification_id" ] == existing_notification_id :
531
+ event_definition ["notifications" ].pop (ind )
532
+ break
533
+
489
534
event_definition ["notifications" ].append (
490
535
{"notification_id" : new_notification ["id" ]}
491
536
)
0 commit comments