Files
enteletaor/enteletaor_lib/modules/redis/redis_dump.py
cr0hn ff2abc7b65 add: complete documentation
fix: unused options in redis
fix: compatibility between python 2-3
fix: forgot vars declarations
fix: carry conditions in listing redis keys
fix: listing redis list keys
fix: removed duplicated tasks when they are listed
fix: index number when redis DB are listed
fix:  some error levels in log
fix: renamed *proc* -> *tasks* files
fix: added the process manager backend for 'tasks' options, thinking in future  to add new process managers
2016-02-29 19:14:20 +01:00

190 lines
4.6 KiB
Python

# -*- coding: utf-8 -*-
import six
import json
import redis
import base64
import logging
import binascii
from six.moves.cPickle import loads
log = logging.getLogger()
# ----------------------------------------------------------------------
def dump_keys(con):
for key in con.keys('*'):
key_type = con.type(key).lower()
val = None
if key_type in (b"kv", b"string"):
val = con.get(key)
elif key_type in (b"hash", b"unacked", b"unacked_index"):
val = con.hgetall(key)
elif key_type == b"zet":
val = con.zrange(key, 0, -1)
elif key_type in (b"set", b"list"):
val = con.mget(key)
elif key_type == b"list":
con.lrange(key, 0, -1)
if val is not None:
if isinstance(val, list):
if val[0] is None:
continue
yield key, val
# --------------------------------------------------------------------------
# Human parsers
# --------------------------------------------------------------------------
def decode_object(key, val, ident=5):
if isinstance(val, dict):
log.error(' "%s":' % key)
log.error(" {")
_decode_object(val, ident)
log.error(" }")
else:
log.error(' "%s": "%s"' % (key, val))
# ----------------------------------------------------------------------
def _decode_object(val, ident=5):
"""
Decode recursively string
"""
_new_ident = ident + 1
for k, v in six.iteritems(val):
# convert value to original type -> JSON
try:
_transformed_info = json.loads(v.decode("utf-8"))
except (binascii.Error, AttributeError, ValueError):
_transformed_info = v
# --------------------------------------------------------------------------
# Try to display in "human" format
# --------------------------------------------------------------------------
if isinstance(_transformed_info, list):
log.error('%s"%s":' % (" " * ident, k))
for x in _transformed_info:
if isinstance(x, dict):
# Open data
log.error("%s{" % (" " * _new_ident))
_decode_object(x, _new_ident + 2)
log.error("%s}" % (" " * _new_ident))
else:
log.error('%s"%s"' % ((" " * ident), x))
# Dict handler
elif isinstance(_transformed_info, dict):
log.error('%s"%s":' % ((" " * ident), k))
log.error("%s{" % (" " * _new_ident))
_decode_object(v, _new_ident + 2)
log.error("%s}" % (" " * _new_ident))
# Basic type as value
else:
try:
use_obj = _transformed_info.encode()
except (TypeError, AttributeError, binascii.Error):
use_obj = _transformed_info
# Is Pickle encoded?
try:
_pickle_decoded = loads(use_obj)
# Is pickled
log.error('%s"%s":' % ((" " * ident), k))
log.error("%s{" % (" " * _new_ident))
_decode_object(_pickle_decoded, _new_ident + 2)
log.error("%s}" % (" " * _new_ident))
except Exception as e:
if "BadPickleGet" == e.__class__.__name__:
log.info(
" <!!> Can't decode value for key '%s' because Pickle protocol 3 o 4 used, and it's "
"incompatible with Python 2" % k)
# Try again decoding in base64
try:
_b64_decoded = base64.decodebytes(use_obj)
# Is pickled
log.error('%s"%s":' % ((" " * ident), k))
log.error("%s{" % (" " * _new_ident))
_decode_object(loads(_b64_decoded), _new_ident + 2)
log.error("%s}" % (" " * _new_ident))
except Exception:
# Transform is not possible -> plain string
log.error('%s"%s": "%s"' % ((" " * ident), k, use_obj))
# ----------------------------------------------------------------------
def action_redis_dump(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)
# Export results?
export_file = None
export_file_name = None
# Fix filename
if config.export_results:
export_file_name = config.export_results if ".json" in config.export_results else "%s.json" % config.export_results
if config.export_results:
export_file = open(export_file_name, "w")
log.error(" - Storing information into '%s'" % export_file_name)
elif config.no_screen is True:
log.error(" <!> If results will not be displayed, you must to indicate output file for results.")
return
registers = False
for i, t_val in enumerate(dump_keys(con)):
key = t_val[0]
val = t_val[1]
# Display results?
if config.no_screen is False:
decode_object(key, val)
# Dump to file?
if export_file is not None:
export_file.write("%s: %s" % (key, str(val)))
# There are registers
registers = True
if registers is False:
log.error(" - No information to dump in database")
# Close file descriptor
if export_file is not None:
export_file.close()