Skip to content

Commit

Permalink
Add: Add hostnames to report data for templates
Browse files Browse the repository at this point in the history
The main hostnames and a list of all hostnames are added to each host
and scan results now also have their associated hostname added.

This allows adding the hostname info to generated reports.
  • Loading branch information
timopollmeier committed Nov 28, 2023
1 parent b53a637 commit 556e27b
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 0 deletions.
45 changes: 45 additions & 0 deletions pheme/transformation/scanreport/gvmd.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,14 @@ def __get_host_ip_from_result(result) -> str:
return "unknown"


def __get_hostname_from_result(result) -> str:
if isinstance(result, dict):
host = result.get("host", {})
if isinstance(host, dict):
return host.get("hostname", "")
return ""

Check warning on line 88 in pheme/transformation/scanreport/gvmd.py

View check run for this annotation

Codecov / codecov/patch

pheme/transformation/scanreport/gvmd.py#L88

Added line #L88 was not covered by tests


def __return_highest_threat(threats: List[int]) -> str:
"""
returns the highest threat
Expand Down Expand Up @@ -170,6 +178,7 @@ def __create_results_per_host(report: Dict) -> List[Dict]:
"""
host_information_lookup = __create_host_information_lookup(report)
results = report.get("results", {}).get("result", [])
hosts = report.get("host", [])
by_host = {}
host_threat_count = {}
host_severity_count = {}
Expand All @@ -180,6 +189,7 @@ def transform_key(prefix: str, vic: Dict) -> Dict:

def per_result(result):
host_ip = __get_host_ip_from_result(result)
hostname = __get_hostname_from_result(result)
host_dict = by_host.get(host_ip, {})
threat = result.get("threat", "unknown")
port = result.get("port")
Expand All @@ -192,6 +202,7 @@ def per_result(result):
overrides = result.get("overrides", {}).get("override", [])

new_host_result = {
"hostname": hostname,
"port": port,
"threat": threat,
"severity": severity,
Expand All @@ -203,6 +214,9 @@ def per_result(result):
}
host_results = host_dict.get("results", [])
host_results.append(new_host_result)
hostnames = host_dict.get("hostnames", [])
if hostname is not None and hostname not in hostnames:
hostnames.append(hostname)
equipment = host_dict.get("equipment", {})
ports = list(dict.fromkeys(equipment.get("ports", [])))
if port and not port.startswith("general"):
Expand Down Expand Up @@ -275,18 +289,49 @@ def per_override(override):

by_host[host_ip] = {
"host": host_ip,
"hostname": "",
"hostnames": hostnames,
"threats": __host_threat_overview(host_threats),
"severities": __host_severity_overview(host_severities),
"equipment": equipment,
"results": host_results,
}

def per_host(host):
host_ip = host.get("ip")
if host_ip not in by_host:
return

Check warning on line 303 in pheme/transformation/scanreport/gvmd.py

View check run for this annotation

Codecov / codecov/patch

pheme/transformation/scanreport/gvmd.py#L303

Added line #L303 was not covered by tests

def per_detail(detail):
name = detail.get("name", "")
value = detail.get("value", "")

if name == "EXIT_CODE":
return

Check warning on line 310 in pheme/transformation/scanreport/gvmd.py

View check run for this annotation

Codecov / codecov/patch

pheme/transformation/scanreport/gvmd.py#L310

Added line #L310 was not covered by tests

if name == "hostname" and by_host[host_ip]["hostname"] == "":
by_host[host_ip]["hostname"] = value

Check warning on line 313 in pheme/transformation/scanreport/gvmd.py

View check run for this annotation

Codecov / codecov/patch

pheme/transformation/scanreport/gvmd.py#L313

Added line #L313 was not covered by tests

details = host.get("detail", [])
if isinstance(details, dict):
per_detail(details)

Check warning on line 317 in pheme/transformation/scanreport/gvmd.py

View check run for this annotation

Codecov / codecov/patch

pheme/transformation/scanreport/gvmd.py#L317

Added line #L317 was not covered by tests
else:
for detail in details:
per_detail(detail)

# lists with just one element can be parsed as dict by xmltodict
if isinstance(results, dict):
per_result(results)
else:
for result in results:
per_result(result)

if isinstance(hosts, dict):
per_host(hosts)
elif isinstance(hosts, list):
for host in hosts:
per_host(host)

threat_count_dict = {
__threats[i]: count for i, count in enumerate(threat_count)
}
Expand Down
2 changes: 2 additions & 0 deletions pheme/transformation/scanreport/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ def describe():
results=[
dict(
host="str; ip address of host",
hostname="str; main hostname of the host",
threats={
"high": "int; amount of high nvts in host",
"medium": "int; amount of medium nvts in host",
Expand Down Expand Up @@ -145,6 +146,7 @@ def describe():
"nvt.refs.ref": [{"name_of_ref": ["str; ref_vallue"]}],
"nvt.solution.type": "str; nvt.solution.type; optional",
"nvt.solution.text": "str; nvt.solution.text; optional",
"hostname": "str; result specific hostname; optional",
"port": "str; port; optional",
"severity": "str; severity; optional",
"qod.value": "str; qod.value; optional",
Expand Down

0 comments on commit 556e27b

Please sign in to comment.