From 08d8a9510b33109414003feb16f353bf1e6a78d0 Mon Sep 17 00:00:00 2001 From: "gioacchino.vino" <gioacchino.vino@infn.it> Date: Tue, 26 Sep 2023 18:12:14 +0200 Subject: [PATCH] Added greenbone check --- files/greenbone_check.py | 471 --------------------------------------- jenkinsfile/Jenkinsfile | 5 +- 2 files changed, 3 insertions(+), 473 deletions(-) delete mode 100644 files/greenbone_check.py diff --git a/files/greenbone_check.py b/files/greenbone_check.py deleted file mode 100644 index 053146e..0000000 --- a/files/greenbone_check.py +++ /dev/null @@ -1,471 +0,0 @@ -from gvm.connections import TLSConnection -from gvm.protocols.gmpv208 import Gmp, AliveTest -from gvm.transforms import EtreeTransform -from gvm.xml import pretty_print -from time import time, sleep -import logging -import json -import base64 -from sys import argv, exit -import socket -import os - -def get_version_old(): - with Gmp(connection, transform=transform) as gmp: - gmp.authenticate(auth_name, auth_passwd) - pretty_print(gmp.get_version()) - -def create_connection(): - connection_retries = 5 - retry = connection_retries - while(retry > 0): - try: - gmp = Gmp(connection, transform=transform) - gmp.authenticate(auth_name, auth_passwd) - return gmp - except: - print("WARNING: 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") - -def get_version(): - gmp = create_connection() - res = gmp.get_version() - pretty_print(res) - -########## PORT LIST ################################## - -def create_port_list(port_list_name, ports): - gmp = create_connection() - res = gmp.create_port_list(port_list_name, ','.join(ports)) - status = res.xpath('@status')[0] - status_text = res.xpath('@status_text')[0] - if status == "201": - id = res.xpath('@id')[0] - return {'name': port_list_name, 'id': id} - else: - msg = f"ERROR during Port list creation. Status code: {status}, msg: {status_text}" - raise Exception(msg) - -def get_port_lists(filter_str="rows=-1"): - l_o = [] - gmp = create_connection() - res = gmp.get_port_lists(filter_string=filter_str) - for pl in res.xpath('port_list'): - o = dict() - o['name'] = pl.xpath('name/text()')[0] - o['id'] = pl.xpath('@id')[0] - o['in_use'] = pl.xpath('in_use/text()')[0] - l_o.append(o) - return l_o - -def delete_port_list(port_list): - gmp = create_connection() - res = gmp.delete_portlist(port_list['id']) - 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") - else: - print(f"ERROR {status}: {status_text}") - -def get_or_create_port_list(port_list_name, ports): - res = get_port_lists(port_list_name) - if len(res) == 0: - port_list = create_port_list(port_list_name, ports) - return get_port_lists(port_list['id'])[0] - elif len(res) == 1: - return res[0] - else: - print(f"WARNING Found {len(res)} results.") - return res - -############## TARGET ################################## - -def create_target(name,ip,port_list,ovs_ssh_credential): - o = dict() - gmp = create_connection() - res = gmp.create_target( - name=name, - comment = "", - hosts=[ip], - port_list_id = port_list['id'], - ssh_credential_id = ovs_ssh_credential['id'], - alive_test=AliveTest('Consider Alive')) - status = res.xpath('@status')[0] - status_text = res.xpath('@status_text')[0] - if status == "201": - id = res.xpath('@id')[0] - return {'name': name, 'id': id} - else: - msg = f"ERROR during Target creation. Status code: {status}, msg: {status_text}" - raise Exception(msg) - -def get_targets(filter_str): - res = [] - gmp = create_connection() - targets = gmp.get_targets(filter_string=filter_str) - for target in targets.xpath('target'): - o = dict() - o['name'] = target.xpath('name/text()')[0] - o['hosts'] = target.xpath('hosts/text()')[0] - o['id'] = target.xpath('@id')[0] - o['in_use'] = target.xpath('in_use/text()')[0] - res.append(o) - return res - -def delete_target(target): - gmp = create_connection() - res = gmp.delete_target(target['id']) - 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") - else: - print(f"ERROR {status}: {status_text}") - -def get_or_create_target(target_name,ip,port_list,ovs_ssh_credential): - res = get_targets(target_name) - if len(res) == 0: - t = create_target(target_name,ip,port_list,ovs_ssh_credential) - return get_targets(t['id'])[0] - elif len(res) == 1: - return res[0] - else: - print(f"Found {len(res)} results. Return None") - return res - -def search_and_delete_target(target_name): - targets = get_targets(target_name) - if len(targets) == 1: - delete_target(targets[0]['id']) - else: - raise("Multiple results for search") - -def search_and_delete_all_targets(target_name): - targets = get_targets(target_name) - for target in targets: - delete_target(target) - -############## TASK ################################## - -def create_task(name, config, target, scanner): - o = dict() - gmp = create_connection() - res = gmp.create_task( - name=name, - config_id=config['id'], - target_id=target['id'], - scanner_id=scanner['id']) - status = res.xpath('@status')[0] - status_text = res.xpath('@status_text')[0] - if status == "201": - id = res.xpath('@id')[0] - return {'name': name, 'id': id} - else: - msg = f"ERROR during Task creation. Status code: {status}, msg: {status_text}" - raise Exception(msg) - -def get_tasks(filter_str): - res = [] - gmp = create_connection() - tasks = gmp.get_tasks(filter_string=filter_str) - for task in tasks.xpath('task'): - o = dict() - o['name'] = task.xpath('name/text()')[0] - o['id'] = task.xpath('@id')[0] - o['progress'] = task.xpath('progress/text()')[0] - o['in_use'] = task.xpath('in_use/text()')[0] - o['status'] = task.xpath('status/text()')[0] - o['target_id'] = task.xpath('target/@id')[0] - try: - o['report_id'] = task.xpath('last_report/report/@id')[0] - except: - pass - res.append(o) - return res - -def get_or_create_task(task_name, config, target, scanner): - res = get_tasks(task_name) - if len(res) == 0: - t = create_task(task_name, config, target, scanner) - return get_tasks(t['id'])[0] - elif len(res) == 1: - return res[0] - else: - print(f"Found {len(res)} results. Return None") - return res - -def get_all_tasks(): - res = [] - gmp = create_connection() - tasks = gmp.get_tasks(filter_string="rows=-1") - for task in tasks.xpath('task'): - o = dict() - o['name'] = task.xpath('name/text()')[0] - o['id'] = task.xpath('@id')[0] - o['progress'] = task.xpath('progress/text()')[0] - o['in_use'] = task.xpath('in_use/text()')[0] - o['status'] = task.xpath('status/text()')[0] - o['target_id'] = task.xpath('target/@id')[0] - try: - o['report_id'] = task.xpath('last_report/report/@id')[0] - except: - pass - res.append(o) - return res - -def search_and_delete_all_tasks(filter_str): - tasks = get_tasks(filter_str) - for task in tasks: - delete_task(task) - -def start_task(task): - gmp = create_connection() - res = gmp.start_task(task['id']) - task['report_id'] = res.xpath('report_id/text()')[0] - return task - -def stop_task(task): - gmp = create_connection() - res = gmp.stop_task(task['id']) - pretty_print(res) - -def delete_task(task): - gmp = create_connection() - res = gmp.delete_task(task['id']) - 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") - else: - print(f"ERROR {status}: {status_text}") - -############## REPORTS #####################################3 - -class report_formats: - anonymous_xml = "5057e5cc-b825-11e4-9d0e-28d24461215b" - csv_results = "c1645568-627a-11e3-a660-406186ea4fc5" - itg = "77bd6c4a-1f62-11e1-abf0-406186ea4fc5" - pdf = "c402cc3e-b531-11e1-9163-406186ea4fc5" - txt = "a3810a62-1f62-11e1-9219-406186ea4fc5" - xml = "a994b278-1f62-11e1-96ac-406186ea4fc5" - -def get_report_formats(): - gmp = create_connection() - res = gmp.get_report_formats() - for f in res.xpath('report_format'): - name = f.xpath('name/text()')[0] - id = f.xpath('@id')[0] - print(id,name) - -def get_report_format(id): - gmp = create_connection() - res = gmp.get_report_formats() - pretty_print(res) - -def get_progress(task): - task_info = get_tasks(task['id'])[0] - status = task_info['status'] # New -> Requested -> Queued -> Running -> Done - progress = int(task_info['progress'])# 0 0 0 0 -> 100 -1 - return status, progress - -def wait_for_task_completition(task, timeout=3600): - start_time = time() - while True: - status, progress = get_progress(task) - if status not in ["New","Requested","Queued","Running","Done"]: # ["Interrupted", ...] - return False - if status == "Done" and progress == -1: - return True - if time() - start_time > timeout: - print("TIMEOUT during waiting for task completition") - return False - sleep(60) - -def save_report(task,report_format_id, report_filename ): - gmp = create_connection() - res = gmp.get_report(task['report_id'], - report_format_id=report_format_id, - ignore_pagination=True, - details="1") - code = str(res.xpath('report/text()')[0]) - with open(report_filename, "wb") as fh: - fh.write(base64.b64decode(code)) - -def save_severity_report(task, severity_filename): - dict_severity = {"Log": 0, "Low": 1, "Medium": 2, "High": 3} - gmp = create_connection() - res = gmp.get_report(task['report_id'], - 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 - with open(severity_filename, "w") as f: - f.write(severity) - -def get_severity(task): - dict_severity = {"Log": 0, "Low": 1, "Medium": 2, "High": 3} - gmp = create_connection() - res = gmp.get_report(task['report_id'], - 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 - -def get_reports(filter_str="rows=-1"): - lo = [] - gmp = create_connection() - reports = gmp.get_reports(filter_string = filter_str) - for report in reports.xpath('report'): - o = dict() - o['task_name'] = report.xpath('task/name/text()')[0] - o['id'] = report.xpath('@id')[0] - lo.append(o) - return lo - -def get_numeric_severity(severity): - if severity == "Log": - return 0 - elif severity == "Low": - return 1 - elif severity == "Medium": - return 2 - elif severity == "High": - return 3 - else: - return 4 - -def get_severity_from_number(num): - if num == 0: - return "Low" - elif num == 1: - return "Low" - elif num == 2: - return "Medium" - elif num == 3: - return "High" - 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" - else: - severities['global'] = "NOK" - return severities - -def print_pretty_json(j): - print(json.dumps(j,sort_keys=True,indent=4)) - -def import_dep_info(file_path, endpoints_to_scan): - with open(file_path) as f: - data = json.load(f) - - endpoints = dict() - for key in data['outputs'].keys(): - if key in endpoints_to_scan: - endpoint = str(data['outputs'][key]) - prefix,url = endpoint.split("://") - if ":" in url: - host,port = url.split(":") - else: - host = url - if prefix == "https": - port = '443' - elif prefix == 'http': - port = '80' - else: - raise Exception(f"Impossible to parse the endpoint port. Endpoint: {endpoint}") - print(f"Endpoint: {host}:{port}") - if host not in endpoints: - endpoints[host] = {"22"} - endpoints[host].add(port) - return endpoints - -################ 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) -#local_ip = socket.gethostbyname(socket.gethostname()) -#local_ip = '127.0.0.1' -local_ip = os.getenv('HOST_IP') -connection = TLSConnection(hostname=local_ip) -transform = EtreeTransform() -config = {'id':"9866edc1-8869-4e80-acac-d15d5647b4d9"} -scanner = {'id': "08b69003-5fc2-4037-a479-93b440211c73"} -ovs_ssh_credential = {'id': "b9af5845-8b87-4378-bca4-cee39a894c17"} -wait_timeout = 3600 #1h - -if len(argv) != 4: - print("Please pass three parameters:") - print("- endpoints to scans [endpoints1,endpoint2,endpoint3,...]") - print("- dep.json path [/home/gmp/workspace/dep.json]") - print("- output directory [/home/gmp/workspace]") - exit(1) - -endpoints_to_scan = argv[1].split(',') -dep_json = argv[2] -output_dir = argv[3] -print("endpoints_to_scan", endpoints_to_scan) -print("dep_json", dep_json) -print("output_dir", output_dir) - -endpoints = import_dep_info(dep_json, endpoints_to_scan) -#print_pretty_json(endpoints) - -# test gmp connection -get_version() - -severities = dict() -for host,ports in endpoints.items(): - print(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" - - port_list = get_or_create_port_list(port_list_name,ports) - print_pretty_json(port_list) - target = get_or_create_target(target_name,host,port_list,ovs_ssh_credential) - print_pretty_json(target) - task = get_or_create_task(task_name, config, target,scanner) - print_pretty_json(task) - if task['status'] == 'New': - task = start_task(task) - if wait_for_task_completition(task,wait_timeout): - save_report(task,report_formats.txt, report_filename) - severities[host] = get_severity(task) - else: - severities[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)) diff --git a/jenkinsfile/Jenkinsfile b/jenkinsfile/Jenkinsfile index b0cfd57..64bb44e 100644 --- a/jenkinsfile/Jenkinsfile +++ b/jenkinsfile/Jenkinsfile @@ -13,6 +13,8 @@ pipeline { eval `oidc-agent-service use` oidc-add infn-cloud-ops + env + # Orchent connection test orchent depls > depls.output if cat depls.output | grep -q ERROR @@ -25,8 +27,7 @@ pipeline { fi # Greenbone connection test - export HOST_IP=`/sbin/ip route list scope link | grep -v " 172." | awk '{print $7}' | tr -d '\n'` - gvm-cli --gmp-username $GMP_USERNAME --gmp-password $GMP_PASSWD tls --hostname $HOST_IP --xml "<get_version/>" + /usr/local/bin/gvm-cli --gmp-username $GMP_USERNAME --gmp-password $GMP_PASSWD tls --hostname $HOST_IP --xml "<get_version/>" ''' } -- GitLab