From 0fda6a51a6aa5f637aa7630a91f1c518997efc28 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rajmund=20Hru=C5=A1ka?= <rajmund.hruska@cesnet.cz> Date: Tue, 3 Aug 2021 16:25:41 +0200 Subject: [PATCH] Feature: Use fallback for emails with no recipients. (Redmine issue: #6227) --- conf/core/reporting.json.conf | 1 + lib/mentat/const.py | 2 ++ lib/mentat/datatype/internal.py | 13 ++++++++----- lib/mentat/module/netmngr.py | 12 ++++++++++++ lib/mentat/module/reporter.py | 1 + lib/mentat/reports/event.py | 8 +++++--- lib/mentat/reports/test_event.py | 1 + 7 files changed, 30 insertions(+), 8 deletions(-) diff --git a/conf/core/reporting.json.conf b/conf/core/reporting.json.conf index 14f8c0766..897e18ece 100644 --- a/conf/core/reporting.json.conf +++ b/conf/core/reporting.json.conf @@ -7,6 +7,7 @@ "templates_dir": "/etc/mentat/templates/reporter", "event_classes_dir": "/etc/mentat/event_classes", "mail_admin": "root", + "fallback": ["abuse@cesnet.cz"], # Additional variables that can be used inside the report templates. # default: {} diff --git a/lib/mentat/const.py b/lib/mentat/const.py index 744ba7922..a7fec6b16 100644 --- a/lib/mentat/const.py +++ b/lib/mentat/const.py @@ -120,6 +120,8 @@ CKEY_CORE_REPORTER_TEMPLATEVARS = 'template_vars' """Name of the configuration subkey key for ``template vars`` configuration in ``core reporter`` configurations.""" CKEY_CORE_REPORTER_EVENTCLASSESDIR = 'event_classes_dir' """Name of the configuration subkey key for ``event classes dir`` configuration in ``core reporter`` configurations.""" +CKEY_CORE_REPORTER_FALLBACK = 'fallback' +"""Name of the configuration subkey key for ``fallback`` configuration in ``core reporter`` configurations.""" CKEY_CORE_INFORMANT = '__core__informant' """Name of the configuration key for ``core informant`` configurations.""" diff --git a/lib/mentat/datatype/internal.py b/lib/mentat/datatype/internal.py index ea5aa87ef..ef3948ebf 100644 --- a/lib/mentat/datatype/internal.py +++ b/lib/mentat/datatype/internal.py @@ -342,17 +342,14 @@ def t_network_record(val, source = None): if 'abuse_group' in val: record['abuse_group'] = val['abuse_group'] elif 'resolved_abuses' in val: - for severity in 'low', 'medium', 'high', 'critical': + for severity in 'fallback', 'low', 'medium', 'high', 'critical': if severity in val['resolved_abuses']: record['emails_{}'.format(severity)] = val['resolved_abuses'][severity] # compute resulting abuse group from all emails emails = [] - for severity in 'emails_low', 'emails_medium', 'emails_high', 'emails_critical': + for severity in 'emails_fallback', 'emails_low', 'emails_medium', 'emails_high', 'emails_critical': if severity in record: - # TODO: this probably won't be necessary, after the issue is solved elsewhere - if len(record[severity]) > 1 and 'abuse@cesnet.cz' in record[severity]: - record[severity].remove('abuse@cesnet.cz') emails.extend(record[severity]) if emails: record['abuse_group'] = ','.join(sorted(map(str.lower, list(set(emails))))) @@ -487,6 +484,9 @@ def typedef_network_record_ip4(flavour, list_flavour, addon = None): 'emails': { 'type': list_flavour['String'] }, + 'emails_fallback': { + 'type': list_flavour['String'] + }, 'emails_low': { 'type': list_flavour['String'] }, @@ -570,6 +570,9 @@ def typedef_network_record_ip6(flavour, list_flavour, addon = None): 'emails': { 'type': list_flavour['String'] }, + 'emails_fallback': { + 'type': list_flavour['String'] + }, 'emails_low': { 'type': list_flavour['String'] }, diff --git a/lib/mentat/module/netmngr.py b/lib/mentat/module/netmngr.py index 53d71a34e..f2706acde 100644 --- a/lib/mentat/module/netmngr.py +++ b/lib/mentat/module/netmngr.py @@ -452,6 +452,12 @@ class MentatNetmngrScript(mentat.script.fetcher.FetcherScript): emails = {'low': [], 'medium': [], 'high': [], 'critical': []} for nwrkey in wi_file_data[abuse_group]: for network in wi_file_data[abuse_group][nwrkey]: + # Check that the fallback defined in the whois_file is the same as the global one. + if 'emails_fallback' in network: + system_fallback = self.config[mentat.const.CKEY_CORE_REPORTER][mentat.const.CKEY_CORE_REPORTER_FALLBACK] + if not set(map(str.lower, system_fallback)) == set(map(str.lower, network['emails_fallback'])): + self.logger.error("Fallback provided by whois file is different from the system fallback defined in reporting configuration.") + continue for severity in ['low', 'medium', 'high', 'critical']: emails[severity].append(sorted(map(str.lower, list(set(network.get('emails_{}'.format(severity), [])))))) @@ -507,6 +513,9 @@ class MentatNetmngrScript(mentat.script.fetcher.FetcherScript): checked_group_name = False for network in [network for networks in wi_file_data[group_name].values() for network in networks]: + # Do not create networks where fallback option is present. + if 'emails_fallback' in network: + continue # If there are multiple emails in this abuse group or lowest severity is not low then save # emails in the reporting settings. By default, if the group in the database doesn't have # any emails set in the reporting settings then the name of the abuse group is used as @@ -587,6 +596,9 @@ class MentatNetmngrScript(mentat.script.fetcher.FetcherScript): """ gkey = '{}::{}'.format(group.name, group.source) for net in networks: + # Do not create networks where fallback option is present. + if 'emails_fallback' in net: + continue nkey = '{}::{}'.format(net['network'], net['source']) index = self._get_index_of_network(net, group.networks) if index == -1: diff --git a/lib/mentat/module/reporter.py b/lib/mentat/module/reporter.py index ba8fd8fe6..804fb647d 100644 --- a/lib/mentat/module/reporter.py +++ b/lib/mentat/module/reporter.py @@ -360,6 +360,7 @@ class MentatReporterScript(mentat.script.fetcher.FetcherScript): self.logger, self.config[self.CORECFG_REPORTER][self.CONFIG_REPORTS_DIR], self.config[self.CORECFG_REPORTER][self.CONFIG_TEMPLATES_DIR], + self.config[mentat.const.CKEY_CORE_REPORTER][mentat.const.CKEY_CORE_REPORTER_FALLBACK], mentat.const.DFLT_REPORTING_LOCALE, mentat.const.DFLT_REPORTING_TIMEZONE, self.eventservice, diff --git a/lib/mentat/reports/event.py b/lib/mentat/reports/event.py index 0d011db52..912a6f0f6 100644 --- a/lib/mentat/reports/event.py +++ b/lib/mentat/reports/event.py @@ -145,7 +145,7 @@ class EventReporter(BaseReporter): Implementation of reporting class providing Mentat event reports. """ - def __init__(self, logger, reports_dir, templates_dir, locale, timezone, eventservice, sqlservice, mailer, event_classes_dir, groups_dict, settings_dict, whoismodule, thresholding = True): + def __init__(self, logger, reports_dir, templates_dir, fallback, locale, timezone, eventservice, sqlservice, mailer, event_classes_dir, groups_dict, settings_dict, whoismodule, thresholding = True): self.translations_dir = ";".join([os.path.join(event_classes_dir, event_class, "translations") for event_class in os.listdir(event_classes_dir) if os.path.isdir(os.path.join(event_classes_dir, event_class))]) @@ -158,6 +158,7 @@ class EventReporter(BaseReporter): self.event_classes_data = {} self.event_classes_dir = event_classes_dir + self.fallback = fallback self.filter_parser = PynspectFilterParser() self.filter_compiler = IDEAFilterCompiler() @@ -997,9 +998,10 @@ class EventReporter(BaseReporter): i -= 1 cc = list(set(cc)) + # Use fallback option if no email addresses are found for the given severity. if not to: - #TODO: fallback option - return + to = self.fallback + self.logger.info("No email addresses found for the given severity, using fallback: %s", to) # Common report email headers. report_msg_headers = { diff --git a/lib/mentat/reports/test_event.py b/lib/mentat/reports/test_event.py index 46e5e981c..2638dd4fa 100644 --- a/lib/mentat/reports/test_event.py +++ b/lib/mentat/reports/test_event.py @@ -184,6 +184,7 @@ class TestMentatReportsEvent(unittest.TestCase): Mock(), REPORTS_DIR, os.path.abspath(os.path.join(os.path.dirname(__file__), '../../../conf/templates/reporter')), + [], 'en', 'UTC', self.eventstorage, -- GitLab