diff --git a/scripts/monthly-report-gos24.10.gmp.py b/scripts/monthly-report-gos24.10.gmp.py index 97654671..23d601d8 100644 --- a/scripts/monthly-report-gos24.10.gmp.py +++ b/scripts/monthly-report-gos24.10.gmp.py @@ -2,41 +2,19 @@ # # SPDX-License-Identifier: GPL-3.0-or-later -import sys -from argparse import Namespace -from datetime import date, timedelta +from argparse import ArgumentParser, Namespace, RawDescriptionHelpFormatter +from datetime import date, datetime, timedelta from gvm.protocols.gmp import Gmp from terminaltables import AsciiTable -def check_args(args: Namespace) -> None: - len_args = len(args.script) - 1 - if len_args < 2: - message = """ - This script will display all vulnerabilities from the hosts of the - reports in a given month! - It needs two parameters after the script name. - First one is the month and second one is the year. - Both parameters are plain numbers, so no text. - - Explicitly made for GOS 24.10. - - 1. -- month of the monthly report - 2. -- year of the monthly report - - Example: - $ gvm-script --gmp-username name --gmp-password pass \ - ssh --hostname scripts/monthly-report2.gmp.py 05 2019 - """ - print(message) - sys.exit() - - -def print_reports(gmp: Gmp, from_date: date, to_date: date) -> None: +def print_reports( + gmp: Gmp, from_date: date, to_date: date, reports_choice: str +) -> None: host_filter = ( f"rows=-1 and modified>{from_date.isoformat()} " - f"and modified<{to_date.isoformat()}" + f"and created<{to_date.isoformat()}" ) hosts_xml = gmp.get_hosts(filter_string=host_filter) @@ -45,9 +23,31 @@ def print_reports(gmp: Gmp, from_date: date, to_date: date) -> None: sum_high = 0 sum_medium = 0 sum_low = 0 - table_data = [ - ["Hostname", "IP", "Bericht", "critical", "high", "medium", "low"] - ] + + if reports_choice == "last": + table_header = [ + "Hostname", + "IP", + "Report", + "Critical", + "High", + "Medium", + "Low", + ] + elif reports_choice == "list": + table_header = [ + "Hostname", + "IP", + "Reports", + "Critical", + "High", + "Medium", + "Low", + ] + else: + table_header = ["Hostname", "IP", "Critical", "High", "Medium", "Low"] + + table_data = [table_header] for host in hosts_xml.xpath("asset"): ip = host.xpath("name/text()")[0] @@ -62,30 +62,76 @@ def print_reports(gmp: Gmp, from_date: date, to_date: date) -> None: hostname = hostnames[0] results = gmp.get_results( - details=False, filter_string=f"host={ip} and severity>0.0" + details=False, + filter_string=( + f"rows=-1 host={ip} and severity>0.0" + f" and modified>{from_date.isoformat()}" + f" and modified<{to_date.isoformat()}" + ), ) - low = int(results.xpath('count(//result/threat[text()="Low"])')) - sum_low += low + unique_vt_results = results.xpath( + "result[" + " not (./nvt/@oid = preceding-sibling::result/nvt/@oid)" + "]" + ) + if len(unique_vt_results) == 0: + continue - medium = int(results.xpath('count(//result/threat[text()="Medium"])')) - sum_medium += medium + low = medium = high = critical = 0 + for result in unique_vt_results: + threat = result.findtext("threat") + if threat == "Critical": + critical += 1 + elif threat == "High": + high += 1 + elif threat == "Medium": + medium += 1 + elif threat == "Low": + low += 1 - high = int(results.xpath('count(//result/threat[text()="High"])')) + sum_low += low + sum_medium += medium sum_high += high - - critical = int( - results.xpath('count(//result/threat[text()="Critical"])') - ) sum_critical += critical - best_os_cpe_report_id = host.xpath( - 'host/detail/name[text()="best_os_cpe"]/../source/@id' - )[0] - - table_data.append( - [hostname, ip, best_os_cpe_report_id, critical, high, medium, low] - ) + if reports_choice == "none": + table_data.append([hostname, ip, critical, high, medium, low]) + else: + report_host_identifiers = host.xpath( + "identifiers/identifier[source/deleted = 0 and" + ' (source/type = "Report Host"' + ' or source/type = "Report Host Detail")]' + ) + report_ids = [] + for identifier in report_host_identifiers: + mod_date = datetime.fromisoformat( + identifier.findtext("modification_time") + ).date() + + if mod_date >= to_date or mod_date < from_date: + continue + + report_ids.append(identifier.find("source").get("id")) + if reports_choice == "last": + break + + if reports_choice == "last": + table_data.append( + [hostname, ip, report_ids[0], critical, high, medium, low] + ) + else: + table_data.append( + [ + hostname, + ip, + ",\n".join(report_ids) + "\n", + critical, + high, + medium, + low, + ] + ) table = AsciiTable(table_data) print(f"{table.table}\n") @@ -102,16 +148,45 @@ def print_reports(gmp: Gmp, from_date: date, to_date: date) -> None: def main(gmp: Gmp, args: Namespace) -> None: # pylint: disable=undefined-variable - check_args(args) + description_message = """ +This script will display all vulnerabilities from the hosts of the \ +reports in a given month and year. +These must be given after the script name as plain numbers. + +This version is explicitly made for GOS 24.10. + +Example: + $ gvm-script --gmp-username name --gmp-password pass \ +ssh --hostname scripts/monthly-report2.gmp.py 05 2019 + """ + + parser = ArgumentParser( + prog=("gvm-script [...] " + args.script[0]), + formatter_class=RawDescriptionHelpFormatter, + prefix_chars="+", + description=description_message, + ) + parser.add_argument("month", type=int, help="month of the monthly report") + parser.add_argument("year", type=int, help="year of the monthly report") + parser.add_argument( + "++reports", + choices=["none", "last", "list"], + default="last", + help=( + "what to show in the reports column:" + ' "none": do not show a reports column;' + ' "last": show the last report in the selected month;' + ' "list": show a list of reports in the selected month.' + ), + ) + script_args, _ = parser.parse_known_args(args.script[1:]) - month = int(args.script[1]) - year = int(args.script[2]) - from_date = date(year, month, 1) + from_date = date(script_args.year, script_args.month, 1) to_date = from_date + timedelta(days=31) # To have the first day in month to_date = to_date.replace(day=1) - print_reports(gmp, from_date, to_date) + print_reports(gmp, from_date, to_date, script_args.reports) if __name__ == "__gmp__":