Added plugin manager

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

@ -4,13 +4,12 @@
import os
import time
from glob import glob
import requests
import straight.plugin
from app.config import MachineConfig, ExperimentConfig
from app.exceptions import ServerError, ConfigurationError
from app.pluginmanager import PluginManager
from app.calderacontrol import CalderaControl
from app.interface_sfx import CommandlineColors
from plugins.base.kali import KaliPlugin
@ -37,6 +36,8 @@ class Machine():
else:
self.config = MachineConfig(config)
self.plugin_manager = PluginManager()
# TODO: Read config from plugin
if self.config.vmcontroller() == "vagrant":
self.__parse_vagrant_config__()
@ -155,59 +156,31 @@ class Machine():
@returns: The output of the cmdline attacking tool
"""
def get_handlers(plugin) -> [KaliPlugin]:
return plugin.produce()
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 self.plugin_manager.get_plugins(KaliPlugin, [attack]):
name = plugin.get_name()
for plugin in handlers:
name = plugin.get_name()
if name == attack:
print(f"{CommandlineColors.OKBLUE}Running Kali plugin {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.__set_logger__(self.attack_logger)
plugin.__execute__([target], config.kali_conf(name))
print(f"{CommandlineColors.OKBLUE}Running Kali plugin {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.__set_logger__(self.attack_logger)
plugin.__execute__([target], config.kali_conf(name))
def load_machine_plugin(self):
""" Loads the matching machine plugin """
def get_handlers(a_plugin) -> [MachineryPlugin]:
return a_plugin.produce()
for plugin in self.plugin_manager.get_plugins(MachineryPlugin, [self.config.vmcontroller()]):
base = "plugins/**/*.py"
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}")
name = plugin.get_name()
print(f"{CommandlineColors.OKBLUE}Installing sensor: {name}{CommandlineColors.ENDC}")
syscon = {"abs_machinepath_internal": self.abs_machinepath_internal,
"abs_machinepath_external": self.abs_machinepath_external}
plugin.set_sysconf(syscon)
plugin.__call_process_config__(self.config)
self.vm_manager = plugin
break
syscon = {"abs_machinepath_internal": self.abs_machinepath_internal,
"abs_machinepath_external": self.abs_machinepath_external}
plugin.set_sysconf(syscon)
plugin.__call_process_config__(self.config)
self.vm_manager = plugin
break
def prime_sensors(self):
""" 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
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=SensorPlugin)
handlers = get_handlers(plugins)
for plugin in handlers:
name = plugin.get_name()
if name in self.config.sensors():
print(f"{CommandlineColors.OKBLUE}Priming sensor: {name}{CommandlineColors.ENDC}")
syscon = {"abs_machinepath_internal": self.abs_machinepath_internal,
"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}")
for plugin in self.plugin_manager.get_plugins(SensorPlugin, self.config.sensors()):
name = plugin.get_name()
# if name in self.config.sensors():
print(f"{CommandlineColors.OKBLUE}Priming sensor: {name}{CommandlineColors.ENDC}")
syscon = {"abs_machinepath_internal": self.abs_machinepath_internal,
"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
def install_sensors(self):
@ -266,7 +226,6 @@ class Machine():
plugin.setup()
plugin.install()
print(f"{CommandlineColors.OKGREEN}Installed sensor: {name}{CommandlineColors.ENDC}")
# self.sensors.append(plugin)
def get_sensors(self) -> [SensorPlugin]:
""" Returns a list of running sensors """
@ -323,32 +282,17 @@ class Machine():
"""
def get_handlers(a_plugin) -> [SensorPlugin]:
return a_plugin.produce()
base = "plugins/**/*.py"
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=VulnerabilityPlugin)
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)
for plugin in self.plugin_manager.get_plugins(VulnerabilityPlugin, self.config.vulnerabilities()):
name = plugin.get_name()
print(f"Configured vulnerabilities: {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]:
""" 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
name = None # The name of the plugin
alternative_names = [] # The is an optional list of alternative names
description = None # The description of this plugin
def __init__(self):
@ -78,6 +79,22 @@ class BasePlugin():
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):
""" Returns the description of the plugin, please set in boilerplate """
if self.description:

Loading…
Cancel
Save