displayMappedFields

Display the mapped fields in a dynamic-section.

python · Common Scripts

Details

IDdisplayMappedFields
Languagepython
From Version6.8.0
Docker Imagedemisto/python3:3.12.13.10404775
Tagsdynamic-section
import demistomock as demisto  # noqa: F401
from CommonServerPython import *  # noqa: F401
import html as html_module

# List of empty values that we want to filter out.
EMPTY_VALUES = [
    "{}",
    "[{}]",
    "[{}, {}]",
    "[{}, {}, {}]",
    "0001-01-01T00:00:00Z",
    "containmentsla",
    "remediationsla",
    "detectionsla",
    "triagesla",
]


def extract_keys_with_values(obj, parent_key=""):
    """
    Extracts the keys with values in the JSON object
    """
    items = []
    for k, v in obj.items():
        new_key = f"{parent_key}.{k}" if parent_key else k
        if isinstance(v, dict):
            items.extend(extract_keys_with_values(v, new_key))
        else:
            items.append((new_key, v))
    return items


def escape_for_html_table(value):
    """Escape value for safe insertion into HTML table cells."""
    return html_module.escape(str(value))


def format_data_to_rows(items):
    """
    Formats the extracted data into (key, value) rows.

    Each row is kept as a tuple rather than a pipe-delimited string so that values
    that themselves contain the pipe character are never split into extra table columns.
    """
    rows = []
    for key, value in items:
        if isinstance(value, list):
            # If the value is a list, join the items with a comma for display
            value = ", ".join(map(str, value))
        rows.append((str(key), str(value)))
    return rows


def convert_to_html(rows):
    html = [
        """<table style="border-collapse:collapse;"><tbody style="font-family:Lato,Assistant,sans-serif;font-weight:600;font-size:12px;text-align:left;padding: 1px 0px 0px;margin:0px 5px 0px 0px;contrast:4.95">"""  # noqa: E501
    ]  # noqa: E501
    for key, value in rows:
        html.append("<tr>")
        for i, column in enumerate((key.strip(), value.strip())):
            if column:
                style = "color:var(--xdr-on-background-secondary)" if i == 0 else "color:var(--xdr-on-background)"
                html.append(f'<td style="{style}">{escape_for_html_table(column)}</td>')
        html.append("</tr>")
    html.append("</tbody></table>")
    return "".join(html)


def remove_empty_rows(rows):
    # Filter out rows whose value is exactly an empty marker (not merely containing one)
    return [(key, value) for key, value in rows if value.strip() not in EMPTY_VALUES]


def main():
    # Fetch alert mapped fields
    incident = demisto.incident()
    fields = incident.get("CustomFields", {})
    fields = fields if isinstance(fields, dict) else {}

    # Extract the keys with values
    items = extract_keys_with_values(fields)
    # Format the data into a rows
    rows = format_data_to_rows(items)
    # Remove keys with empty dictionaries
    filtered_rows = remove_empty_rows(rows)
    # Convert the rows to HTML
    html = convert_to_html(filtered_rows)

    demisto.results({"ContentsFormat": formats["html"], "Type": entryTypes["note"], "Contents": html})


if __name__ in ("builtins", "__builtin__", "__main__"):
    main()