def load_modules(self, rule, args=None): """ Loads things that could be modules. Enhancements, alerts and rule type. """ # Set match enhancements match_enhancements = [] for enhancement_name in rule.get('match_enhancements', []): if enhancement_name in dir(enhancements): enhancement = getattr(enhancements, enhancement_name) else: enhancement = get_module(enhancement_name) if not issubclass(enhancement, enhancements.BaseEnhancement): raise EAException( "Enhancement module %s not a subclass of BaseEnhancement" % enhancement_name) match_enhancements.append(enhancement(rule)) rule['match_enhancements'] = match_enhancements # Convert rule type into RuleType object if rule['type'] in self.rules_mapping: rule['type'] = self.rules_mapping[rule['type']] else: rule['type'] = get_module(rule['type']) if not issubclass(rule['type'], ruletypes.RuleType): raise EAException( 'Rule module %s is not a subclass of RuleType' % (rule['type'])) # Make sure we have required alert and type options reqs = rule['type'].required_options if reqs - frozenset(list(rule.keys())): raise EAException('Missing required option(s): %s' % (', '.join(reqs - frozenset(list(rule.keys()))))) # Instantiate rule try: rule['type'] = rule['type'](rule, args) except (KeyError, EAException) as e: raise EAException('Error initializing rule %s: %s' % (rule['name'], e)).with_traceback( sys.exc_info()[2]) # Instantiate alerts only if we're not in debug mode # In debug mode alerts are not actually sent so don't bother instantiating them if not args or not args.debug: rule['alert'] = self.load_alerts(rule, alert_field=rule['alert'])
def create_alert(alert, alert_config): alert_class = self.alerts_mapping.get(alert) or get_module(alert) if not issubclass(alert_class, alerts.Alerter): raise EAException( 'Alert module %s is not a subclass of Alerter' % alert) missing_options = (rule['type'].required_options | alert_class.required_options) - frozenset( alert_config or []) if missing_options: raise EAException('Missing required option(s): %s' % (', '.join(missing_options))) return alert_class(alert_config)
def load_conf(args, defaults=None, overwrites=None): """ Creates a conf dictionary for ElastAlerter. Loads the global config file and then each rule found in rules_folder. :param args: The parsed arguments to ElastAlert :param defaults: Dictionary of default conf values :param overwrites: Dictionary of conf values to override :return: The global configuration, a dictionary. """ filename = args.config if filename: conf = read_yaml(filename) else: try: conf = read_yaml('config.yaml') except FileNotFoundError: raise EAException('No --config or config.yaml found') # init logging from config and set log levels according to command line options configure_logging(args, conf) for env_var, conf_var in list(env_settings.items()): val = env(env_var, None) if val is not None: conf[conf_var] = val for key, value in (iter(defaults.items()) if defaults is not None else []): if key not in conf: conf[key] = value for key, value in (iter(overwrites.items()) if overwrites is not None else []): conf[key] = value # Make sure we have all required globals if required_globals - frozenset(list(conf.keys())): raise EAException('%s must contain %s' % (filename, ', '.join(required_globals - frozenset(list(conf.keys()))))) conf.setdefault('max_query_size', 10000) conf.setdefault('scroll_keepalive', '30s') conf.setdefault('max_scrolling_count', 0) conf.setdefault('disable_rules_on_error', True) conf.setdefault('scan_subdirectories', True) conf.setdefault('rules_loader', 'file') # Convert run_every, buffer_time into a timedelta object try: conf['run_every'] = datetime.timedelta(**conf['run_every']) conf['buffer_time'] = datetime.timedelta(**conf['buffer_time']) if 'alert_time_limit' in conf: conf['alert_time_limit'] = datetime.timedelta( **conf['alert_time_limit']) else: conf['alert_time_limit'] = datetime.timedelta(days=2) if 'old_query_limit' in conf: conf['old_query_limit'] = datetime.timedelta( **conf['old_query_limit']) else: conf['old_query_limit'] = datetime.timedelta(weeks=1) except (KeyError, TypeError) as e: raise EAException('Invalid time format used: %s' % e) # Initialise the rule loader and load each rule configuration rules_loader_class = loader_mapping.get( conf['rules_loader']) or get_module(conf['rules_loader']) rules_loader = rules_loader_class(conf) conf['rules_loader'] = rules_loader # Make sure we have all the required globals for the loader # Make sure we have all required globals if rules_loader.required_globals - frozenset(list(conf.keys())): raise EAException('%s must contain %s' % (filename, ', '.join(rules_loader.required_globals - frozenset(list(conf.keys()))))) return conf
def test_get_module(): with pytest.raises(EAException) as ea: get_module('test') assert 'Could not import module' in str(ea)