Source code for greynoise.cli.formatter

# coding=utf-8
"""Output formatters."""

from __future__ import print_function

import functools
import json
import shutil

import ansimarkup
import colorama
from dict2xml import dict2xml
from jinja2 import Environment, PackageLoader, select_autoescape

JINJA2_ENV = Environment(
    loader=PackageLoader("greynoise.cli"),
    autoescape=select_autoescape(disabled_extensions=["txt.j2"]),
)

colorama.init()
DIM = "<dim>"
ANSI_MARKUP = ansimarkup.AnsiMarkup(
    tags={
        "header": ansimarkup.parse("<bold>"),
        "key": ansimarkup.parse("<blue>"),
        "value": ansimarkup.parse("<green>"),
        "noise": ansimarkup.parse("<light-yellow>"),
        "not-noise": ansimarkup.parse(DIM),
        "riot": ansimarkup.parse("<magenta>"),
        "not-riot": ansimarkup.parse(DIM),
        "malicious": ansimarkup.parse("<light-red>"),
        "unknown": ansimarkup.parse(DIM),
        "benign": ansimarkup.parse("<light-green>"),
    }
)


[docs]def colored_output(function): """Decorator that converts ansi markup into ansi escape sequences. :param function: Function that will return text using ansi markup. :type function: callable :returns: Wrapped function that converts markup into escape sequences. :rtype: callable """ @functools.wraps(function) def wrapper(*args, **kwargs): output = function(*args, **kwargs) return ANSI_MARKUP(output) return wrapper
[docs]def json_formatter(result, _verbose): """Format result as json.""" if isinstance(result, list) and "data" in result[0]: res = [json.dumps(record) for record in result[0]["data"]] output = "\n".join(res) else: output = json.dumps(result, indent=4, sort_keys=True) return output
[docs]def xml_formatter(result, _verbose): """Format result as xml.""" xml_formatted = "" if type(result) is list: xml_formatted = dict2xml({"item": result}, wrap="root", indent="\t") else: xml_formatted = dict2xml(result, wrap="root", indent=" ") # dict2xml does not add header, so add header manually xml_header = '<?xml version="1.0" ?>' return "{}\n{}".format(xml_header, xml_formatted)
[docs]def get_location(metadata): """Get location from ip context metadata.""" city = metadata["city"] country = metadata["country"] country_code = metadata["country_code"] location = [] if city: location.append("{},".format(city)) if country: location.append(country) if country_code: location.append("({})".format(country_code)) return " ".join(location)
[docs]@colored_output def ip_context_formatter(results, verbose): """Convert IP context result into human-readable text.""" for ip_context in results: if "seen" in ip_context: if ip_context["seen"]: metadata = ip_context["metadata"] metadata["location"] = get_location(metadata) template = JINJA2_ENV.get_template("ip_context.txt.j2") else: template = JINJA2_ENV.get_template("ip_context.txt.j2") elif "noise" in ip_context or "riot" in ip_context: template = JINJA2_ENV.get_template("ip_community.txt.j2") return template.render(results=results, verbose=verbose)
[docs]@colored_output def ip_quick_check_formatter(results, verbose): """Convert IP quick check result into human-readable text.""" template = JINJA2_ENV.get_template("ip_quick_check.txt.j2") return template.render(results=results, verbose=verbose)
[docs]@colored_output def ip_multi_context_formatter(results, verbose): """Convert IP multi context result into human-readable text.""" template = JINJA2_ENV.get_template("ip_multi_context.txt.j2") return template.render(results=results, verbose=verbose)
[docs]@colored_output def gnql_query_formatter(results, verbose): """Convert GNQL query result into human-readable text.""" for result in results: if "data" in result: for ip_context in result["data"]: if ip_context["seen"]: metadata = ip_context["metadata"] metadata["location"] = get_location(metadata) template = JINJA2_ENV.get_template("gnql_query.txt.j2") return template.render(results=results, verbose=verbose)
[docs]@colored_output def gnql_stats_formatter(results, verbose): """Convert GNQL stats result into human-readable text.""" template = JINJA2_ENV.get_template("gnql_stats.txt.j2") max_width, _ = shutil.get_terminal_size() return template.render(results=results, verbose=verbose, max_width=max_width)
[docs]@colored_output def analyze_formatter(result, verbose): """Conver analyze result into human-readable text.""" template = JINJA2_ENV.get_template("analyze.txt.j2") max_width, _ = shutil.get_terminal_size() return template.render(result=result, verbose=verbose, max_width=max_width)
[docs]@colored_output def riot_formatter(results, verbose): """Convert RIOT to human-readable text.""" template = JINJA2_ENV.get_template("riot.txt.j2") max_width, _ = shutil.get_terminal_size() return template.render(results=results, verbose=verbose, max_width=max_width)
[docs]@colored_output def interesting_formatter(results, verbose): """Convert RIOT to human-readable text.""" template = JINJA2_ENV.get_template("interesting.txt.j2") max_width, _ = shutil.get_terminal_size() return template.render(results=results, verbose=verbose, max_width=max_width)
FORMATTERS = { "json": json_formatter, "xml": xml_formatter, "txt": { "analyze": analyze_formatter, "ip": ip_context_formatter, "quick": ip_quick_check_formatter, "query": gnql_query_formatter, "stats": gnql_stats_formatter, "riot": riot_formatter, "interesting": interesting_formatter, "ip-multi": ip_multi_context_formatter, }, }