Skip to content
Snippets Groups Projects
script.py 15.7 KiB
Newer Older
  • Learn to ignore specific revisions
  • qweqweasdasd's avatar
    qweqweasdasd committed
    #gvm-script --gmp-username backbone --gmp-password krowfodwas3olrab tls --hostname "172.17.0.2" script.py
    #auth_name = 'backbone'
    #auth_passwd = 'krowfodwas3olrab'
    
    
    qweqweasdasd's avatar
    qweqweasdasd committed
    from hashlib import new
    
    qweqweasdasd's avatar
    qweqweasdasd committed
    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
    from datetime import datetime
    import json
    import base64
    from sys import argv, exit
    
    def get_version():
    	with Gmp(connection, transform=transform) as gmp:
    		gmp.authenticate(auth_name, auth_passwd)	
    		pretty_print(gmp.get_version())
    
    
    qweqweasdasd's avatar
    qweqweasdasd committed
    ########## PORT LIST ##################################
    
    qweqweasdasd's avatar
    qweqweasdasd committed
    
    def create_port_list(port_list_name, ports):
        with Gmp(connection, transform=transform) as gmp:
            gmp.authenticate(auth_name, auth_passwd)
            res = gmp.create_port_list(port_list_name, ','.join(ports))
    
    qweqweasdasd's avatar
    qweqweasdasd committed
            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}
    
    qweqweasdasd's avatar
    qweqweasdasd committed
            else:
    
    qweqweasdasd's avatar
    qweqweasdasd committed
                msg = f"ERROR during Port list creation. Status code: {status}, msg: {status_text}"
                raise Exception(msg) 
    
    qweqweasdasd's avatar
    qweqweasdasd committed
    
    def get_port_lists(filter_str="rows=-1"):
    
    qweqweasdasd's avatar
    qweqweasdasd committed
        l_o = []
    
    qweqweasdasd's avatar
    qweqweasdasd committed
        with Gmp(connection, transform=transform) as gmp:
            gmp.authenticate(auth_name, auth_passwd)
    
    qweqweasdasd's avatar
    qweqweasdasd committed
            res = gmp.get_port_lists(filter_string=filter_str)
            for pl in res.xpath('port_list'):
    
    qweqweasdasd's avatar
    qweqweasdasd committed
                o = dict()
                o['name'] = pl.xpath('name/text()')[0]
                o['id'] = pl.xpath('@id')[0]
    
    qweqweasdasd's avatar
    qweqweasdasd committed
                o['in_use'] = pl.xpath('in_use/text()')[0]
                l_o.append(o)
        return l_o
    
    qweqweasdasd's avatar
    qweqweasdasd committed
    
    def delete_port_list(port_list):
        with Gmp(connection, transform=transform) as gmp:
            gmp.authenticate(auth_name, auth_passwd)
            res = gmp.delete_port_list(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}")
    
    
    qweqweasdasd's avatar
    qweqweasdasd committed
    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_id):
        o = dict()
        with Gmp(connection, transform=transform) as gmp:
            gmp.authenticate(auth_name, auth_passwd)
            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):
    
    qweqweasdasd's avatar
    qweqweasdasd committed
        res = []
        with Gmp(connection, transform=transform) as gmp:
            gmp.authenticate(auth_name, auth_passwd)
            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):
        with Gmp(connection, transform=transform) as gmp:
            gmp.authenticate(auth_name, auth_passwd)
            res = gmp.delete_target(target['id'])
            status = res.xpath('@status')[0]
            status_text = res.xpath('@status_text')[0]
    
    qweqweasdasd's avatar
    qweqweasdasd committed
            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_id):
        res = get_targets(target_name)
        if len(res) == 0:
            t = create_target(target_name,ip,port_list,ovs_ssh_credential_id)
            return get_targets(t['id'])[0]
        elif len(res) == 1:
            return res[0]
        else:
            print(f"Found {len(res)} results. Return None")
            return res
    
    qweqweasdasd's avatar
    qweqweasdasd committed
    
    def search_and_delete_target(target_name):
    
    qweqweasdasd's avatar
    qweqweasdasd committed
        targets = get_targets(target_name)
    
    qweqweasdasd's avatar
    qweqweasdasd committed
        if len(targets) == 1:
            delete_target(targets[0]['id'])
        else:
            raise("Multiple results for search")
    
    def search_and_delete_all_targets(target_name):
    
    qweqweasdasd's avatar
    qweqweasdasd committed
        targets = get_targets(target_name)
    
    qweqweasdasd's avatar
    qweqweasdasd committed
        for target in targets:
            delete_target(target)
    
    
    qweqweasdasd's avatar
    qweqweasdasd committed
    ############## TASK ##################################
    
    qweqweasdasd's avatar
    qweqweasdasd committed
    
    def create_task(name, config_id, target_id, scanner_id):
        o = dict()
        with Gmp(connection, transform=transform) as gmp:
            gmp.authenticate(auth_name, auth_passwd)
            res = gmp.create_task(
                    name=name,
                    config_id=config_id,
                    target_id=target_id,
                    scanner_id=scanner_id)
    
    qweqweasdasd's avatar
    qweqweasdasd committed
            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}
    
    qweqweasdasd's avatar
    qweqweasdasd committed
            else:
    
    qweqweasdasd's avatar
    qweqweasdasd committed
                msg = f"ERROR during Task creation. Status code: {status}, msg: {status_text}"
                raise Exception(msg)
    
    qweqweasdasd's avatar
    qweqweasdasd committed
    def get_tasks(filter_str):
    
    qweqweasdasd's avatar
    qweqweasdasd committed
        res = []
        with Gmp(connection, transform=transform) as gmp:
            gmp.authenticate(auth_name, auth_passwd)
            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]
    
    qweqweasdasd's avatar
    qweqweasdasd committed
                    try:
                        o['report_id'] = task.xpath('last_report/report/@id')[0]
                    except:
                        pass
    
    qweqweasdasd's avatar
    qweqweasdasd committed
                    res.append(o)
        return res
    
    
    qweqweasdasd's avatar
    qweqweasdasd committed
    def get_or_create_task(task_name, config_id, target_id, scanner_id):
        res = get_tasks(task_name)
        if len(res) == 0:
            t = create_task(task_name, config_id, target_id, scanner_id)
            return get_tasks(t['id'])[0]
        elif len(res) == 1:
            return res[0]
        else:
            print(f"Found {len(res)} results. Return None")
            return res
    
    
    qweqweasdasd's avatar
    qweqweasdasd committed
    def get_all_tasks():
        res = []
        with Gmp(connection, transform=transform) as gmp:
            gmp.authenticate(auth_name, auth_passwd)
            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]
    
    qweqweasdasd's avatar
    qweqweasdasd committed
                    try:
                        o['report_id'] = task.xpath('last_report/report/@id')[0]
                    except:
                        pass
    
    qweqweasdasd's avatar
    qweqweasdasd committed
                    res.append(o)
        return res
    
    def search_and_delete_all_tasks(filter_str):
    
    qweqweasdasd's avatar
    qweqweasdasd committed
        tasks = get_tasks(filter_str)
    
    qweqweasdasd's avatar
    qweqweasdasd committed
        for task in tasks:
            delete_task(task)
    
    def start_task(task):
        with Gmp(connection, transform=transform) as gmp:
            gmp.authenticate(auth_name, auth_passwd)
            res = gmp.start_task(task['id'])
    
    qweqweasdasd's avatar
    qweqweasdasd committed
            task['report_id'] = res.xpath('report_id/text()')[0]
        return task        
    
    qweqweasdasd's avatar
    qweqweasdasd committed
    
    def stop_task(task):
        with Gmp(connection, transform=transform) as gmp:
            gmp.authenticate(auth_name, auth_passwd)
            pretty_print(gmp.stop_task(task['id']))
    
    def delete_task(task):
        with Gmp(connection, transform=transform) as gmp:
            gmp.authenticate(auth_name, auth_passwd)
            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}")
    
    
    qweqweasdasd's avatar
    qweqweasdasd committed
    ############## REPORTS #####################################3
    
    
    qweqweasdasd's avatar
    qweqweasdasd committed
    def get_report_formats():
        # |------------- ID -----------------| |--- NAME ---|
        # 5057e5cc-b825-11e4-9d0e-28d24461215b Anonymous XML
        # c1645568-627a-11e3-a660-406186ea4fc5 CSV Results
        # 77bd6c4a-1f62-11e1-abf0-406186ea4fc5 ITG
        # c402cc3e-b531-11e1-9163-406186ea4fc5 PDF
        # a3810a62-1f62-11e1-9219-406186ea4fc5 TXT
        # a994b278-1f62-11e1-96ac-406186ea4fc5 XML
        with Gmp(connection, transform=transform) as gmp:
            gmp.authenticate(auth_name, auth_passwd)   
            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):
        with Gmp(connection, transform=transform) as gmp:
            gmp.authenticate(auth_name, auth_passwd)   
            res =  gmp.get_report_formats()
            pretty_print(res)  
    
    
    qweqweasdasd's avatar
    qweqweasdasd committed
    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
    
    qweqweasdasd's avatar
    qweqweasdasd committed
    
    
    qweqweasdasd's avatar
    qweqweasdasd committed
    def wait_for_task_completition(task, timeout=3600):
    
    qweqweasdasd's avatar
    qweqweasdasd committed
        start_time = time()
        while True:
    
    qweqweasdasd's avatar
    qweqweasdasd committed
            status, progress = get_progress(task)
            if status == "Done" and progress == -1:
                return True
            if time() - start_time > timeout:
    
    qweqweasdasd's avatar
    qweqweasdasd committed
                    print("TIMEOUT during waiting for task completition")
                    return False
    
    qweqweasdasd's avatar
    qweqweasdasd committed
            sleep(10)
    
    qweqweasdasd's avatar
    qweqweasdasd committed
    
    
    qweqweasdasd's avatar
    qweqweasdasd committed
    def save_report(task,report_format_id, report_filename ):
    
    qweqweasdasd's avatar
    qweqweasdasd committed
        with Gmp(connection, transform=transform) as gmp:
            gmp.authenticate(auth_name, auth_passwd)
    
    qweqweasdasd's avatar
    qweqweasdasd committed
            res = gmp.get_report(task['report_id'],
    
    qweqweasdasd's avatar
    qweqweasdasd committed
                                        report_format_id=report_format_id, 
                                        ignore_pagination=True,
                                        details="1")
            code = str(res.xpath('report/text()')[0])
    
    qweqweasdasd's avatar
    qweqweasdasd committed
            with open(report_filename, "wb") as fh:
    
    qweqweasdasd's avatar
    qweqweasdasd committed
                fh.write(base64.b64decode(code))
    
    
    qweqweasdasd's avatar
    qweqweasdasd committed
    def save_severity_report(task, severity_filename):
    
    qweqweasdasd's avatar
    qweqweasdasd committed
        dict_severity = {"Log": 0, "Low": 1, "Medium": 2, "High": 3}
        with Gmp(connection, transform=transform) as gmp:
            gmp.authenticate(auth_name, auth_passwd)
    
    qweqweasdasd's avatar
    qweqweasdasd committed
            res = gmp.get_report(task['report_id'],
    
    qweqweasdasd's avatar
    qweqweasdasd committed
                                report_format_id="5057e5cc-b825-11e4-9d0e-28d24461215b", 
                                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)
    
    
    qweqweasdasd's avatar
    qweqweasdasd committed
    def get_severity(task):
        dict_severity = {"Log": 0, "Low": 1, "Medium": 2, "High": 3}
        with Gmp(connection, transform=transform) as gmp:
            gmp.authenticate(auth_name, auth_passwd)
            res = gmp.get_report(task['report_id'],
                                report_format_id="5057e5cc-b825-11e4-9d0e-28d24461215b", 
                                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
                
    
    qweqweasdasd's avatar
    qweqweasdasd committed
    def get_reports(filter_str="rows=-1"):
        lo = []
        with Gmp(connection, transform=transform) as gmp:
            gmp.authenticate(auth_name, auth_passwd)
            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
    
    
    qweqweasdasd's avatar
    qweqweasdasd committed
    def print_pretty_json(j):
        print(json.dumps(j,sort_keys=True,indent=4))
    
    
    qweqweasdasd's avatar
    qweqweasdasd committed
    def process_global_severity(severities):
        dict_severity = {"Log": 0, "Low": 1, "Medium": 2, "High": 3}    
        global_sev = "Log"
        old_num_severity = 0
        for _,sev in severities.items():
            if dict_severity[sev] > old_num_severity:
                old_num_severity = dict_severity[sev]
                global_sev = sev
    
    qweqweasdasd's avatar
    qweqweasdasd committed
        severities['global_severity'] = global_sev
        if global_sev == "Log" or global_sev == "Low":
            severities['global'] = "OK"
        else:
            severities['global'] = "NOK"
    
    qweqweasdasd's avatar
    qweqweasdasd committed
        return severities
        
        
    
    qweqweasdasd's avatar
    qweqweasdasd committed
    ################ MAIN #######################################
    
    qweqweasdasd's avatar
    qweqweasdasd committed
    
    auth_name = "jenkins"
    auth_passwd = "bleyrauvHecsUbDy"
    logging.basicConfig(filename='debug.log', level=logging.DEBUG)
    connection = TLSConnection(hostname='172.17.0.2')
    transform = EtreeTransform()
    config_id = "9866edc1-8869-4e80-acac-d15d5647b4d9"
    scanner_id = "08b69003-5fc2-4037-a479-93b440211c73"
    ovs_ssh_credential_id = "a89d5ebf-01bf-4836-ae72-a65bc633219a"
    txt_report_format_id = "a3810a62-1f62-11e1-9219-406186ea4fc5"
    csv_report_format_id = "c1645568-627a-11e3-a660-406186ea4fc5"
    xml_report_format_id = "5057e5cc-b825-11e4-9d0e-28d24461215b"
    
    qweqweasdasd's avatar
    qweqweasdasd committed
    wait_timeout = 3600 #1h
    
    qweqweasdasd's avatar
    qweqweasdasd committed
    print("len_argv:",len(argv))
    for i in range(len(argv)):
        print(i,argv[i])
      
    
    endpoints = argv[1].split(',')
    dep_json = argv[2]
    
    qweqweasdasd's avatar
    qweqweasdasd committed
    output_dir = argv[3]
    
    #endpoins = "jupyter_notebook,grafana_endpoint"
    #dep_json = "/home/gmp/workspace/dep.json"
    #output_dir = "/home/gmp/workspace"
    
    qweqweasdasd's avatar
    qweqweasdasd committed
    
    
    qweqweasdasd's avatar
    qweqweasdasd committed
    print("endpoints", endpoints)
    
    print("dep_json", dep_json)
    
    qweqweasdasd's avatar
    qweqweasdasd committed
    print("output_dir", output_dir)
    
    qweqweasdasd's avatar
    qweqweasdasd committed
    
    with open(dep_json) as f:
        data = json.load(f)
    
    
    qweqweasdasd's avatar
    qweqweasdasd committed
    endpoints = dict()
    for key in data['outputs'].keys():
        if "endpoint" in key:
            endpoint = str(data['outputs'][key]).split("://")[1]
            print("endpoint",endpoint)
            host,port = endpoint.split(':')
            if host not in endpoints:
                endpoints[host] = ["22"]
            endpoints[host].append(port)
    
    qweqweasdasd's avatar
    qweqweasdasd committed
    print(json.dumps(endpoints,sort_keys=True,indent=4))      
    
    
    qweqweasdasd's avatar
    qweqweasdasd committed
    severities = dict()
    
    
    qweqweasdasd's avatar
    qweqweasdasd committed
    for host,ports in endpoints.items():
        print(host,ports)
    
    qweqweasdasd's avatar
    qweqweasdasd committed
      
        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"
    
    qweqweasdasd's avatar
    qweqweasdasd committed
        severity_filename = f"{output_dir}/severity.json"
    
    qweqweasdasd's avatar
    qweqweasdasd committed
    
        pl = get_or_create_port_list(port_list_name,ports)
        print_pretty_json(pl)
        target = get_or_create_target(target_name,host,pl,ovs_ssh_credential_id)
        print_pretty_json(target)
        task = get_or_create_task(task_name, config_id, target['id'],scanner_id)
        print_pretty_json(task)
        if task['status'] == 'New':
            task = start_task(task)
        if wait_for_task_completition(task,wait_timeout):
            save_report(task,txt_report_format_id, report_filename)
            severities[host] = get_severity(task)
    
        delete_task(task)
        delete_target(target)
        delete_port_list(pl)
    
    qweqweasdasd's avatar
    qweqweasdasd committed
    
    severities = process_global_severity(severities)
    with open(severity_filename, "w") as f:
        f.write(json.dumps(severities))