From 29d82bf86efbdc59f5a8eaba8079aa684fef7302 Mon Sep 17 00:00:00 2001 From: "gioacchino.vino" <gioacchino.vino@infn.it> Date: Fri, 29 Sep 2023 11:37:51 +0200 Subject: [PATCH] Enhanced report summary --- files/script.py | 140 ++++++++++++++++++++++++++++++------------------ 1 file changed, 87 insertions(+), 53 deletions(-) diff --git a/files/script.py b/files/script.py index 605d64b..0e3c421 100644 --- a/files/script.py +++ b/files/script.py @@ -24,7 +24,7 @@ def create_connection(): gmp.authenticate(auth_name, auth_passwd) return gmp except: - print("WARNING: Connection error with the gmp endpoint. Remaining {retry} retries") + logging.warning(f"Connection error with the gmp endpoint. Remaining {retry} retries") retry -= 1 sleep(0.5) raise Exception("Impossible connect to the gmp endpoint even after 5 retries") @@ -32,7 +32,7 @@ def create_connection(): def get_version(): gmp = create_connection() res = gmp.get_version() - return res + return res.xpath('version/text()')[0] ########## PORT LIST ################################## @@ -45,6 +45,7 @@ def create_port_list(port_list_name, ports): id = res.xpath('@id')[0] return {'name': port_list_name, 'id': id} else: + logging.error(f"ERROR during Port list creation. Status code: {status}, msg: {status_text}") msg = f"ERROR during Port list creation. Status code: {status}, msg: {status_text}" raise Exception(msg) @@ -66,9 +67,9 @@ def delete_port_list(port_list): status = res.xpath('@status')[0] status_text = res.xpath('@status_text')[0] if status == "200": - print(f"Port_list with id: {port_list['id']} and name: {port_list['name']} DELETED") + logging.info(f"Port_list with id: {port_list['id']} and name: {port_list['name']} DELETED") else: - print(f"ERROR {status}: {status_text}") + logging.error(f"ERROR {status}: {status_text}") def get_or_create_port_list(port_list_name, ports): res = get_port_lists(port_list_name) @@ -78,7 +79,7 @@ def get_or_create_port_list(port_list_name, ports): elif len(res) == 1: return res[0] else: - print(f"WARNING Found {len(res)} results.") + logging.warning(f"Found {len(res)} results.") return res ############## TARGET ################################## @@ -121,9 +122,9 @@ def delete_target(target): status = res.xpath('@status')[0] status_text = res.xpath('@status_text')[0] if status == "200": - print(f"Port_list with id: {target['id']} and name: {target['name']} DELETED") + logging.info(f"Port_list with id: {target['id']} and name: {target['name']} DELETED") else: - print(f"ERROR {status}: {status_text}") + logging.error(f"ERROR {status}: {status_text}") def get_or_create_target(target_name,ip,port_list,ovs_ssh_credential): res = get_targets(target_name) @@ -238,9 +239,9 @@ def delete_task(task): status = res.xpath('@status')[0] status_text = res.xpath('@status_text')[0] if status == "200": - print(f"Target with id: {task['id']} and name: {task['name']} DELETED") + logging.info(f"Target with id: {task['id']} and name: {task['name']} DELETED") else: - print(f"ERROR {status}: {status_text}") + logging.error(f"ERROR {status}: {status_text}") ############## REPORTS #####################################3 @@ -273,17 +274,21 @@ def get_progress(task): def wait_for_task_ending(task, timeout=3600): start_time = time() + logging.info("Waiting for scans ends the task") while True: status, progress = get_progress(task) if status not in ["New","Requested","Queued","Running","Done"]: # ["Interrupted", ...] + logging.warning(f"Waiting for scans ends the task. Status: {status}") return False if status == "Done" and progress == -1: + logging.info(f"Waiting for scans ends the task. Status: {status}") return True if time() - start_time > timeout: - print("TIMEOUT during waiting for task ending") + logging.error("TIMEOUT during waiting for task ending") return False - sleep(60) - + logging.debug(f"Waiting for the task ends. Now {int(time() - start_time)}s from start. Status: {status}") + sleep(10) + def save_report(task,report_format_id, report_filename ): gmp = create_connection() res = gmp.get_report(task['report_id'], @@ -311,21 +316,30 @@ def save_severity_report(task, severity_filename): with open(severity_filename, "w") as f: f.write(severity) -def get_severity(task): - dict_severity = {"Log": 0, "Low": 1, "Medium": 2, "High": 3} +def get_report_info(task): + report = dict() gmp = create_connection() res = gmp.get_report(task['report_id'], - report_format_id=report_formats.anonymous_xml, + report_format_id=report_formats.anonymous_xml, ignore_pagination=True, details="1") - severities = res.xpath('report/report/ports/port/threat/text()') - old_num_severity = 0 - severity = "Log" - for sev in severities: - if dict_severity[sev] > old_num_severity: - old_num_severity = dict_severity[sev] - severity = sev - return severity + threats = res.xpath('report/report/ports/port/threat/text()') + ports = res.xpath('report/report/ports/port/text()') + severities = res.xpath('report/report/ports/port/severity/text()') + severities = list(map(lambda a : float(a), severities)) + for p,t,s in zip(ports, threats, severities): + report[p] = {'severity': s, 'threat': t} + glob_severity = -1 # returned severities are null or positive + glob_threat = 'Log' + for threat,severity in zip(threats,severities): + if severity > glob_severity: + glob_severity = severity + glob_threat = threat + glob_severity = severity + + report['global'] = {'threat': glob_threat, 'severity': glob_severity} + return report + def get_reports(filter_str="rows=-1"): lo = [] @@ -362,18 +376,21 @@ def get_severity_from_number(num): else: return "Undefined" -def process_global_severity(severities): - max_num_severity = 0 - for _,sev in severities.items(): - numeric_severity = get_numeric_severity(sev) - if numeric_severity > max_num_severity: - max_num_severity = numeric_severity - severities['global_severity'] = get_severity_from_number(max_num_severity) - if max_num_severity < 2: - severities['global'] = "OK" +def process_global_reports_info(reports): + glob_severity = -1 + glob_threat = 'Log' + for host in reports: + host_glob_severity = reports[host]['global']['severity'] + if host_glob_severity > glob_severity: + glob_severity = host_glob_severity + glob_threat = reports[host]['global']['threat'] + reports['deployment'] = {'severity': glob_severity, + 'threat': glob_threat} + if reports['deployment']['severity'] < 2: + reports['global'] = "OK" else: - severities['global'] = "NOK" - return severities + reports['global'] = "NOK" + return reports def pretty_json(j): return json.dumps(j,sort_keys=True,indent=4) @@ -397,7 +414,7 @@ def import_dep_info(file_path, endpoints_to_scan): port = '80' else: raise Exception(f"Impossible to parse the endpoint port. Endpoint: {endpoint}") - print(f"Endpoint: {host}:{port}") + logging.info(f"Endpoint: {host}:{port}") if host not in endpoints: endpoints[host] = {"22"} endpoints[host].add(port) @@ -405,10 +422,28 @@ def import_dep_info(file_path, endpoints_to_scan): ################ MAIN ####################################### -auth_name = os.getenv('GMP_USER') -auth_passwd = os.getenv('GMP_PASSWORD') -print(auth_name, auth_passwd) -logging.basicConfig(filename='debug.log', level=logging.DEBUG) +logging.basicConfig( + filename='debug.log', + level=logging.DEBUG, + format='%(asctime)s %(levelname)-8s %(message)s', + datefmt='%Y-%m-%d %H:%M:%S', + filemode='w') +logging.info("\n\nStart scan application") + +if os.environ.get('GMP_USER') is not None and \ + os.environ.get('GMP_USER') != '': + auth_name = os.getenv('GMP_USER') +else: + logging.error("GMP_USER env var is not defined\nexit") + raise Exception("GMP_USER env var is not defined") + +if os.environ.get('GMP_PASSWORD') is not None and \ + os.environ.get('GMP_PASSWORD') != '': + auth_passwd = os.getenv('GMP_PASSWORD') +else: + logging.error("GMP_PASSWORD env var is not defined\nexit") + raise Exception("GMP_PASSWORD env var is not defined") + local_ip = "127.0.0.1" connection = TLSConnection(hostname=local_ip) transform = EtreeTransform() @@ -434,20 +469,20 @@ logging.info(f"dep_json: {dep_json}") logging.info(f"output_dir: {output_dir}") endpoints = import_dep_info(dep_json, endpoints_to_scan) -logging.info(f"endpoints\n{pretty_json(endpoints)}") +logging.info(f"endpoints: {endpoints}") # test gmp connection logging.info(f"gvm version: {get_version()}") -severities = dict() +reports = dict() for host,ports in endpoints.items(): - logging.info(host,ports) + logging.info(f"endpoint: {host}:{ports}") target_name = f"{auth_name}_target_{host}" task_name = f"{auth_name}_task_{host}" port_list_name = f"{auth_name}_pl_{host}" report_filename = f"{output_dir}/{host}-report.txt" - severity_filename = f"{output_dir}/severity.json" + summary_filename = f"{output_dir}/summary-report.json" port_list = get_or_create_port_list(port_list_name,ports) logging.info(f"Port list:\n {pretty_json(port_list)}") @@ -462,15 +497,14 @@ for host,ports in endpoints.items(): task = start_task(task) if wait_for_task_ending(task,wait_timeout): save_report(task,report_formats.txt, report_filename) - severities[host] = get_severity(task) + reports[host] = get_report_info(task) else: - severities[host] = f"ERROR Task: {task['id']}" + reports[host] = f"ERROR Task: {task['id']}" - delete_task(task) - delete_target(target) - delete_port_list(port_list) - -severities = process_global_severity(severities) -with open(severity_filename, "w") as f: - f.write(json.dumps(severities)) - \ No newline at end of file + #delete_task(task) + #delete_target(target) + #delete_port_list(port_list) + +reports = process_global_reports_info(reports) +with open(summary_filename, "w") as f: + f.write(json.dumps(reports)) \ No newline at end of file -- GitLab