# -*- coding: utf-8 -*- # # Copyright Grégory Soutadé 2015 # This file is part of iwla # iwla is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # iwla is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with iwla. If not, see . # import importlib import inspect import logging # # IWLA Plugin interface # class IPlugin(object): def __init__(self, iwla): self.iwla = iwla self.requires = [] self.conf_requires = [] self.API_VERSION = 1 self.ANALYSIS_CLASS = 'HTTP' def isValid(self, analysis_class, api_version): if analysis_class != self.ANALYSIS_CLASS: return False # For now there is only version 1 if self.API_VERSION != api_version: return False return True def getRequirements(self): return self.requires def getConfRequirements(self): return self.conf_requires def load(self): return True def hook(self): pass def validConfRequirements(conf_requirements, iwla, plugin_path): for r in conf_requirements: if iwla.getConfValue(r, None) is None: print('\'%s\' conf value required for %s' % (r, plugin_path)) return False return True def preloadPlugins(plugins, iwla): cache_plugins = {} logger = logging.getLogger(__name__) logger.info("==> Preload plugins") for (root, plugins_filenames) in plugins: for plugin_filename in plugins_filenames: plugin_path = root + '.' + plugin_filename try: mod = importlib.import_module(plugin_path) classes = [c for _,c in inspect.getmembers(mod)\ if inspect.isclass(c) and \ issubclass(c, IPlugin) and \ c.__name__ != 'IPlugin' and \ not c.__subclasses__() ] if not classes: logger.warning('No plugin defined in %s' % (plugin_path)) continue if len(classes) > 1: logger.warning('More than one class found in %s, loading may fail. Selecting %s' % (plugin_path, classes[0])) print(classes) continue plugin = classes[0](iwla) plugin_name = plugin.__class__.__name__ if not plugin.isValid(iwla.ANALYSIS_CLASS, iwla.API_VERSION): #print 'Plugin not valid %s' % (plugin_filename) continue #print 'Load plugin %s' % (plugin_name) conf_requirements = plugin.getConfRequirements() if not validConfRequirements(conf_requirements, iwla, plugin_path): continue requirements = plugin.getRequirements() requirement_validated = False for r in requirements: for p in cache_plugins.values(): if p.__class__.__name__ == r: requirement_validated = True break if not requirement_validated: logger.error('Missing requirements \'%s\' for plugin %s' % (r, plugin_path)) break if requirements and not requirement_validated: continue if not plugin.load(): logger.error('Plugin %s load failed' % (plugin_path)) continue logger.info('\tRegister %s' % (plugin_path)) cache_plugins[plugin_path] = plugin except Exception as e: logger.exception('Error loading %s => %s' % (plugin_path, e)) return cache_plugins