Skip to content

Commit

Permalink
Fixing Results Output (#37)
Browse files Browse the repository at this point in the history
* Fixing results output

* matching should happen on matched no results

---------

Co-authored-by: Harrison Bornstein <[email protected]>
  • Loading branch information
harrison-bornstein and harrison-cruise authored Jun 18, 2024
1 parent bdc9431 commit 8558071
Show file tree
Hide file tree
Showing 5 changed files with 53 additions and 33 deletions.
5 changes: 3 additions & 2 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ def read(fname):

setup(
name="sublime-cli",
version="0.0.31",
version="0.0.32",
description="Abstraction to interact with the Sublime API.",
url="https://sublimesecurity.com/",
author="Sublime Security",
Expand All @@ -56,6 +56,7 @@ def read(fname):
],
entry_points={"console_scripts": ["sublime = sublime.cli:main"]},
zip_safe=False,
keywords=["security", "phishing", "analysts", "soc", "threat intelligence", "security-automation", "email security"],
keywords=["security", "phishing", "analysts", "soc",
"threat intelligence", "security-automation", "email security"],
download_url="https://github.com/sublime-security/sublime-cli",
)
2 changes: 1 addition & 1 deletion src/sublime/__version__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@
__maintainer__ = "Sublime Security"
__email__ = "[email protected]"
__status__ = "BETA"
__version__ = "0.0.30"
__version__ = "0.0.32"
61 changes: 40 additions & 21 deletions src/sublime/cli/formatter.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
from jinja2 import Environment, PackageLoader

JINJA2_ENV = Environment(loader=PackageLoader("sublime.cli"),
extensions=['jinja2.ext.loopcontrols'])
extensions=['jinja2.ext.loopcontrols'])

colorama.init()
ANSI_MARKUP = ansimarkup.AnsiMarkup(
Expand Down Expand Up @@ -60,14 +60,22 @@ def json_formatter(result, verbose=False, indent=4, offset=0):
return string


def filter_none_recursive(item):
"""Recursive Filter Out Values"""
if isinstance(item, list):
return [filter_none_recursive(sub_item) for sub_item in item if sub_item is not None and (not isinstance(sub_item, list) or any(sub_sub_item is not None for sub_sub_item in sub_item))]
return item


@colored_output
def analyze_formatter(results, verbose):
"""Convert Analyze output into human-readable text."""
mql_offset = 3
json_offset = 2
template_file = "analyze_multi.txt.j2" if len(results) > 1 else "analyze.txt.j2"
template_file = "analyze_multi.txt.j2" if len(
results) > 1 else "analyze.txt.j2"
template = JINJA2_ENV.get_template(template_file)

# calculate total stats
sample_result = next(iter(results.values()))
summary_stats = {
Expand All @@ -77,7 +85,7 @@ def analyze_formatter(results, verbose):
}
rules = [rule for rule in sample_result['rule_results']]
queries = [query for query in sample_result['query_results']]

# separate matched/unmatched messages and distinguish flagged/unflagged rules
flagged_messages = []
unflagged_messages = []
Expand All @@ -87,9 +95,17 @@ def analyze_formatter(results, verbose):
falsey_queries = []
failed_queries = []
for query in result['query_results']:
if query['result']:
result_value = query.get('result')
if isinstance(result_value, list):
# Filter out None values from the result array
filtered_result = filter_none_recursive(result_value)
if filtered_result and any(item is not None for item in filtered_result):
query['result'] = filtered_result
normal_queries.append(query)
elif result_value:
# If the result is not a list and exists (is truthy)
normal_queries.append(query)
elif query['success']:
elif query.get('success'):
falsey_queries.append(query)
else:
failed_queries.append(query)
Expand All @@ -101,10 +117,12 @@ def analyze_formatter(results, verbose):
unflagged_rules = []
failed_rules = []
for rule in result['rule_results']:
if rule['result']:
if rule.get('matched'):
flagged_rules.append(rule)
all_flagged_rules.add(rule['name']+rule['source']) # no unique identifier
elif rule['success']:
# no unique identifier
all_flagged_rules.add(
rule.get("rule").get('name')+rule.get("rule").get('source'))
elif rule.get('success'):
unflagged_rules.append(rule)
else:
failed_rules.append(rule)
Expand All @@ -116,30 +134,29 @@ def analyze_formatter(results, verbose):
flagged_messages.append(result)
else:
unflagged_messages.append(result)

# calculate flagged stats
summary_stats['flagged_rules'] = len(all_flagged_rules)
summary_stats['flagged_messages'] = len(flagged_messages)

# format mql and json outputs
for msg in flagged_messages + unflagged_messages:
for msg in flagged_messages + unflagged_messages:
for result in msg['rule_results'] + msg['query_results']:
if 'result' in result and (isinstance(result['result'], dict) or isinstance(result['result'], list)):
result['result'] = json_formatter(
result['result'],
offset=json_offset,
indent=2)

result['result'],
offset=json_offset,
indent=2)

# TO DO: sort each list of messages by extension and file name (or directory?)

return template.render(
stats=summary_stats,
flagged_messages=flagged_messages,
unflagged_messages=unflagged_messages,
rules=rules,
queries=queries,
verbose=verbose)
stats=summary_stats,
flagged_messages=flagged_messages,
unflagged_messages=unflagged_messages,
rules=rules,
queries=queries,
verbose=verbose)


def mdm_formatter(results, verbose):
Expand All @@ -153,13 +170,15 @@ def mdm_formatter(results, verbose):
# template = JINJA2_ENV.get_template("message_data_model.txt.j2")
# return template.render(results=results, verbose=verbose)


@colored_output
def me_formatter(result, verbose):
"""Convert 'me' output into human-readable text."""
template = JINJA2_ENV.get_template("me_result.txt.j2")

return template.render(result=result, verbose=verbose)


@colored_output
def feedback_formatter(result, verbose):
"""Convert 'feedback' output into human-readable text."""
Expand Down
2 changes: 1 addition & 1 deletion src/sublime/cli/templates/analyze.txt.j2
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
{%- set max_elements = 20 %}
{%- set elements_slice = msg.unflagged_rule_results[:max_elements if verbose < 1 else None] %}
{%- for rule in elements_slice %}
- <not-detected><bold>{{ rule.name }}</bold></not-detected>
- <not-detected><bold>{{ rule.rule.name }}</bold></not-detected>
{%- if verbose %}
<key>Source:</key> {{ rule.source }}
{# new line #}
Expand Down
16 changes: 8 additions & 8 deletions src/sublime/cli/templates/macros.txt.j2
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<header>FLAGGED RULES</header>
{# new line #}
{%- for rule in msg.flagged_rule_results %}
- <detected><bold>{{ rule.name }}</bold></detected>
- <detected><bold>{{ rule.rule.name}}</bold></detected>
{%- if verbose %}
<key>Source:</key> {{ rule.source }}
{# new line #}
Expand All @@ -16,7 +16,7 @@
<header>FAILED RULES</header>
{# new line #}
{%- for rule in msg.failed_rule_results %}
- <fail><bold>{{ rule.name }}</bold></fail>
- <fail><bold>{{ rule.rule.name }}</bold></fail>
<key>Error:</key> {{ rule.error }}
{%- if verbose %}
<key>Source:</key> {{ rule.source }}
Expand All @@ -34,8 +34,8 @@

{%- if msg.normal_query_results | length > 0 %}
{%- for query in (msg.normal_query_results) %}
{%- if query.name %}
- <query><bold>{{ query.name }}</bold></query>
{%- if query.query.name %}
- <query><bold>{{ query.query.name }}</bold></query>
{%- else %}
- <query><bold>Query {{ loop.index }}</bold></query>
{%- endif %}
Expand All @@ -49,8 +49,8 @@

{%- if (verbose and (msg.falsey_query_results | length > 0)) or msg.falsey_query_results|length == 1 %}
{%- for query in (msg.falsey_query_results) %}
{%- if query.name %}
- <query><bold>{{ query.name }}</bold></query>
{%- if query.query.name %}
- <query><bold>{{ query.query.name }}</bold></query>
{%- else %}
- <query><bold>Query {{ loop.index }}</bold></query>
{%- endif %}
Expand All @@ -68,8 +68,8 @@
<header>FAILED QUERIES</header>
{# new line #}
{%- for query in msg.failed_query_results %}
{%- if query.name %}
- <fail><bold>{{ query.name }}</bold></fail>
{%- if query.query.name %}
- <fail><bold>{{ query.query.name }}</bold></fail>
{%- else %}
- <fail><bold>Query {{ loop.index }}</bold></fail>
{%- endif %}
Expand Down

0 comments on commit 8558071

Please sign in to comment.