CLI: Support hiding data that may be inaccurate

This commit is contained in:
Mike Auty
2020-07-16 22:35:58 +01:00
parent e97549498c
commit dab852c22c
2 changed files with 35 additions and 5 deletions
+5 -1
View File
@@ -157,6 +157,10 @@ class CommandLine(interfaces.plugins.FileConsumerInterface):
help = "Clears out all short-term cached items",
default = False,
action = 'store_true')
parser.add_argument("--safe",
help = "Does not display data that is unreadable or unparsable",
default = False,
action = 'store_true')
# We have to filter out help, otherwise parse_known_args will trigger the help message before having
# processed the plugin choice or had the plugin subparser added.
@@ -305,7 +309,7 @@ class CommandLine(interfaces.plugins.FileConsumerInterface):
try:
# Construct and run the plugin
if constructed:
renderers[args.renderer]().render(constructed.run())
renderers[args.renderer](safe = args.safe).render(constructed.run())
except (exceptions.VolatilityException) as excp:
self.process_exceptions(excp)
+30 -4
View File
@@ -111,6 +111,10 @@ class CLIRenderer(interfaces.renderers.Renderer):
name = "unnamed"
structured_output = False
def __init__(self, safe: bool = False, *args, **kwargs):
super().__init__(*args, **kwargs)
self._safe = safe
class QuickTextRenderer(CLIRenderer):
_type_renderers = {
@@ -148,14 +152,21 @@ class QuickTextRenderer(CLIRenderer):
def visitor(node, accumulator):
accumulator.write("\n")
# Nodes always have a path value, giving them a path_depth of at least 1, we use max just in case
accumulator.write("*" * max(0, node.path_depth - 1) + ("" if (node.path_depth <= 1) else " "))
# Nodes always have a path value, giving them a path_depth of at least 1, we use max just in case
line = []
skip = False
for column_index in range(len(grid.columns)):
column = grid.columns[column_index]
renderer = self._type_renderers.get(column.type, self._type_renderers['default'])
if isinstance(node.values[column_index],
(renderers.UnparsableValue, renderers.UnreadableValue)) and self._safe:
skip = True
line.append(renderer(node.values[column_index]))
accumulator.write("{}".format("\t".join(line)))
if not skip:
accumulator.write("{}".format("\t".join(line)))
else:
accumulator.write("--- Unsafe data ---")
accumulator.flush()
return accumulator
@@ -190,8 +201,10 @@ class CSVRenderer(CLIRenderer):
Args:
grid: The TreeGrid object to render
"""
outfd = sys.stdout
if self._safe:
vollog.info("CSV does not support safe rendering, all records will be returned")
outfd = sys.stdout
line = ['"TreeDepth"']
for column in grid.columns:
# Ignore the type because namedtuples don't realize they have accessible attributes
@@ -250,15 +263,22 @@ class PrettyTextRenderer(CLIRenderer):
node, accumulator: List[Tuple[int, Dict[interfaces.renderers.Column, bytes]]]
) -> List[Tuple[int, Dict[interfaces.renderers.Column, bytes]]]:
# Nodes always have a path value, giving them a path_depth of at least 1, we use max just in case
skip = False
max_column_widths[tree_indent_column] = max(max_column_widths.get(tree_indent_column, 0), node.path_depth)
line = {}
skip = False
for column_index in range(len(grid.columns)):
column = grid.columns[column_index]
renderer = self._type_renderers.get(column.type, self._type_renderers['default'])
data = renderer(node.values[column_index])
if isinstance(node.values[column_index],
(renderers.UnparsableValue, renderers.UnreadableValue)) and self._safe:
skip = True
max_column_widths[column.name] = max(max_column_widths.get(column.name, len(column.name)),
len("{}".format(data)))
line[column] = data
line['__skip'] = skip
accumulator.append((node.path_depth, line))
return accumulator
@@ -280,7 +300,10 @@ class PrettyTextRenderer(CLIRenderer):
column_titles = [""] + [column.name for column in grid.columns]
outfd.write(format_string.format(*column_titles))
for (depth, line) in final_output:
outfd.write(format_string.format("*" * depth, *[line[column] for column in grid.columns]))
if line['__skip']:
outfd.write("{}".format("*" * depth, "--- Unsafe data ---"))
else:
outfd.write(format_string.format("*" * depth, *[line[column] for column in grid.columns]))
class JsonRenderer(CLIRenderer):
@@ -302,6 +325,9 @@ class JsonRenderer(CLIRenderer):
outfd.write(json.dumps(result, indent = 2, sort_keys = True))
def render(self, grid: interfaces.renderers.TreeGrid):
if self._safe:
vollog.info("JSON output does not support safe rendering, all records will be returned")
outfd = sys.stdout
outfd.write("\n")