def main(workspace, server_address, user, password, output, email, email_password, mail_protocol, port_protocol, log, rules): signal.signal(signal.SIGINT, signal_handler) loglevel = log with open(rules, 'r') as rules_file: try: rules = json.loads(rules_file.read()) except Exception: print("Invalid rules file.") sys.exit(1) mail_notification = MailNotification( email, email_password, mail_protocol, port_protocol, ) for d in [output, 'log/']: if not os.path.isdir(d): os.makedirs(d) numeric_level = getattr(logging, loglevel.upper(), None) if not isinstance(numeric_level, int): raise ValueError('Invalid log level: %s' % loglevel) if not logger.handlers: logger.propagate = 0 logger.setLevel(numeric_level) fh = logging.FileHandler('log/searcher.log') fh.setLevel(numeric_level) # create console handler with a higher log level ch = logging.StreamHandler() ch.setLevel(numeric_level) # create formatter and add it to the handlers formatter = logging.Formatter( '%(asctime)s - %(name)s - %(levelname)s[%(pathname)s %(lineno)d ]: %(message)s', datefmt='%m/%d/%Y %I:%M:%S %p') fh.setFormatter(formatter) ch.setFormatter(formatter) logger.addHandler(fh) logger.addHandler(ch) try: logger.info('Started') logger.info('Searching objects into workspace %s ' % workspace) if not server_address.endswith('/'): server_address += '/' if not server_address.endswith('/_api'): server_address += '_api' api = Api(requests=requests, workspace=workspace, username=user, password=password, base=server_address) searcher = Searcher(api, mail_notification) searcher.process(rules) logger.info('Finished') except Exception as error: logger.exception(error)
class TestSearcherRules(): @pytest.mark.parametrize("api", [ lambda workspace, test_client, session: Api(workspace.name, test_client, session, username='******', password='******', base=''), lambda workspace, test_client, session: SqlApi(workspace.name, test_client, session), ]) @pytest.mark.usefixtures('ignore_nplusone') def test_searcher_update_rules(self, api, session, test_client): workspace = WorkspaceFactory.create() vuln = VulnerabilityFactory.create(workspace=workspace, severity='low') session.add(workspace) session.add(vuln) session.commit() assert vuln.severity == 'low' searcher = Searcher(api(workspace, test_client, session)) rules = [{ 'id': 'CHANGE_SEVERITY', 'model': 'Vulnerability', 'object': "severity=low", 'actions': ["--UPDATE:severity=med"] }] searcher.process(rules) vulns_count = session.query(Vulnerability).filter_by( workspace=workspace).count() assert vulns_count == 1 vuln = session.query(Vulnerability).filter_by( workspace=workspace).first() assert vuln.severity == 'medium' check_command(vuln, session) @pytest.mark.parametrize("api", [ lambda workspace, test_client, session: Api(workspace.name, test_client, session, username='******', password='******', base=''), lambda workspace, test_client, session: SqlApi(workspace.name, test_client, session), ]) @pytest.mark.usefixtures('ignore_nplusone') def test_searcher_delete_rules(self, api, session, test_client): workspace = WorkspaceFactory.create() vuln = VulnerabilityFactory.create(workspace=workspace, severity='low') session.add(workspace) session.add(vuln) session.commit() searcher = Searcher(api(workspace, test_client, session)) rules = [{ 'id': 'DELETE_LOW', 'model': 'Vulnerability', 'object': "severity=low", 'actions': ["--DELETE:"] }] searcher.process(rules) vulns_count = session.query(Vulnerability).filter_by( workspace=workspace).count() assert vulns_count == 0 @pytest.mark.parametrize("api", [ lambda workspace, test_client, session: Api(workspace.name, test_client, session, username='******', password='******', base=''), lambda workspace, test_client, session: SqlApi(workspace.name, test_client, session), ]) @pytest.mark.usefixtures('ignore_nplusone') @pytest.mark.skip("No available in community") def test_searcher_rules_tag_vulns_low(self, api, session, test_client): workspace = WorkspaceFactory.create() vuln = VulnerabilityFactory.create(workspace=workspace, severity='low') session.add(workspace) session.add(vuln) session.commit() searcher = Searcher(api(workspace, test_client, session)) rules = [{ 'id': 'DELETE_LOW', 'model': 'Vulnerability', 'object': "severity=low", 'actions': ["--UPDATE:tags=TEST"] }] searcher.process(rules) vulns_count = session.query(Vulnerability).filter_by( workspace=workspace).count() assert vulns_count == 1 vuln = session.query(Vulnerability).filter_by(workspace=workspace, id=vuln.id).first() assert list(vuln.tags) == ["TEST"] check_command(vuln, session) @pytest.mark.parametrize("api", [ lambda workspace, test_client, session: Api(workspace.name, test_client, session, username='******', password='******', base=''), lambda workspace, test_client, session: SqlApi(workspace.name, test_client, session), ]) @pytest.mark.usefixtures('ignore_nplusone') def test_confirm_vuln(self, api, session, test_client): workspace = WorkspaceFactory.create() vuln = VulnerabilityFactory.create(workspace=workspace, severity='low', confirmed=False) session.add(workspace) session.add(vuln) session.commit() assert vuln.confirmed is False searcher = Searcher(api(workspace, test_client, session)) rules = [{ 'id': 'CONFIRM_VULN', 'model': 'Vulnerability', 'object': "severity=low", 'actions': ["--UPDATE:confirmed=True"] }] searcher.process(rules) vulns_count = session.query(Vulnerability).filter_by( workspace=workspace).count() assert vulns_count == 1 vuln = session.query(Vulnerability).filter_by( workspace=workspace).first() assert vuln.confirmed is True @pytest.mark.parametrize("api", [ lambda workspace, test_client, session: Api(workspace.name, test_client, session, username='******', password='******', base=''), lambda workspace, test_client, session: SqlApi(workspace.name, test_client, session), ]) @pytest.mark.usefixtures('ignore_nplusone') def test_change_severity_webvuln(self, api, session, test_client): workspace = WorkspaceFactory.create() vuln = VulnerabilityWebFactory.create(workspace=workspace, severity='high') session.add(workspace) session.add(vuln) session.commit() assert vuln.severity == 'high' searcher = Searcher(api(workspace, test_client, session)) rules = [{ 'id': 'CONFIRM_VULN', 'model': 'Vulnerability', 'object': "severity=high", 'actions': ["--UPDATE:severity=informational"] }] searcher.process(rules) vulns_count = session.query(VulnerabilityWeb).filter_by( workspace=workspace).count() assert vulns_count == 1 vuln = session.query(VulnerabilityWeb).filter_by( workspace=workspace).first() assert vuln.severity == 'informational' @pytest.mark.parametrize("api", [ lambda workspace, test_client, session: Api(workspace.name, test_client, session, username='******', password='******', base=''), lambda workspace, test_client, session: SqlApi(workspace.name, test_client, session), ]) @pytest.mark.usefixtures('ignore_nplusone') def test_severity_info_med(self, api, session, test_client): workspace = WorkspaceFactory.create() vuln = VulnerabilityWebFactory.create(workspace=workspace, severity='medium') session.add(workspace) session.add(vuln) session.commit() assert vuln.severity == 'medium' searcher = Searcher(api(workspace, test_client, session)) rules = [{ 'id': 'CONFIRM_VULN', 'model': 'Vulnerability', 'object': "severity=med", 'actions': ["--UPDATE:severity=info"] }] searcher.process(rules) vulns_count = session.query(VulnerabilityWeb).filter_by( workspace=workspace).count() assert vulns_count == 1 vuln = session.query(VulnerabilityWeb).filter_by( workspace=workspace).first() assert vuln.severity == 'informational' @pytest.mark.parametrize("api", [ lambda workspace, test_client, session: Api(workspace.name, test_client, session, username='******', password='******', base=''), lambda workspace, test_client, session: SqlApi(workspace.name, test_client, session), ]) @pytest.mark.usefixtures('ignore_nplusone') def test_severity_info_med_2(self, api, session, test_client): workspace = WorkspaceFactory.create() vuln = VulnerabilityWebFactory.create(workspace=workspace, severity='informational') session.add(workspace) session.add(vuln) session.commit() assert vuln.severity == 'informational' searcher = Searcher(api(workspace, test_client, session)) rules = [{ 'id': 'CONFIRM_VULN', 'model': 'Vulnerability', 'object': "severity=info", 'actions': ["--UPDATE:severity=med"] }] searcher.process(rules) vulns_count = session.query(VulnerabilityWeb).filter_by( workspace=workspace).count() assert vulns_count == 1 vuln = session.query(VulnerabilityWeb).filter_by( workspace=workspace).first() assert vuln.severity == 'medium' @pytest.mark.parametrize("api", [ lambda workspace, test_client, session: Api(workspace.name, test_client, session, username='******', password='******', base=''), lambda workspace, test_client, session: SqlApi(workspace.name, test_client, session), ]) @pytest.mark.usefixtures('ignore_nplusone') def test_apply_template_by_id(self, api, session, test_client): workspace = WorkspaceFactory.create() template = VulnerabilityTemplateFactory.create() vuln = VulnerabilityFactory.create(workspace=workspace, severity='low', confirmed=False) session.add(workspace) session.add(vuln) session.add(template) session.commit() template_name = template.name template_id = template.id searcher = Searcher(api(workspace, test_client, session)) rules = [{ 'id': 'APPLY_TEMPLATE', 'model': 'Vulnerability', 'object': "severity=low", 'actions': [f"--UPDATE:template={template_id}"] }] searcher.process(rules) vulns_count = session.query(Vulnerability).filter_by( workspace=workspace).count() assert vulns_count == 1 vuln = session.query(Vulnerability).filter_by( workspace=workspace).first() assert vuln.name == template_name @pytest.mark.parametrize("api", [ lambda workspace, test_client, session: Api(workspace.name, test_client, session, username='******', password='******', base=''), lambda workspace, test_client, session: SqlApi(workspace.name, test_client, session), ]) @pytest.mark.usefixtures('ignore_nplusone') # TO FIX def test_remove_duplicated_by_name(self, api, session, test_client): workspace = WorkspaceFactory.create() host = HostFactory.create(workspace=workspace) vuln = VulnerabilityFactory.create(workspace=workspace, severity='low', name='Duplicated Vuln', host=host, service=None) duplicated_vuln = VulnerabilityFactory.create(workspace=workspace, severity='low', name='Duplicated Vuln 2', host=host, service=None) session.add(workspace) session.add(vuln) session.add(duplicated_vuln) session.add(host) session.commit() searcher = Searcher(api(workspace, test_client, session)) rules = [{ 'id': 'REMOVE_DUPLICATED_VULNS', 'model': 'Vulnerability', 'fields': ['name'], 'object': "severity=low --old", # Without --old param Searcher deletes all duplicated objects 'actions': ["--DELETE:"] }] vulns_count = session.query(Vulnerability).filter_by( workspace=workspace).count() assert vulns_count == 2 searcher.process(rules) vulns_count = session.query(Vulnerability).filter_by( workspace=workspace).count() assert vulns_count == 1 @pytest.mark.parametrize("api", [ lambda workspace, test_client, session: Api(workspace.name, test_client, session, username='******', password='******', base=''), lambda workspace, test_client, session: SqlApi(workspace.name, test_client, session), ]) @pytest.mark.usefixtures('ignore_nplusone') @pytest.mark.skip("No available in community") def test_mail_notification(self, api, session, test_client): workspace = WorkspaceFactory.create() vuln = VulnerabilityFactory.create(workspace=workspace, severity='low') session.add(workspace) session.add(vuln) session.commit() mail_notification = MailNotification(smtp_host='smtp.gmail.com', smtp_sender='*****@*****.**', smtp_password='******', smtp_port=587) _api = api(workspace, test_client, session) searcher = Searcher(_api, mail_notification=mail_notification) rules = [{ 'id': 'SEND_MAIL', 'model': 'Vulnerability', 'object': "severity=low", 'actions': ["--ALERT:[email protected]"] }] searcher.process(rules) assert searcher.mail_notification == mail_notification @pytest.mark.skip # TODO Fix the test and remove this @pytest.mark.parametrize("api", [ lambda workspace, test_client, session: Api(workspace.name, test_client, session, username='******', password='******', base=''), lambda workspace, test_client, session: SqlApi(workspace.name, test_client, session), ]) @pytest.mark.usefixtures('ignore_nplusone') def test_add_ref_to_duplicated_vuln(self, api, session, test_client): workspace = WorkspaceFactory.create() host = HostFactory.create(workspace=workspace) vuln = VulnerabilityFactory.create(workspace=workspace, severity='low', name='Duplicated Vuln', host=host, service=None) duplicated_vuln = VulnerabilityFactory.create(workspace=workspace, severity='low', name='Duplicated Vuln 2', host=host, service=None) session.add(workspace) session.add(vuln) session.add(duplicated_vuln) session.add(host) session.commit() first_vuln_id = vuln.id searcher = Searcher(api(workspace, test_client, session)) rules = [{ 'id': 'ADD_REFS_DUPLICATED_VULNS', 'model': 'Vulnerability', 'fields': ['name'], 'object': "severity=low --old", # Without --old param Searcher deletes all duplicated objects 'conditions': ['severity=low'], 'actions': ["--UPDATE:refs=REF_TEST"] }] vulns_count = session.query(Vulnerability).filter_by( workspace=workspace).count() assert vulns_count == 2 searcher.process(rules) vuln1 = session.query(Vulnerability).get(first_vuln_id) assert len(vuln1.references) > 0 assert list(vuln1.references)[0] == 'REF_TEST' @pytest.mark.parametrize("api", [ lambda workspace, test_client, session: Api(workspace.name, test_client, session, username='******', password='******', base=''), lambda workspace, test_client, session: SqlApi(workspace.name, test_client, session), ]) @pytest.mark.usefixtures('ignore_nplusone') def test_update_severity_inside_one_host(self, api, session, test_client): workspace = WorkspaceFactory.create() host = HostFactory.create(workspace=workspace) vuln1 = VulnerabilityFactory.create(workspace=workspace, severity='low', host=host, service=None) vuln2 = VulnerabilityFactory.create(workspace=workspace, severity='low', host=host, service=None) session.add(workspace) session.add(vuln1) session.add(vuln2) session.add(host) session.commit() parent_id = host.id first_vuln_id = vuln1.id second_vuln_id = vuln2.id assert vuln1.severity == 'low' assert vuln2.severity == 'low' assert vuln1.parent.id == parent_id assert vuln2.parent.id == parent_id searcher = Searcher(api(workspace, test_client, session)) rules = [{ 'id': 'CHANGE_SEVERITY_INSIDE_HOST', 'model': 'Vulnerability', 'parent': parent_id, 'object': "severity=low", # Without --old param Searcher deletes all duplicated objects 'conditions': ['severity=low'], 'actions': ["--UPDATE:severity=info"] }] searcher.process(rules) vuln1 = session.query(Vulnerability).get(first_vuln_id) vuln2 = session.query(Vulnerability).get(second_vuln_id) assert vuln1.severity == 'informational' assert vuln2.severity == 'informational' @pytest.mark.parametrize("api", [ lambda workspace, test_client, session: Api(workspace.name, test_client, session, username='******', password='******', base=''), lambda workspace, test_client, session: SqlApi(workspace.name, test_client, session), ]) @pytest.mark.usefixtures('ignore_nplusone') def test_update_severity_by_tool(self, api, session, test_client): workspace = WorkspaceFactory.create() host = HostFactory.create(workspace=workspace) vuln = VulnerabilityFactory.create(workspace=workspace, tool='Nessus', severity='low', host=host, service=None) session.add(workspace) session.add(vuln) session.add(host) session.commit() vuln_id = vuln.id assert vuln.severity == 'low' searcher = Searcher(api(workspace, test_client, session)) rules = [{ 'id': 'CHANGE_SEVERITY_INSIDE_HOST', 'model': 'Vulnerability', 'object': "tool=Nessus", # Without --old param Searcher deletes all duplicated objects 'conditions': ['tool=Nessus'], 'actions': ["--UPDATE:severity=info"] }] searcher.process(rules) vuln = session.query(Vulnerability).get(vuln_id) assert vuln.severity == 'informational' @pytest.mark.parametrize("api", [ lambda workspace, test_client, session: Api(workspace.name, test_client, session, username='******', password='******', base=''), lambda workspace, test_client, session: SqlApi(workspace.name, test_client, session), ]) @pytest.mark.usefixtures('ignore_nplusone') def test_update_severity_by_values_with_space(self, api, session, test_client): workspace = WorkspaceFactory.create() vuln = VulnerabilityFactory.create(workspace=workspace, tool='Nessus Tool', severity='low', service=None) session.add(workspace) session.add(vuln) session.commit() vuln_id = vuln.id assert vuln.severity == 'low' searcher = Searcher(api(workspace, test_client, session)) rules = [{ 'id': 'CHANGE_SEVERITY', 'model': 'Vulnerability', 'object': "tool=Nessus%Tool", # Without --old param Searcher deletes all duplicated objects 'conditions': ['severity=low'], 'actions': ["--UPDATE:severity=info"] }] searcher.process(rules) vuln = session.query(Vulnerability).get(vuln_id) assert vuln.severity == 'informational' @pytest.mark.parametrize("api", [ lambda workspace, test_client, session: Api(workspace.name, test_client, session, username='******', password='******', base=''), lambda workspace, test_client, session: SqlApi(workspace.name, test_client, session), ]) @pytest.mark.usefixtures('ignore_nplusone') def test_update_severity_by_values_with_space_2(self, api, session, test_client): workspace = WorkspaceFactory.create() vuln = VulnerabilityFactory.create(workspace=workspace, name='Cross-domain Referer leakage', severity='low', service=None) session.add(workspace) session.add(vuln) session.commit() vuln_id = vuln.id assert vuln.severity == 'low' searcher = Searcher(api(workspace, test_client, session)) rules = [{ 'id': 'CHANGE_SEVERITY', 'model': 'Vulnerability', 'object': "name=Cross-domain%Referer%leakage", # Without --old param Searcher deletes all duplicated objects 'conditions': ['name=Cross-domain%Referer%leakage'], 'actions': ["--UPDATE:severity=info"] }] searcher.process(rules) vuln = session.query(Vulnerability).get(vuln_id) assert vuln.severity == 'informational' @pytest.mark.parametrize("api", [ lambda workspace, test_client, session: Api(workspace.name, test_client, session, username='******', password='******', base=''), lambda workspace, test_client, session: SqlApi(workspace.name, test_client, session), ]) @pytest.mark.usefixtures('ignore_nplusone') def test_update_severity_by_creator(self, api, session, test_client): workspace = WorkspaceFactory.create() host = HostFactory.create(workspace=workspace) user = UserFactory.create() vuln = VulnerabilityFactory.create(workspace=workspace, tool='Nessus', severity='low', host=host, creator=user, service=None) session.add(workspace) session.add(vuln) session.add(host) session.commit() vuln_id = vuln.id assert vuln.severity == 'low' searcher = Searcher(api(workspace, test_client, session)) rules = [{ 'id': 'CHANGE_SEVERITY_INSIDE_HOST', 'model': 'Vulnerability', 'object': f'creator={user.username}', # Without --old param Searcher deletes all duplicated objects 'conditions': ['tool=Nessus'], 'actions': ["--UPDATE:severity=info"] }] searcher.process(rules) vuln = session.query(Vulnerability).get(vuln_id) assert vuln.severity == 'informational' @pytest.mark.skip( reason= "the following test generates a search on the field regex of vuln, which does not exists" ) @pytest.mark.parametrize("api", [ lambda workspace, test_client, session: Api(workspace.name, test_client, session, username='******', password='******', base=''), lambda workspace, test_client, session: SqlApi(workspace.name, test_client, session), ]) @pytest.mark.usefixtures('ignore_nplusone') @pytest.mark.skip_sql_dialect('sqlite') def test_delete_vulns_with_dynamic_values(self, api, session, test_client): workspace = WorkspaceFactory.create() vuln1 = VulnerabilityFactory.create(workspace=workspace, name="TEST1") vuln2 = VulnerabilityFactory.create(workspace=workspace, name="TEST2") session.add(workspace) session.add(vuln1) session.add(vuln2) session.commit() searcher = Searcher(api(workspace, test_client, session)) rules = [{ 'id': 'DELETE_VULN_{{name}}', 'model': 'Vulnerability', 'object': "regex=^{{name}}", 'actions': ["--DELETE:"], 'values': [{ 'name': 'TEST1' }, { 'name': 'TEST2' }] }] vulns_count = session.query(Vulnerability).filter_by( workspace=workspace).count() assert vulns_count == 2 searcher.process(rules) vulns_count = session.query(Vulnerability).filter_by( workspace=workspace).count() assert vulns_count == 0 @pytest.mark.parametrize("api", [ lambda workspace, test_client, session: Api(workspace.name, test_client, session, username='******', password='******', base=''), lambda workspace, test_client, session: SqlApi(workspace.name, test_client, session), ]) @pytest.mark.usefixtures('ignore_nplusone') @pytest.mark.skip_sql_dialect('sqlite') def test_update_custom_field(self, api, session, test_client): workspace = WorkspaceFactory.create() custom_field = CustomFieldsSchemaFactory.create( table_name='vulnerability', field_name='cfield', field_type='str', field_order=1, field_display_name='CField', ) vuln = VulnerabilityFactory.create(workspace=workspace, severity='low', confirmed=True) vuln.custom_fields = {'cfield': 'test'} session.add(workspace) session.add(custom_field) session.add(vuln) session.commit() assert vuln.confirmed is True searcher = Searcher(api(workspace, test_client, session)) rules = [{ 'id': 'CHANGE_CUSTOM_FIELD', 'model': 'Vulnerability', 'object': "severity=low", 'conditions': ['confirmed=True'], 'actions': ["--UPDATE:cfield=CUSTOM_FIELD_UPDATED"] }] searcher.process(rules) vulns_count = session.query(Vulnerability).filter_by( workspace=workspace).count() assert vulns_count == 1 vuln = session.query(Vulnerability).filter_by( workspace=workspace).first() assert vuln.custom_fields['cfield'] == 'CUSTOM_FIELD_UPDATED' check_command(vuln, session) @pytest.mark.parametrize("api", [ lambda workspace, test_client, session: Api(workspace.name, test_client, session, username='******', password='******', base=''), lambda workspace, test_client, session: SqlApi(workspace.name, test_client, session), ]) @pytest.mark.usefixtures('ignore_nplusone') def test_delete_services(self, api, session, test_client): workspace = WorkspaceFactory.create() service = ServiceFactory.create(workspace=workspace, name="http") session.add(workspace) session.add(service) session.commit() searcher = Searcher(api(workspace, test_client, session)) rules = [{ 'id': 'DELETE_SERVICE', 'model': 'Service', 'object': "name=http", 'actions': ["--DELETE:"] }] service_count = session.query(Service).filter_by( workspace=workspace).count() assert service_count == 1 searcher.process(rules) service_count = session.query(Service).filter_by( workspace=workspace).count() assert service_count == 0 @pytest.mark.parametrize("api", [ lambda workspace, test_client, session: Api(workspace.name, test_client, session, username='******', password='******', base=''), lambda workspace, test_client, session: SqlApi(workspace.name, test_client, session), ]) @pytest.mark.usefixtures('ignore_nplusone') def test_delete_host(self, api, session, test_client): workspace = WorkspaceFactory.create() host = HostFactory.create(workspace=workspace, ip="10.25.86.39") session.add(workspace) session.add(host) session.commit() searcher = Searcher(api(workspace, test_client, session)) rules = [{ 'id': 'DELETE_HOST', 'model': 'Host', 'object': "ip=10.25.86.39", 'actions': ["--DELETE:"] }] host_count = session.query(Host).filter_by(workspace=workspace).count() assert host_count == 1 searcher.process(rules) host_count = session.query(Host).filter_by(workspace=workspace).count() assert host_count == 0 @pytest.mark.parametrize("api", [ lambda workspace, test_client, session: Api(workspace.name, test_client, session, username='******', password='******', base=''), lambda workspace, test_client, session: SqlApi(workspace.name, test_client, session), ]) @pytest.mark.usefixtures('ignore_nplusone') def test_update_services(self, api, session, test_client): workspace = WorkspaceFactory.create() service = ServiceFactory.create(workspace=workspace, name="http", owned=False) session.add(workspace) session.add(service) session.commit() assert service.owned is False searcher = Searcher(api(workspace, test_client, session)) rules = [{ 'id': 'UPDATE_SERVICE', 'model': 'Service', 'object': "name=http", 'actions': ["--UPDATE:owned=True"] }] searcher.process(rules) service = session.query(Service).filter_by(workspace=workspace).first() assert service.owned is True @pytest.mark.parametrize("api", [ lambda workspace, test_client, session: Api(workspace.name, test_client, session, username='******', password='******', base=''), lambda workspace, test_client, session: SqlApi(workspace.name, test_client, session), ]) @pytest.mark.usefixtures('ignore_nplusone') def test_update_host(self, api, session, test_client): workspace = WorkspaceFactory.create() host = HostFactory.create(workspace=workspace, ip="10.25.86.39", owned=False) session.add(workspace) session.add(host) session.commit() assert host.owned is False searcher = Searcher(api(workspace, test_client, session)) rules = [{ 'id': 'UPDATE_HOST', 'model': 'Host', 'object': "ip=10.25.86.39", 'actions': ["--UPDATE:owned=True"] }] searcher.process(rules) host = session.query(Host).filter_by(workspace=workspace).first() assert host.owned is True @pytest.mark.parametrize("api", [ lambda workspace, test_client, session: Api(workspace.name, test_client, session, username='******', password='******', base=''), lambda workspace, test_client, session: SqlApi(workspace.name, test_client, session), ]) @pytest.mark.usefixtures('ignore_nplusone') def test_update_host_with_all_fields(self, api, session, test_client): workspace = WorkspaceFactory.create() host = HostFactory.create(workspace=workspace, os='Unix', ip="10.25.86.39", owned=False, description='HDesc', mac='MAC') session.add(workspace) session.add(host) session.commit() assert host.owned is False assert host.os == 'Unix' assert host.ip == "10.25.86.39" assert host.description == 'HDesc' assert host.mac == 'MAC' searcher = Searcher(api(workspace, test_client, session)) rules = [{ 'id': 'UPDATE_HOST', 'model': 'Host', 'object': "ip=10.25.86.39 owned=False os=Unix", 'actions': ["--UPDATE:description=HDescUp", "--UPDATE:mac=MAC2"] }] searcher.process(rules) host = session.query(Host).filter_by(workspace=workspace).first() assert host.description == 'HDescUp' assert host.mac == 'MAC2' @pytest.mark.parametrize("api", [ lambda workspace, test_client, session: Api(workspace.name, test_client, session, username='******', password='******', base=''), lambda workspace, test_client, session: SqlApi(workspace.name, test_client, session), ]) @pytest.mark.usefixtures('ignore_nplusone') def test_update_host_with_all_fields_2(self, api, session, test_client): workspace = WorkspaceFactory.create() host = HostFactory.create(workspace=workspace, os='Unix', ip="10.25.86.39", owned=False, description='HDesc', mac='MAC') session.add(workspace) session.add(host) session.commit() assert host.owned is False assert host.os == 'Unix' assert host.ip == "10.25.86.39" assert host.description == 'HDesc' assert host.mac == 'MAC' searcher = Searcher(api(workspace, test_client, session)) rules = [{ 'id': 'UPDATE_HOST', 'model': 'Host', 'object': "description=HDesc mac=MAC", 'actions': [ "--UPDATE:ip=10.25.50.47", "--UPDATE:owned=True", "--UPDATE:os=Windows" ] }] searcher.process(rules) host = session.query(Host).filter_by(workspace=workspace).first() assert host.ip == '10.25.50.47' assert host.os == 'Windows' assert host.owned is True @pytest.mark.parametrize("api", [ lambda workspace, test_client, session: Api(workspace.name, test_client, session, username='******', password='******', base=''), lambda workspace, test_client, session: SqlApi(workspace.name, test_client, session), ]) @pytest.mark.usefixtures('ignore_nplusone') def test_disable_rule(self, api, session, test_client, vulnerability_factory): workspace = WorkspaceFactory.create() vulns = vulnerability_factory.create_batch(5, workspace=workspace, severity='low') vulns2 = vulnerability_factory.create_batch(5, workspace=workspace, severity='medium') session.add(workspace) session.add_all(vulns) session.add_all(vulns2) session.commit() vulns_count = session.query(Vulnerability).filter_by( workspace=workspace).count() assert vulns_count == 10 searcher = Searcher(api(workspace, test_client, session)) rule_disabled: Rule = RuleFactory.create(disabled=True, workspace=workspace) rule_enabled = RuleFactory.create(disabled=False, workspace=workspace) with session.no_autoflush: rule_disabled.conditions = [ ConditionFactory.create(field='severity', value="low") ] rule_enabled.conditions = [ ConditionFactory.create(field='severity', value="medium") ] action = ActionFactory.create(command='DELETE') session.add(action) session.add(rule_disabled) session.add(rule_enabled) rules = [rule_disabled, rule_enabled] for rule in rules: rule_action = RuleActionFactory.create(action=action, rule=rule) session.add(rule_action) session.commit() rules_data = [] for rule in rules: rule_data = WorkerRuleSchema().dumps(rule) rules_data.append(json.loads(rule_data)) searcher.process(rules_data) vulns_count = session.query(Vulnerability).filter_by( workspace=workspace).count() assert vulns_count == 5