diff --git a/config.py b/config.py index 2187c5c18ab7cc1f2ce209f3b922cd97cb721353..a1deb53af4ea08ac3380be95bdf933fbf9b565a0 100644 --- a/config.py +++ b/config.py @@ -512,6 +512,17 @@ class Config(BaseConfig): retry_timeout = IntParameter(default=2) use_proxy = BooleanParameter(default=False) + class webhook(ConfigSection): + url = SecretParameter() + message = StringParameter() + sender = StringParameter() + received = StringParameter() + options = StringParameter() + # Method default False, use GET method + method = BooleanParameter(default=False) + retry_timeout = IntParameter(default=2) + use_proxy = BooleanParameter(default=False) + class threadpool(ConfigSection): idle_timeout = SecondsParameter(default="30s") shutdown_timeout = SecondsParameter(default="1M") diff --git a/core/config/proto/legacy.py b/core/config/proto/legacy.py index 97ae26d3b0d3284079582fde14cf1cf6389276c4..d2308f57b73033d2bbf0f1a917528423020cb7b3 100644 --- a/core/config/proto/legacy.py +++ b/core/config/proto/legacy.py @@ -138,6 +138,19 @@ class LegacyProtocol(BaseProtocol): # TgSender ("tgsender.token", "tgsender.token"), ("tgsender-global-%(node)s.token", "tgsender.token"), + # WebHook + ("webhook.url", "webhook.url"), + ("webhook-global-%(node)s.url", "webhook.url"), + ("webhook.message", "webhook.message"), + ("webhook-global-%(node)s.message", "webhook.message"), + ("webhook.sender", "webhook.sender"), + ("webhook-global-%(node)s.sender", "webhook.sender"), + ("webhook.received", "webhook.received"), + ("webhook-global-%(node)s.received", "webhook.received"), + ("webhook.options", "webhook.options"), + ("webhook-global-%(node)s.options", "webhook.options"), + ("webhook.method", "webhook.method"), + ("webhook-global-%(node)s.method", "webhook.method"), # TrapCollector ("trapcollector.listen_traps", "trapcollector.listen"), ("trapcollector-%(pool)s-%(node)s.listen_traps", "trapcollector.listen"), diff --git a/main/models/notificationgroup.py b/main/models/notificationgroup.py index 257cc9967770b07369e010bf22df6ceeed656c09..2c6040f77f73f66f3b2668920ee098680a84f908 100644 --- a/main/models/notificationgroup.py +++ b/main/models/notificationgroup.py @@ -29,7 +29,8 @@ logger = logging.getLogger(__name__) NOTIFICATION_TOPICS = { "mail": "mailsender", - "tg": "tgsender" + "tg": "tgsender", + "wh": "webhook" } NOTIFICATION_METHOD_CHOICES = [ diff --git a/services/webhook/__init__.py b/services/webhook/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/services/webhook/service.py b/services/webhook/service.py new file mode 100644 index 0000000000000000000000000000000000000000..f07863a4725c48ff2634c72843ca9a522353f535 --- /dev/null +++ b/services/webhook/service.py @@ -0,0 +1,106 @@ +#!./bin/python +# -*- coding: utf-8 -*- +# ---------------------------------------------------------------------- +# webhook service +# ---------------------------------------------------------------------- +# Copyright (C) 2007-2019 The NOC Project +# See LICENSE for details +# ---------------------------------------------------------------------- + +# Third-party modules +import re +import datetime +import time +import urllib +# NOC modules +from noc.core.service.base import Service +from noc.core.http.client import fetch_sync +from noc.core.perf import metrics +from noc.config import config + + +class WebhookService(Service): + name = "webhook" + + def __init__(self, *args, **kwargs): + super(WebhookService, self).__init__(*args, **kwargs) + self.url = config.webhook.url + self.message = config.webhook.message + self.sender = config.webhook.sender + self.method = "POST" if config.webhook.method is True else "GET" + self.received = config.webhook.received + self.options = config.webhook.options + + def on_activate(self): + if self.url and self.message and self.received: + self.subscribe( + topic=self.name, + channel="sender", + handler=self.on_message + ) + + def on_message(self, message, address, subject, body, **kwargs): + self.logger.info( + "[%s] Receiving message: %s (%s) [%s, attempt %d]", + message.id, subject, address, + datetime.datetime.fromtimestamp( + message.timestamp / 1000000000.0 + ), + message.attempts + ) + return self.send_tb(message.id, address, subject, body) + + def _str(self, uni): + ''' Make inbound a string Encoding to utf-8 if needed ''' + try: + return str(uni) + except Exception as e: + self.logger.error("Not str() -> %s failed: %s", uni, e) + return uni.encode('utf-8') + + @staticmethod + def escape_markdown(text): + """Helper function to escape telegram markup symbols""" + escape_chars = '\*_`' + return re.sub(r'([%s])' % escape_chars, r'\\\1', text) + + def send_tb(self, messages, address, subject, body): + # proxy_addres = config.proxy.https_proxy # not used. + sendMessage = self._str(subject + '\n' + body) + time.sleep(config.webhook.retry_timeout) + if self.url and self.message and self.received: + url = self.url + if self.received: + url = url + "%s%s" % (self.received, address) + if self.sender: + url = url + self.sender + url = url + "%s%s" % (self.message, urllib.quote(sendMessage)) + if self.options: + url = url + self.options + self.logger.info("HTTP %s %s", self.method, url) + try: + code, header, body = fetch_sync( + url, + method=self.method, + allow_proxy=True, + request_timeout=config.activator.http_request_timeout, + follow_redirects=True, + validate_cert=config.activator.http_validate_cert, + ) + if 200 <= code <= 299: + self.logger.info("Result: %s" % body) + metrics["webhook_proxy_sended_ok"] += 1 + return True + else: + self.logger.error("HTTP %s %s failed: %s %s", self.method, url, code, body) + metrics["webhook_proxy_failed_httperror"] += 1 + return False + except Exception as e: + self.logger.error("HTTP %s failed: %s", self.method, e) + else: + self.logger.info("No Url, no message, no sender, no received") + return False + + +if __name__ == "__main__": + WebhookService().start() diff --git a/ui/web/main/notificationgroup/Application.js b/ui/web/main/notificationgroup/Application.js index ca09b4a0b0ba8b63f565c33ba059db0141313cb6..054287ea1247bd50184455dfe9f2127d458bb772 100644 --- a/ui/web/main/notificationgroup/Application.js +++ b/ui/web/main/notificationgroup/Application.js @@ -85,6 +85,7 @@ Ext.define("NOC.main.notificationgroup.Application", { store: [ ["mail", "Mail"], ["tg", "Telegram"], + ["wh", "Webhook"], ["file", "File"], ["xmpp", "Jabber"] ]