Added plugin manager

pull/3/head
Thorsten Sick 3 years ago
parent a2d4e601e8
commit 3d9780d57e

@ -4,13 +4,12 @@
import os import os
import time import time
from glob import glob
import requests import requests
import straight.plugin
from app.config import MachineConfig, ExperimentConfig from app.config import MachineConfig, ExperimentConfig
from app.exceptions import ServerError, ConfigurationError from app.exceptions import ServerError, ConfigurationError
from app.pluginmanager import PluginManager
from app.calderacontrol import CalderaControl from app.calderacontrol import CalderaControl
from app.interface_sfx import CommandlineColors from app.interface_sfx import CommandlineColors
from plugins.base.kali import KaliPlugin from plugins.base.kali import KaliPlugin
@ -37,6 +36,8 @@ class Machine():
else: else:
self.config = MachineConfig(config) self.config = MachineConfig(config)
self.plugin_manager = PluginManager()
# TODO: Read config from plugin # TODO: Read config from plugin
if self.config.vmcontroller() == "vagrant": if self.config.vmcontroller() == "vagrant":
self.__parse_vagrant_config__() self.__parse_vagrant_config__()
@ -155,59 +156,31 @@ class Machine():
@returns: The output of the cmdline attacking tool @returns: The output of the cmdline attacking tool
""" """
def get_handlers(plugin) -> [KaliPlugin]: for plugin in self.plugin_manager.get_plugins(KaliPlugin, [attack]):
return plugin.produce() name = plugin.get_name()
base = "plugins/**/*.py"
plugin_dirs = set()
for a_glob in glob(base, recursive=True):
plugin_dirs.add(os.path.dirname(a_glob))
for a_directory in plugin_dirs:
plugins = straight.plugin.load(a_directory, subclasses=KaliPlugin)
handlers = get_handlers(plugins)
for plugin in handlers: print(f"{CommandlineColors.OKBLUE}Running Kali plugin {name}{CommandlineColors.ENDC}")
name = plugin.get_name() syscon = {"abs_machinepath_internal": self.abs_machinepath_internal,
if name == attack: "abs_machinepath_external": self.abs_machinepath_external}
print(f"{CommandlineColors.OKBLUE}Running Kali plugin {name}{CommandlineColors.ENDC}") plugin.set_sysconf(syscon)
syscon = {"abs_machinepath_internal": self.abs_machinepath_internal, plugin.set_machine_plugin(self.vm_manager)
"abs_machinepath_external": self.abs_machinepath_external} plugin.__set_logger__(self.attack_logger)
plugin.set_sysconf(syscon) plugin.__execute__([target], config.kali_conf(name))
plugin.set_machine_plugin(self.vm_manager)
plugin.__set_logger__(self.attack_logger)
plugin.__execute__([target], config.kali_conf(name))
def load_machine_plugin(self): def load_machine_plugin(self):
""" Loads the matching machine plugin """ """ Loads the matching machine plugin """
def get_handlers(a_plugin) -> [MachineryPlugin]: for plugin in self.plugin_manager.get_plugins(MachineryPlugin, [self.config.vmcontroller()]):
return a_plugin.produce()
base = "plugins/**/*.py" name = plugin.get_name()
print(f"{CommandlineColors.OKBLUE}Installing sensor: {name}{CommandlineColors.ENDC}")
plugin_dirs = set()
for a_glob in glob(base, recursive=True):
plugin_dirs.add(os.path.dirname(a_glob))
for a_dir in plugin_dirs:
plugins = straight.plugin.load(a_dir, subclasses=MachineryPlugin)
handlers = get_handlers(plugins)
for plugin in handlers:
name = plugin.get_name()
if name == self.config.vmcontroller():
print(f"{CommandlineColors.OKBLUE}Installing sensor: {name}{CommandlineColors.ENDC}")
syscon = {"abs_machinepath_internal": self.abs_machinepath_internal, syscon = {"abs_machinepath_internal": self.abs_machinepath_internal,
"abs_machinepath_external": self.abs_machinepath_external} "abs_machinepath_external": self.abs_machinepath_external}
plugin.set_sysconf(syscon) plugin.set_sysconf(syscon)
plugin.__call_process_config__(self.config) plugin.__call_process_config__(self.config)
self.vm_manager = plugin self.vm_manager = plugin
break break
def prime_sensors(self): def prime_sensors(self):
""" Prime sensors from plugins (hard core installs that could require a reboot) """ Prime sensors from plugins (hard core installs that could require a reboot)
@ -216,35 +189,22 @@ class Machine():
""" """
def get_handlers(a_plugin) -> [SensorPlugin]:
return a_plugin.produce()
base = "plugins/**/*.py"
reboot = False reboot = False
plugin_dirs = set() for plugin in self.plugin_manager.get_plugins(SensorPlugin, self.config.sensors()):
for a_glob in glob(base, recursive=True): name = plugin.get_name()
plugin_dirs.add(os.path.dirname(a_glob)) # if name in self.config.sensors():
print(f"{CommandlineColors.OKBLUE}Priming sensor: {name}{CommandlineColors.ENDC}")
for a_dir in plugin_dirs: syscon = {"abs_machinepath_internal": self.abs_machinepath_internal,
plugins = straight.plugin.load(a_dir, subclasses=SensorPlugin) "abs_machinepath_external": self.abs_machinepath_external,
"sensor_specific": self.config.raw_config.get(name, {})
handlers = get_handlers(plugins) }
plugin.set_sysconf(syscon)
for plugin in handlers: plugin.set_machine_plugin(self.vm_manager)
name = plugin.get_name() plugin.setup()
if name in self.config.sensors(): reboot |= plugin.prime()
print(f"{CommandlineColors.OKBLUE}Priming sensor: {name}{CommandlineColors.ENDC}") self.sensors.append(plugin)
syscon = {"abs_machinepath_internal": self.abs_machinepath_internal, print(f"{CommandlineColors.OKGREEN}Primed sensor: {name}{CommandlineColors.ENDC}")
"abs_machinepath_external": self.abs_machinepath_external,
"sensor_specific": self.config.raw_config.get(name, {})
}
plugin.set_sysconf(syscon)
plugin.set_machine_plugin(self.vm_manager)
plugin.setup()
reboot |= plugin.prime()
self.sensors.append(plugin)
print(f"{CommandlineColors.OKGREEN}Primed sensor: {name}{CommandlineColors.ENDC}")
return reboot return reboot
def install_sensors(self): def install_sensors(self):
@ -266,7 +226,6 @@ class Machine():
plugin.setup() plugin.setup()
plugin.install() plugin.install()
print(f"{CommandlineColors.OKGREEN}Installed sensor: {name}{CommandlineColors.ENDC}") print(f"{CommandlineColors.OKGREEN}Installed sensor: {name}{CommandlineColors.ENDC}")
# self.sensors.append(plugin)
def get_sensors(self) -> [SensorPlugin]: def get_sensors(self) -> [SensorPlugin]:
""" Returns a list of running sensors """ """ Returns a list of running sensors """
@ -323,32 +282,17 @@ class Machine():
""" """
def get_handlers(a_plugin) -> [SensorPlugin]: for plugin in self.plugin_manager.get_plugins(VulnerabilityPlugin, self.config.vulnerabilities()):
return a_plugin.produce() name = plugin.get_name()
print(f"Configured vulnerabilities: {self.config.vulnerabilities()}")
base = "plugins/**/*.py" print(f"{CommandlineColors.OKBLUE}Installing vulnerability: {name}{CommandlineColors.ENDC}")
syscon = {"abs_machinepath_internal": self.abs_machinepath_internal,
plugin_dirs = set() "abs_machinepath_external": self.abs_machinepath_external}
for a_glob in glob(base, recursive=True): plugin.set_sysconf(syscon)
plugin_dirs.add(os.path.dirname(a_glob)) plugin.set_machine_plugin(self.vm_manager)
plugin.setup()
for a_dir in plugin_dirs: plugin.install(self.vm_manager)
plugins = straight.plugin.load(a_dir, subclasses=VulnerabilityPlugin) self.vulnerabilities.append(plugin)
handlers = get_handlers(plugins)
for plugin in handlers:
name = plugin.get_name()
print(f"Configured vulnerabilities: {self.config.vulnerabilities()}")
if name in self.config.vulnerabilities():
print(f"{CommandlineColors.OKBLUE}Installing vulnerability: {name}{CommandlineColors.ENDC}")
syscon = {"abs_machinepath_internal": self.abs_machinepath_internal,
"abs_machinepath_external": self.abs_machinepath_external}
plugin.set_sysconf(syscon)
plugin.set_machine_plugin(self.vm_manager)
plugin.setup()
plugin.install(self.vm_manager)
self.vulnerabilities.append(plugin)
def get_vulnerabilities(self) -> [SensorPlugin]: def get_vulnerabilities(self) -> [SensorPlugin]:
""" Returns a list of installed vulnerabilities """ """ Returns a list of installed vulnerabilities """

@ -0,0 +1,74 @@
#!/usr/bin/env python3
""" Manage plugins """
import straight.plugin
from glob import glob
import os
from plugins.base.plugin_base import BasePlugin
from plugins.base.kali import KaliPlugin
from plugins.base.machinery import MachineryPlugin
from plugins.base.sensor import SensorPlugin
from plugins.base.vulnerability_plugin import VulnerabilityPlugin
# from app.interface_sfx import CommandlineColors
class PluginManager():
""" Manage plugins """
def __init__(self):
self.base = "plugins/**/*.py"
def get_plugins(self, subclass, name_filter=None) -> [BasePlugin]:
""" Returns a list plugins matching specified criteria
:param subclass: The subclass to use to filter plugins. Currently: KaliPlugin, MachineryPlugin, SensorPlugin, VulnerabilityPlugin
:param name_filter: an optional list of names to select the plugins by
:return: A list of instantiated plugins
"""
res = []
def get_handlers(a_plugin) -> [subclass]:
return a_plugin.produce()
plugin_dirs = set()
for a_glob in glob(self.base, recursive=True):
plugin_dirs.add(os.path.dirname(a_glob))
for a_dir in plugin_dirs:
plugins = straight.plugin.load(a_dir, subclasses=subclass)
handlers = get_handlers(plugins)
for plugin in handlers:
if name_filter is None:
res.append(plugin)
else:
names = set(plugin.get_names())
intersection = names.intersection(name_filter)
if len(intersection):
res.append(plugin)
return res
def print_list(self):
""" Print a pretty list of all available plugins """
sections = [{"name": "Vulnerabilities",
"subclass": VulnerabilityPlugin},
{"name": "Machinery",
"subclass": MachineryPlugin},
{"name": "Kali",
"subclass": KaliPlugin},
{"name": "Sensors",
"subclass": SensorPlugin},
]
for section in sections:
print(f'\t\t{section["name"]}')
plugins = self.get_plugins(section["subclass"])
for plugin in plugins:
print(f"Name: {plugin.get_name()}")
print(f"Description: {plugin.get_description()}")
print("\t")

@ -0,0 +1,34 @@
#!/usr/bin/env python3
""" Managing plugins """
import argparse
from app.pluginmanager import PluginManager
def list_plugins(arguments):
p = PluginManager()
p.print_list()
def create_parser():
""" Creates the parser for the command line arguments"""
main_parser = argparse.ArgumentParser("Manage plugins")
subparsers = main_parser.add_subparsers(help="sub-commands")
# Sub parser for machine creation
parser_create = subparsers.add_parser("list", help="list plugins")
parser_create.set_defaults(func=list_plugins)
# parser_create.add_argument("--configfile", default="experiment.yaml", help="Config file to create from")
# TODO: Get default config
return main_parser
if __name__ == "__main__":
parser = create_parser()
args = parser.parse_args()
args.func(args)

@ -10,6 +10,7 @@ class BasePlugin():
required_files = None # a list of files shipped with the plugin to be installed required_files = None # a list of files shipped with the plugin to be installed
name = None # The name of the plugin name = None # The name of the plugin
alternative_names = [] # The is an optional list of alternative names
description = None # The description of this plugin description = None # The description of this plugin
def __init__(self): def __init__(self):
@ -78,6 +79,22 @@ class BasePlugin():
raise NotImplementedError raise NotImplementedError
def get_names(self) -> []:
""" Adds the name of the plugin to the alternative names and returns the list """
res = set()
if self.name:
res.add(self.name)
for i in self.alternative_names:
res.add(i)
if len(res):
return list(res)
raise NotImplementedError
def get_description(self): def get_description(self):
""" Returns the description of the plugin, please set in boilerplate """ """ Returns the description of the plugin, please set in boilerplate """
if self.description: if self.description:

Loading…
Cancel
Save