summaryrefslogtreecommitdiffstats
path: root/peekaboo/ruleset/engine.py
diff options
context:
space:
mode:
authorMichael Weiser <michael.weiser@gmx.de>2019-04-18 08:57:15 +0000
committerMichael Weiser <michael.weiser@gmx.de>2019-04-25 12:20:20 +0000
commit77d2ff1348a6f1ade05b54b297fc771abd0e14cd (patch)
treee7914e3ad89f36b65aced27f53132244f894832f /peekaboo/ruleset/engine.py
parente6c44a8ca3c2216904731e4d889e53473691c0dc (diff)
Validate ruleset config
Validate the ruleset configuration at startup to inform the user about misconfiguration and exit immediately instead of giving warnings during seemingly normal operation. This also gives us a chance to pre-compile regexes for more efficient matching later on. We give rules a new method get_config() which retrieves their configuration. This is called for each rule by new method the validate_config() of the ruleset engine to catch errors. This way the layout and extent of configuration is still completely governed by the rule and we can interview it about its happiness with what's provided in the configuration file. As an incidental cleanup, merge class PeekabooRulesetConfig into PeekabooRulesetParser because there's nothing left where it could and would need to help the rules with an abstraction of the config file. Also switch class PeekabooConfig to be a subclass of PeekabooConfigParser so it can (potentially) benefit from the list parsing code there. By moving the special log level and by-default-type getters over there as well we end up with nicely generic config classes that can benefit directly from improvements in the configparser module. Update the test suite to test and use this new functionality. Incidentally, remove the convoluted inheritance-based config testing layout in favour of creating subclasses of the config classes.
Diffstat (limited to 'peekaboo/ruleset/engine.py')
-rw-r--r--peekaboo/ruleset/engine.py52
1 files changed, 42 insertions, 10 deletions
diff --git a/peekaboo/ruleset/engine.py b/peekaboo/ruleset/engine.py
index 86b95e8..376cc08 100644
--- a/peekaboo/ruleset/engine.py
+++ b/peekaboo/ruleset/engine.py
@@ -28,7 +28,8 @@ import logging
from peekaboo.ruleset import Result, RuleResult
from peekaboo.ruleset.rules import *
from peekaboo.toolbox.peekabooyar import ContainsPeekabooYarRule
-from peekaboo.exceptions import PeekabooAnalysisDeferred
+from peekaboo.exceptions import PeekabooAnalysisDeferred, \
+ PeekabooConfigException, PeekabooRulesetConfigError
logger = logging.getLogger(__name__)
@@ -54,19 +55,51 @@ class RulesetEngine(object):
FinalRule
]
- def __init__(self, sample, ruleset_config, db_con):
- self.sample = sample
+ def __init__(self, ruleset_config, db_con):
self.config = ruleset_config
self.db_con = db_con
# create a lookup table from rule name to class
- self.rules = {}
+ self.rule_classes = {}
for known_rule in self.known_rules:
- self.rules[known_rule.rule_name] = known_rule
+ self.rule_classes[known_rule.rule_name] = known_rule
- def run(self):
- for rule in self.config.rule_config('rules').get('rule'):
- result = self.__exec_rule(self.sample, self.rules[rule])
+ try:
+ self.enabled_rules = self.config.getlist('rules', 'rule')
+ except PeekabooConfigException as error:
+ raise PeekabooRulesetConfigError(
+ 'Ruleset configuration error: %s' % error)
+
+ self.validate_rule_config()
+
+ def validate_rule_config(self):
+ """ Validate the rule configuration in various ways.
+
+ @returns: None
+ @raises PeekabooRulesetConfigError: if configuration errors are found
+ """
+ if not self.enabled_rules:
+ raise PeekabooRulesetConfigError(
+ 'No enabled rules found, check ruleset config.')
+
+ # check if unknown rules are enabled
+ known_rule_names = self.rule_classes.keys()
+ unknown_rules = set(self.enabled_rules) - set(known_rule_names)
+ if unknown_rules:
+ raise PeekabooRulesetConfigError(
+ 'Unknown rule(s) enabled: %s' % ', '.join(unknown_rules))
+
+ config_sections = []
+ for rule in self.enabled_rules:
+ # not passing database connection. Needs revisiting if a rule
+ # ever wants to retrieve configuration from the database. For
+ # now at least rule constructor and get_config() need to be
+ # able to cope without it.
+ rule = self.rule_classes[rule](self.config)
+
+ def run(self, sample):
+ for rule in self.enabled_rules:
+ result = self.__exec_rule(sample, self.rule_classes[rule])
if not result.further_analysis:
return
@@ -80,8 +113,7 @@ class RulesetEngine(object):
logger.debug("Processing rule '%s' for %s" % (rule_name, sample))
try:
- rule_config = self.config.rule_config(rule_name)
- rule = rule_class(config=rule_config, db_con=self.db_con)
+ rule = rule_class(config=self.config, db_con=self.db_con)
result = rule.evaluate(sample)
sample.add_rule_result(result)
except PeekabooAnalysisDeferred: