From 0a5e362cf5709763bc3220c0daa81431c731d0cb Mon Sep 17 00:00:00 2001 From: azazelm3dj3d <56496067+azazelm3dj3d@users.noreply.github.com> Date: Tue, 3 Oct 2023 15:18:05 -0500 Subject: [PATCH] Add BugnSnag to docs + some error handling --- config.example.yml | 4 +++ docs/extras.rst | 13 ++++++++ threatingestor/__init__.py | 54 ++++++++++++++++++++++++++------ threatingestor/bugsnagmonitor.py | 20 ------------ 4 files changed, 61 insertions(+), 30 deletions(-) delete mode 100644 threatingestor/bugsnagmonitor.py diff --git a/config.example.yml b/config.example.yml index 0eb167b..19c563b 100644 --- a/config.example.yml +++ b/config.example.yml @@ -46,6 +46,10 @@ credentials: key: MY_API_KEY ssl: False +error_reporting: + - name: bugsnag + api_key: API_KEY + sources: # This section defines each of the input sources for ThreatIngestor. # Define as many as you want. ThreatIngestor maintains a "state" for each of diff --git a/docs/extras.rst b/docs/extras.rst index fc6f175..761708a 100644 --- a/docs/extras.rst +++ b/docs/extras.rst @@ -3,6 +3,19 @@ Extras There are a few extra tools included alongside ThreatIngestor, that didn't quite make sense as sources or operators. +BugSnag +------- + +BugSnag monitoring is a valuable tool to have when running in daemon mode. Adding it is extremely simple and the only requirement is to have an API key. + +Here's an example to include in your ``config.yml``: + +.. code-block:: yaml + + error_reporting: + - name: bugsnag + api_key: API_KEY + Quick Webapp ------------ diff --git a/threatingestor/__init__.py b/threatingestor/__init__.py index c8f8c22..d931efe 100644 --- a/threatingestor/__init__.py +++ b/threatingestor/__init__.py @@ -12,12 +12,29 @@ logger.info("Notifiers is not installed.") notifiers = None +try: + import bugsnag + bugsnag_imported = True +except ImportError: + logger.info("BugSnag is not installed.") + bugsnag_imported = False + import threatingestor.config import threatingestor.state import threatingestor.exceptions import threatingestor.whitelist -from threatingestor.bugsnagmonitor import configure_bugsnag, send_notification +BUGSNAG_ACTIVE = False + +def bugsnag_notification(msg=None, metadata=None) -> None: + """ + Monitor your code with BugSnag + + You can include a additional information with the `metadata` paramater. + """ + + if bugsnag_imported: + bugsnag.notify(Exception(msg), metadata={"ThreatIngestor" : metadata}) class Ingestor: """ThreatIngestor main work logic. @@ -63,12 +80,17 @@ def __init__(self, config_file): except TypeError: logger.exception("Couldn't initialize statsd client; bad config?") sys.exit(1) - + # Configure BugSnag - for service in self.config.error_reporting(): - if service['name'] == "bugsnag": - configure_bugsnag(service['api_key']) - break + if bugsnag_imported: + for service in self.config.error_reporting(): + if service['name'] == "bugsnag": + if service['api_key']: + bugsnag.configure(api_key=service['api_key']) + logger.debug("BugSnag configured") + BUGSNAG_ACTIVE = True + + break # Load state DB. try: @@ -77,7 +99,10 @@ def __init__(self, config_file): except (OSError, IOError, threatingestor.exceptions.IngestorError): # Error loading state DB. logger.exception("Error reading state database") - send_notification("Error reading state database") + + if BUGSNAG_ACTIVE: + bugsnag_notification("Error reading state database") + sys.exit(1) # Instantiate plugins. @@ -95,7 +120,10 @@ def __init__(self, config_file): except (TypeError, ConnectionError, threatingestor.exceptions.PluginError): logger.exception("Error initializing plugins") - send_notification("Error initializing plugins") + + if BUGSNAG_ACTIVE: + bugsnag_notification("Error initializing plugins") + sys.exit(1) def _is_whitelisted(self, artifact) -> bool: @@ -132,7 +160,10 @@ def run_once(self): except Exception: self.statsd.incr(f'error.source.{source}') logger.exception(f"Unknown error in source '{source}'") - send_notification(f"Unknown error in source '{source}'") + + if BUGSNAG_ACTIVE: + bugsnag_notification(f"Unknown error in source '{source}'") + continue # Save the source state. @@ -155,7 +186,10 @@ def run_once(self): except Exception: self.statsd.incr(f'error.operator.{operator}') logger.exception(f"Unknown error in operator '{operator}'") - send_notification(f"Unknown error in operator '{operator}'") + + if BUGSNAG_ACTIVE: + bugsnag_notification(f"Unknown error in operator '{operator}'") + continue # Record stats and update the summary. diff --git a/threatingestor/bugsnagmonitor.py b/threatingestor/bugsnagmonitor.py deleted file mode 100644 index 216f40f..0000000 --- a/threatingestor/bugsnagmonitor.py +++ /dev/null @@ -1,20 +0,0 @@ -import bugsnag - -def configure_bugsnag(api_key=None) -> bool: - """ - Configure BugSnag API communication in `config.yml`. - """ - - if api_key: - bugsnag.configure(api_key=api_key) - return True - - return False - -def send_notification(msg=None, metadata=None) -> None: - """ - Monitor your code with BugSnag - - You can include a additional information with the `metadata` paramater. - """ - bugsnag.notify(Exception(msg), metadata={"ThreatIngestor" : metadata})