Example #1
0
 def test_find_by_name(self, m_Tag, m_File):
     m_session = MagicMock()
     name = "something"
     tag = MagicMock()
     tag.id = randint(0, 10)
     tags = [tag.id]
     FileExt.query_find_by_name(name, tags, m_session)
     m_session.query.called_with(m_Tag)
     m_session.query().filter_by.assert_called_once_with(id=tag.id)
     m_session.query().filter_by().one.assert_called_once()
Example #2
0
 def test_find_by_hash(self, m_Tag, m_File):
     m_session = MagicMock()
     hash_type, hash = "something", "anotherthing"
     tag = MagicMock()
     tag.id = randint(0, 10)
     tags = [tag.id]
     FileExt.query_find_by_hash(hash_type, hash, tags, m_session)
     m_session.query.called_with(FileExt)
     m_session.query().filter_by.assert_called_once_with(id=tag.id)
     m_session.query().filter_by().one.assert_called_once()
Example #3
0
def set_result(file_ext_id, probe, result):
    with session_transaction() as session:
        file_ext = FileExt.load_from_ext_id(file_ext_id, session=session)
        sanitized_res = _sanitize_res(result)
        file_ext.set_result(probe, sanitized_res)
        scan_id = file_ext.scan.external_id
        log.info("scan %s: file %s result from %s",
                 scan_id, file_ext_id, probe)
    is_finished(scan_id)
Example #4
0
def handle_output_files(file_ext_id, result, error_case=False):
    log.info("Handling output for file %s", file_ext_id)
    with session_transaction() as session:
        file_ext = FileExt.load_from_ext_id(file_ext_id, session)
        scan = file_ext.scan
        uploaded_files = result.get('uploaded_files', None)
        log.debug("scan %s file %s depth %s", scan.external_id,
                  file_ext_id, file_ext.depth)
        if uploaded_files is None:
            return
        resubmit = scan.resubmit_files
        max_resubmit_level = get_max_resubmit_level()
        if max_resubmit_level != 0 and file_ext.depth > \
                max_resubmit_level:
            log.warning("scan %s file %s resubmit level %s exceeded max "
                        "level (%s)", scan.external_id,
                        file_ext_id, file_ext.depth,
                        max_resubmit_level
                        )
            resubmit = False
        if not resubmit or error_case:
            reason = "Error case" if error_case else "Resubmit disabled"
            log.debug("scan %s: %s flushing files", scan.external_id, reason)
            celery_brain.files_flush(list(uploaded_files.values()),
                                     scan.external_id)
            return
        log.debug("scan %s: found files %s", scan.external_id, uploaded_files)
        # Retrieve the DB probe_result to link it with
        # a new FileProbeResult in _append_new_files
        probe_result = file_ext.fetch_probe_result(result['name'])
        new_fws = _append_new_files_to_scan(scan, uploaded_files,
                                            probe_result, file_ext.depth+1)
        parent_file = file_ext.file
        for new_fw in new_fws:
            parent_file.children.append(new_fw)
        session.commit()
        log.debug("scan %s: %d new files to resubmit",
                  scan.external_id, len(new_fws))

        scan_request = _create_scan_request(new_fws,
                                            scan.get_probelist(),
                                            scan.mimetype_filtering)
        scan_request = _add_empty_results(new_fws, scan_request, scan, session)
        if scan_request.nb_files == 0:
            scan.set_status(IrmaScanStatus.finished)
            log.info("scan %s: nothing to do flushing files",
                     scan.external_id)
            celery_brain.files_flush(list(uploaded_files.values()),
                                     scan.external_id)
            return
        for new_fw in new_fws:
            celery_brain.scan_launch(new_fw.external_id,
                                     new_fw.probes,
                                     scan.external_id)
    return
Example #5
0
def scan_launch_file_ext(file_ext_id):
    file_ext = None
    with session_transaction() as session:
        try:
            file_ext = FileExt.load_from_ext_id(file_ext_id, session)
            scan_id = file_ext.scan.external_id
            log.debug("scan %s: launch scan for file_ext: %s",
                      scan_id, file_ext_id)
            ftp_ctrl.upload_file(file_ext_id, file_ext.file.path)
            # launch new celery scan task on brain
            celery_brain.scan_launch(file_ext_id, file_ext.probes, scan_id)
        except IrmaFtpError as e:
            log.error("file_ext %s: ftp upload error %s", file_ext_id, str(e))
            if file_ext is not None:
                file_ext.scan.set_status(IrmaScanStatus.error_ftp_upload)
        except Exception as e:
            log.exception(e)
Example #6
0
def quick_scan(request):
    """ Launch a scan for one file
    """
    session = db.session
    ip = request.remote_addr

    # Create file
    fe = files_ctrl.create(request)
    fe = FileExt.load_from_ext_id(fe['result_id'], session)

    # Create a scan
    scan = Scan(compat.timestamp(), ip, files_ext=[fe, ])
    session.add(scan)
    session.commit()

    # launch_asynchronous scan via frontend task
    celery_frontend.scan_launch(str(scan.external_id))

    return scan_schema.dump(scan).data
Example #7
0
    def test_get_ok(self, m_FileExt):
        api_version = 1
        resultid = "whatever"
        m_file = MagicMock()
        m_fw = FileExt(m_file, "filename")
        m_FileExt.load_from_ext_id.return_value = m_fw

        # As FileExt.other_results value is normally retrieve from database,
        # when requesting it, the API will not return it, and will break the
        # test.
        # A solution is to patch the property as mentionned in the
        # documentation:
        # (https://docs.python.org/3/library/unittest.mock.html#unittest.mock.PropertyMock)
        # Mocking the type object other_results property will break other tests
        # (the database one) as it will globally mocking it.
        with patch('api.files_ext.models.FileExt.other_results',
                   new_callable=PropertyMock) as m_other_results:
            m_other_results.return_value = [m_fw]
            result = api_files_ext.get(api_version, resultid)

        m_FileExt.load_from_ext_id.assert_called_once_with(resultid,
                                                           self.session)
        self.assertIsFileExt(result)
Example #8
0
 def test_load_from_ext_id_raises_multiple(self):
     m_session = MagicMock()
     ext_id = "whatever"
     m_session.query().filter().one.side_effect = MultipleResultsFound()
     with self.assertRaises(IrmaDatabaseError):
         FileExt.load_from_ext_id(ext_id, m_session)
Example #9
0
 def test_load_from_ext_id_raises_noresult(self):
     m_session = MagicMock()
     ext_id = "whatever"
     m_session.query().filter().one.side_effect = NoResultFound()
     with self.assertRaises(IrmaDatabaseResultNotFound):
         FileExt.load_from_ext_id(ext_id, m_session)
Example #10
0
 def test_load_from_ext_id(self):
     m_session = MagicMock()
     ext_id = "whatever"
     FileExt.load_from_ext_id(ext_id, m_session)
     m_filter = m_session.query(FileExt).filter
     m_filter.is_called_once_with(FileExt.external_id == ext_id)
Example #11
0
 def test_from_fobj(self):
     filename = "file"
     m_file = MagicMock()
     fw = FileExt(m_file, filename)
     self.assertIs(type(fw), FileExt)
     self.assertEqual(fw.name, "file")
Example #12
0
 def setUp(self):
     self.file = MagicMock()
     self.name = "name"
     self.scan = MagicMock()
     self.fw = FileExt(self.file, self.name)
Example #13
0
class TestFileExt(TestCase):

    def setUp(self):
        self.file = MagicMock()
        self.name = "name"
        self.scan = MagicMock()
        self.fw = FileExt(self.file, self.name)

    def tearDown(self):
        del self.fw

    def test_load_from_ext_id(self):
        m_session = MagicMock()
        ext_id = "whatever"
        FileExt.load_from_ext_id(ext_id, m_session)
        m_filter = m_session.query(FileExt).filter
        m_filter.is_called_once_with(FileExt.external_id == ext_id)

    def test_load_from_ext_id_raises(self):
        m_session = MagicMock()
        ext_id = "whatever"
        m_session.query.side_effect = NoResultFound()
        with self.assertRaises(IrmaDatabaseResultNotFound):
            FileExt.load_from_ext_id(ext_id, m_session)

    def test_load_from_ext_id_raises(self):
        m_session = MagicMock()
        ext_id = "whatever"
        m_session.query.side_effect = MultipleResultsFound()
        with self.assertRaises(IrmaDatabaseError):
            FileExt.load_from_ext_id(ext_id, m_session)

    @patch("api.files_ext.models.File")
    @patch("api.files_ext.models.Tag")
    def test_find_by_name(self, m_Tag, m_File):
        m_session = MagicMock()
        name = "something"
        tag = MagicMock()
        tag.id = randint(0, 10)
        tags = [tag.id]
        FileExt.query_find_by_name(name, tags, m_session)
        m_Tag.find_by_id.assert_called_once_with(tag.id, m_session)

    @patch("api.files_ext.models.File")
    @patch("api.files_ext.models.Tag")
    def test_find_by_hash(self, m_Tag, m_File):
        m_session = MagicMock()
        hash_type, hash = "something", "anotherthing"
        tag = MagicMock()
        tag.id = randint(0, 10)
        tags = [tag.id]
        FileExt.query_find_by_hash(hash_type, hash, tags, m_session)
        m_session.query.called_with(FileExt)
        m_Tag.find_by_id.assert_called_once_with(tag.id, m_session)

    @patch("api.files_ext.models.File")
    @patch("api.files_ext.models.Tag")
    def test_find_by_hash_distinct_false(self, m_Tag, m_File):
        m_session = MagicMock()
        hash_type, hash = "something", "anotherthing"
        tag = MagicMock()
        tag.id = randint(0, 10)
        tags = [tag.id]
        FileExt.query_find_by_hash(hash_type, hash, tags, m_session,
                                   distinct_name=False)
        m_session.query.called_with(FileExt)
        m_Tag.find_by_id.assert_called_once_with(tag.id, m_session)

    def test_probes_finished(self):
        pr1, pr2 = MagicMock(), MagicMock()
        pr1.doc = None
        pr2.doc = "whatever"
        self.fw.probe_results = [pr1, pr2]
        self.assertEqual(self.fw.probes_finished, 1)

    def test_probes_finished_all_none(self):
        pr1, pr2 = MagicMock(), MagicMock()
        pr1.doc = None
        pr2.doc = None
        self.fw.probe_results = [pr1, pr2]
        self.assertEqual(self.fw.probes_finished, 0)

    def test_status_0(self):
        pr1, pr2 = MagicMock(), MagicMock()
        pr1.doc = {'type': IrmaProbeType.antivirus, 'status': 0}
        pr2.doc = {'type': IrmaProbeType.antivirus, 'status': 0}
        self.fw.probe_results = [pr1, pr2]
        self.assertEqual(self.fw.status, 0)

    def test_status_1(self):
        pr1, pr2 = MagicMock(), MagicMock()
        pr1.doc = {'type': IrmaProbeType.antivirus, 'status': 0}
        pr2.doc = {'type': IrmaProbeType.antivirus, 'status': 1}
        self.fw.probe_results = [pr1, pr2]
        self.assertEqual(self.fw.status, 1)

    def test_get_probe_results_as_list(self):
        pr1, pr2 = MagicMock(), MagicMock()
        pr1.doc = "whatever"
        pr2.doc = "something"
        self.fw.probe_results = [pr1, pr2]
        self.assertCountEqual(self.fw.get_probe_results(results_as="list"),
                              [pr1.get_details(True),
                               pr2.get_details(True)])
        pr1.get_details.assert_called_with(True)
        pr2.get_details.assert_called_with(True)

    def test_get_probe_results_as_dict(self):
        pr1, pr2 = MagicMock(), MagicMock()
        pr1.doc = "whatever"
        pr2.doc = "something"
        self.fw.probe_results = [pr1, pr2]
        self.assertIsInstance(self.fw.get_probe_results(results_as="dict"),
                              dict)
        pr1.get_details.assert_called_with(True)
        pr2.get_details.assert_called_with(True)

    def test_fetch_probe_results(self):
        m_pr = MagicMock()
        probename = "probe1"
        m_pr.name = probename
        self.fw.probe_results = [m_pr]
        res = self.fw.fetch_probe_result(probename)
        self.assertEqual(res, m_pr)

    def test_fetch_probe_results_none(self):
        m_pr = MagicMock()
        probename = "probe1"
        m_pr.name = probename
        self.fw.probe_results = []
        with self.assertRaises(IrmaDatabaseError):
            self.fw.fetch_probe_result(probename)

    def test_fetch_probe_results_multiple_results(self):
        m_pr = MagicMock()
        probename = "probe1"
        m_pr.name = probename
        self.fw.probe_results = [m_pr, m_pr]
        with self.assertRaises(IrmaDatabaseError):
            self.fw.fetch_probe_result(probename)

    def test_from_fobj(self):
        filename = "file"
        m_file = MagicMock()
        fw = FileExt(m_file, filename)
        self.assertIs(type(fw), FileExt)
        self.assertEqual(fw.name, "file")

    def test_set_result(self):
        m_pr = MagicMock()
        m_pr.name = "probename"
        self.fw.probe_results = [m_pr]
        probe = "probename"
        result = {'status': 1, 'type': "something"}
        self.fw.file = MagicMock()
        self.fw.set_result(probe, result)

    def test_probes_empty(self):
        self.fw.probe_results = []
        self.assertEqual(self.fw.probes, [])

    def test_probes_not_empty(self):
        m_pr1, m_pr2 = MagicMock(), MagicMock()
        probename1, probename2 = "probename1", "probename2"
        m_pr1.name = probename1
        m_pr2.name = probename2
        self.fw.probe_results = [m_pr1, m_pr2]
        self.assertCountEqual(self.fw.probes, ["probename1", "probename2"])
Example #14
0
 def test_load_from_ext_id_raises_multiple(self):
     m_session = MagicMock()
     ext_id = "whatever"
     m_session.query().filter().one.side_effect = MultipleResultsFound()
     with self.assertRaises(IrmaDatabaseError):
         FileExt.load_from_ext_id(ext_id, m_session)
Example #15
0
 def test_load_from_ext_id_raises_noresult(self):
     m_session = MagicMock()
     ext_id = "whatever"
     m_session.query().filter().one.side_effect = NoResultFound()
     with self.assertRaises(IrmaDatabaseResultNotFound):
         FileExt.load_from_ext_id(ext_id, m_session)
Example #16
0
 def test_load_from_ext_id(self):
     m_session = MagicMock()
     ext_id = "whatever"
     FileExt.load_from_ext_id(ext_id, m_session)
     m_filter = m_session.query(FileExt).filter
     m_filter.is_called_once_with(FileExt.external_id == ext_id)
Example #17
0
def launch_v2(request, body):
    """ Launch a scan.
        The request should be performed using a POST request method.
        The input json format is the following:
        {
            files: [fileext1, fileext2...]
            options:
               probes: list of probes or None for all available,
               force: boolean (default False),
               mimetype_filtering: boolean (default True),
               resubmit_files: boolean (default True),
        }
    """
    scan_params = body
    if not scan_params:
        raise HTTPInvalidParam("Missing json parameters", "body")
    files_list = body.get('files', None)

    if files_list is None or len(files_list) == 0:
        raise HTTPInvalidParam("Missing values", "files")

    # Set default values
    force = True
    mimetype_filtering = True
    resubmit_files = True
    probes = None
    # override with given values if set
    scan_options = body.get("options", None)
    if scan_options is not None:
        force = scan_options.get("force", force)
        if type(force) is not bool:
            raise HTTPInvalidParam("Should be boolean", "force")
        mimetype_filtering = scan_options.get("mimetype_filtering",
                                              mimetype_filtering)
        if type(mimetype_filtering) is not bool:
            raise HTTPInvalidParam("Should be boolean",
                                   "mimetype_filtering")
        resubmit_files = scan_options.get("resubmit_files", resubmit_files)
        if type(resubmit_files) is not bool:
            raise HTTPInvalidParam("Should be boolean",
                                   "resubmit_files")
        probes = scan_options.get("probes", probes)

    session = db.session
    ip = request.remote_addr

    files_ext = []
    for fe_id in files_list:
        try:
            file_ext = FileExt.load_from_ext_id(fe_id, session)
        except IrmaDatabaseResultNotFound:
            raise HTTPInvalidParam("File %s not found" % fe_id,
                                   "files")
        if file_ext.file.path is None:
            raise HTTPInvalidParam("File with hash %s should be ("
                                   "re)uploaded" %
                                   file_ext.file.sha256,
                                   "files")
        if file_ext.scan is not None:
            raise HTTPInvalidParam("File %s already scanned" %
                                   fe_id,
                                   "files")
        files_ext.append(file_ext)

    scan = Scan(compat.timestamp(), ip,
                force=force, mimetype_filtering=mimetype_filtering,
                resubmit_files=resubmit_files, files_ext=files_ext,
                probes=probes)
    session.add(scan)
    session.commit()
    # launch_asynchronous scan via frontend task
    celery_frontend.scan_launch(str(scan.external_id))

    return scan_schema.dump(scan).data
Example #18
0
def launch_v2(request, body):
    """ Launch a scan.
        The request should be performed using a POST request method.
        The input json format is the following:
        {
            files: [fileext1, fileext2...]
            options:
               probes: list of probes or None for all available,
               force: boolean (default False),
               mimetype_filtering: boolean (default True),
               resubmit_files: boolean (default True),
        }
    """
    scan_params = body
    if not scan_params:
        raise HTTPInvalidParam("Missing json parameters", "body")
    files_list = body.get('files', None)

    if files_list is None or len(files_list) == 0:
        raise HTTPInvalidParam("Missing values", "files")

    # Set default values
    force = True
    mimetype_filtering = True
    resubmit_files = True
    probes = None
    # override with given values if set
    scan_options = body.get("options", None)
    if scan_options is not None:
        force = scan_options.get("force", False)
        if type(force) is not bool:
            raise HTTPInvalidParam("Should be boolean", "force")
        mimetype_filtering = scan_options.get("mimetype_filtering", True)
        if type(mimetype_filtering) is not bool:
            raise HTTPInvalidParam("Should be boolean", "mimetype_filtering")
        resubmit_files = scan_options.get("resubmit_files", True)
        if type(resubmit_files) is not bool:
            raise HTTPInvalidParam("Should be boolean", "resubmit_files")
        probes = scan_options.get("probes", None)

    session = db.session
    ip = request.remote_addr
    scan = Scan(compat.timestamp(), ip)
    session.add(scan)

    # handle scan parameter
    # cached results: "force" (default: True)
    scan.force = force

    # use mimetype for probelist: "mimetype_filtering" (default: True)
    scan.mimetype_filtering = mimetype_filtering

    # rescan file outputted from probes "resubmit_files" (default: True)
    scan.resubmit_files = resubmit_files

    scan.set_status(IrmaScanStatus.empty)
    session.commit()

    log.debug("scan %s: created", scan.external_id)

    msg = "scan %s: Force %s MimeF %s"
    msg += " Resub %s Probes %s"
    log.debug(msg, scan.external_id, scan.force, scan.mimetype_filtering,
              scan.resubmit_files, probes)

    for fe_id in files_list:
        log.info("scan %s adding file %s", scan.external_id, fe_id)
        try:
            file_ext = FileExt.load_from_ext_id(fe_id, session)
        except IrmaDatabaseResultNotFound:
            raise HTTPInvalidParam("File %s not found" % fe_id, "files")

        if file_ext.file.path is None:
            raise HTTPInvalidParam(
                "File with hash %s should be ("
                "re)uploaded" % file_ext.file.sha256, "files")

        if file_ext.scan is not None:
            raise HTTPInvalidParam("File %s already scanned" % fe_id, "files")
        file_ext.scan = scan

    scan.set_status(IrmaScanStatus.ready)
    session.commit()

    probelist = probe_ctrl.check_probe(probes)
    scan.set_probelist(probelist)
    session.commit()
    # launch_asynchronous scan via frontend task
    celery_frontend.scan_launch(str(scan.external_id))

    return scan_schema.dump(scan).data
Example #19
0
class TestFileExt(TestCase):
    def setUp(self):
        self.file = MagicMock()
        self.name = "name"
        self.scan = MagicMock()
        self.fw = FileExt(self.file, self.name)

    def tearDown(self):
        del self.fw

    def test_load_from_ext_id(self):
        m_session = MagicMock()
        ext_id = "whatever"
        FileExt.load_from_ext_id(ext_id, m_session)
        m_filter = m_session.query(FileExt).filter
        m_filter.is_called_once_with(FileExt.external_id == ext_id)

    def test_load_from_ext_id_raises_noresult(self):
        m_session = MagicMock()
        ext_id = "whatever"
        m_session.query().filter().one.side_effect = NoResultFound()
        with self.assertRaises(IrmaDatabaseResultNotFound):
            FileExt.load_from_ext_id(ext_id, m_session)

    def test_load_from_ext_id_raises_multiple(self):
        m_session = MagicMock()
        ext_id = "whatever"
        m_session.query().filter().one.side_effect = MultipleResultsFound()
        with self.assertRaises(IrmaDatabaseError):
            FileExt.load_from_ext_id(ext_id, m_session)

    @patch("api.files_ext.models.File")
    @patch("api.files_ext.models.Tag")
    def test_find_by_name(self, m_Tag, m_File):
        m_session = MagicMock()
        name = "something"
        tag = MagicMock()
        tag.id = randint(0, 10)
        tags = [tag.id]
        FileExt.query_find_by_name(name, tags, m_session)
        m_session.query.called_with(m_Tag)
        m_session.query().filter_by.assert_called_once_with(id=tag.id)
        m_session.query().filter_by().one.assert_called_once()

    @patch("api.files_ext.models.File")
    @patch("api.files_ext.models.Tag")
    def test_find_by_hash(self, m_Tag, m_File):
        m_session = MagicMock()
        hash_type, hash = "something", "anotherthing"
        tag = MagicMock()
        tag.id = randint(0, 10)
        tags = [tag.id]
        FileExt.query_find_by_hash(hash_type, hash, tags, m_session)
        m_session.query.called_with(FileExt)
        m_session.query().filter_by.assert_called_once_with(id=tag.id)
        m_session.query().filter_by().one.assert_called_once()

    @patch("api.files_ext.models.File")
    @patch("api.files_ext.models.Tag")
    def test_find_by_hash_distinct_false(self, m_Tag, m_File):
        m_session = MagicMock()
        hash_type, hash = "something", "anotherthing"
        tag = MagicMock()
        tag.id = randint(0, 10)
        tags = [tag.id]
        FileExt.query_find_by_hash(hash_type,
                                   hash,
                                   tags,
                                   m_session,
                                   distinct_name=False)
        m_session.query.called_with(FileExt)
        m_session.query().filter_by.assert_called_once_with(id=tag.id)
        m_session.query().filter_by().one.assert_called_once()

    def test_probes_finished(self):
        pr1, pr2 = MagicMock(), MagicMock()
        pr1.status = None
        pr2.status = 1
        self.fw.probe_results = [pr1, pr2]
        self.assertEqual(self.fw.probes_finished, 1)

    def test_probes_finished_all_none(self):
        pr1, pr2 = MagicMock(), MagicMock()
        pr1.status = None
        pr2.status = None
        self.fw.probe_results = [pr1, pr2]
        self.assertEqual(self.fw.probes_finished, 0)

    def test_status_0(self):
        pr1, pr2 = MagicMock(), MagicMock()
        pr1.type, pr1.status = IrmaProbeType.antivirus, 0
        pr2.type, pr2.status = IrmaProbeType.antivirus, 0
        self.fw.probe_results = [pr1, pr2]
        self.assertEqual(self.fw.status, 0)

    def test_status_1(self):
        pr1, pr2 = MagicMock(), MagicMock()
        pr1.type, pr1.status = IrmaProbeType.antivirus, 0
        pr2.type, pr2.status = IrmaProbeType.antivirus, 1
        self.fw.probe_results = [pr1, pr2]
        self.assertEqual(self.fw.status, 1)

    def test_status_2(self):
        pr1, pr2 = MagicMock(), MagicMock()
        pr1.type, pr1.status = IrmaProbeType.antivirus, None
        pr2.type, pr2.status = IrmaProbeType.antivirus, 1
        self.fw.probe_results = [pr1, pr2]
        self.assertEqual(self.fw.status, None)

    def test_get_probe_results_as_list(self):
        pr1, pr2 = MagicMock(), MagicMock()
        pr1.doc = "whatever"
        pr2.doc = "something"
        self.fw.probe_results = [pr1, pr2]
        self.assertCountEqual(self.fw.get_probe_results(results_as="list"),
                              [pr1.get_details(True),
                               pr2.get_details(True)])
        pr1.get_details.assert_called_with(True)
        pr2.get_details.assert_called_with(True)

    def test_get_probe_results_as_dict(self):
        pr1, pr2 = MagicMock(), MagicMock()
        pr3 = MagicMock()
        pr1.doc = "whatever"
        pr2.doc = "something"
        pr3.status = None
        self.fw.probe_results = [pr1, pr2, pr3]
        self.assertIsInstance(self.fw.get_probe_results(results_as="dict"),
                              dict)
        pr1.get_details.assert_called_with(True)
        pr2.get_details.assert_called_with(True)
        pr3.get_details.assert_not_called()

    def test_get_probe_results_errors1(self):
        pr1, pr2 = MagicMock(), MagicMock()
        pr1.doc = "whatever"
        pr2.doc = "something"
        self.fw.probe_results = [pr1, pr2]
        with self.assertRaises(ValueError):
            self.fw.get_probe_results(results_as="unknown")

    def test_fetch_probe_results(self):
        m_pr = MagicMock()
        probename = "probe1"
        m_pr.name = probename
        self.fw.probe_results = [m_pr]
        res = self.fw.fetch_probe_result(probename)
        self.assertEqual(res, m_pr)

    def test_fetch_probe_results_none(self):
        m_pr = MagicMock()
        probename = "probe1"
        m_pr.name = probename
        self.fw.probe_results = []
        with self.assertRaises(IrmaDatabaseError):
            self.fw.fetch_probe_result(probename)

    def test_fetch_probe_results_multiple_results(self):
        m_pr = MagicMock()
        probename = "probe1"
        m_pr.name = probename
        self.fw.probe_results = [m_pr, m_pr]
        with self.assertRaises(IrmaDatabaseError):
            self.fw.fetch_probe_result(probename)

    def test_from_fobj(self):
        filename = "file"
        m_file = MagicMock()
        fw = FileExt(m_file, filename)
        self.assertIs(type(fw), FileExt)
        self.assertEqual(fw.name, "file")

    def test_set_result(self):
        m_pr = MagicMock()
        m_pr.name = "probename"
        self.fw.probe_results = [m_pr]
        probe = "probename"
        result = {'status': 1, 'type': "something"}
        self.fw.file = MagicMock()
        self.fw.set_result(probe, result)

    def test_probes_empty(self):
        self.fw.probe_results = []
        self.assertEqual(self.fw.probes, [])

    def test_probes_not_empty(self):
        m_pr1, m_pr2 = MagicMock(), MagicMock()
        probename1, probename2 = "probename1", "probename2"
        m_pr1.name = probename1
        m_pr2.name = probename2
        self.fw.probe_results = [m_pr1, m_pr2]
        self.assertCountEqual(self.fw.probes, ["probename1", "probename2"])

    @patch("api.files_ext.models.inspect")
    def test_other_results(self, m_inspect):
        m_session = MagicMock()
        ret = MagicMock()
        ret.session = m_session
        m_inspect.return_value = ret
        res = self.fw.other_results
        self.assertEqual(res,
                         m_session.query().join().filter().order_by().all())

    @patch("api.files_ext.models.log")
    def test_hook_finished_submitter_id(self, m_log):
        self.scan.date = "scan_date"
        payload = {'submitter_id': "my_kiosk_id"}
        fw = module.FileKiosk(self.file, self.name, payload)
        fw.scan = self.scan
        fw.file.sha256 = "sha256"
        fw.name = "filename"
        fw.file.timestamp_first_scan = "ts_first_scan"
        fw.file.timestamp_last_scan = "ts_last_scan"
        fw.file.size = "size"
        pr1 = MagicMock()
        fw.probe_results = [pr1]
        pr1.name = "probe1"
        pr1.type = "antivirus"
        pr1.status = "status1"
        pr1.duration = "duration1"
        pr1.results = "results1"
        pr1.get_details.return_value = pr1
        fw.hook_finished()

        expected1 = "[files_results] date: %s file_id: %s scan_id: %s "
        expected1 += "status: %s probes: %s submitter: %s submitter_id: %s"
        call1 = call(expected1, 'scan_date', fw.external_id,
                     fw.scan.external_id, 'Clean', 'probe1', 'kiosk',
                     'my_kiosk_id')

        expected2 = '[av_results] date: %s av_name: "%s" '
        expected2 += "status: %d virus_name: \"%s\" file_id: %s "
        expected2 += "file_sha256: %s scan_id: %s duration: %f "
        expected2 += "submitter: %s submitter_id: %s"
        call2 = call(expected2, 'scan_date', 'probe1', 'status1', 'results1',
                     fw.external_id, 'sha256', fw.scan.external_id,
                     'duration1', 'kiosk', 'my_kiosk_id')

        m_log.info.assert_has_calls([call1])
        m_log.info.assert_has_calls([call2])

    @patch("api.files_ext.models.log")
    def test_hook_finished(self, m_log):
        self.scan.date = "scan_date"
        self.fw.scan = self.scan
        self.fw.file.sha256 = "sha256"
        self.fw.name = "filename"
        self.fw.file.timestamp_first_scan = "ts_first_scan"
        self.fw.file.timestamp_last_scan = "ts_last_scan"
        self.fw.file.size = "size"
        pr1, pr2 = MagicMock(), MagicMock()
        self.fw.probe_results = [pr1, pr2]
        pr1.name = "probe1"
        pr1.type = "antivirus"
        pr1.status = "status1"
        pr1.duration = "duration1"
        pr1.results = "results1"
        pr2.name = "probe2"
        pr2.type = "metadata"
        pr2.status = "status2"
        pr2.duration = None
        pr2.results = "results2"
        pr1.get_details.return_value = pr1
        pr2.get_details.return_value = pr2
        self.fw.hook_finished()

        expected1 = "[files_results] date: %s file_id: %s scan_id: %s "
        expected1 += "status: %s probes: %s submitter: %s submitter_id: %s"
        call1 = call(expected1, 'scan_date', self.fw.external_id,
                     self.fw.scan.external_id, 'Clean', 'probe1, probe2',
                     'unknown', 'undefined')

        expected2 = '[av_results] date: %s av_name: "%s" '
        expected2 += "status: %d virus_name: \"%s\" file_id: %s "
        expected2 += "file_sha256: %s scan_id: %s duration: %f "
        expected2 += "submitter: %s submitter_id: %s"
        call2 = call(expected2, 'scan_date', 'probe1', 'status1', 'results1',
                     self.fw.external_id, 'sha256', self.fw.scan.external_id,
                     'duration1', 'unknown', 'undefined')

        expected3 = '[probe_results] date: %s name: "%s" '
        expected3 += "status: %d file_sha256: %s file_id: %s "
        expected3 += "duration: %f submitter: %s submitter_id: %s"
        call3 = call(expected3, 'scan_date', 'probe2', 'status2',
                     self.fw.external_id, 'sha256', 0, 'unknown', 'undefined')

        m_log.info.assert_has_calls([call1])
        m_log.info.assert_has_calls([call2])
        m_log.info.assert_has_calls([call3])

    def test_FileProbeResult(self):
        pr = ProbeResult("doc", "name", "status", "type")
        fe = module.FileProbeResult(self.file, self.name, pr, "depth")
        self.assertEqual(fe.probe_result_parent, pr)
        self.assertEqual(fe.depth, "depth")

    def test_FileSuricata(self):
        fe = module.FileSuricata(self.file, self.name, "context")
        self.assertEqual(fe.context, "context")
Example #20
0
 def setUp(self):
     self.file = MagicMock()
     self.name = "name"
     self.scan = MagicMock()
     self.fw = FileExt(self.file, self.name)
Example #21
0
def launch_v2(request, body):
    """ Launch a scan.
        The request should be performed using a POST request method.
        The input json format is the following:
        {
            files: [fileext1, fileext2...]
            options:
               probes: list of probes or None for all available,
               force: boolean (default False),
               mimetype_filtering: boolean (default True),
               resubmit_files: boolean (default True),
        }
    """
    scan_params = body
    if not scan_params:
        raise HTTPInvalidParam("Missing json parameters", "body")
    files_list = body.get('files', None)

    if files_list is None or len(files_list) == 0:
        raise HTTPInvalidParam("Missing values", "files")

    # Set default values
    force = True
    mimetype_filtering = True
    resubmit_files = True
    probes = None
    # override with given values if set
    scan_options = body.get("options", None)
    if scan_options is not None:
        force = scan_options.get("force", force)
        if type(force) is not bool:
            raise HTTPInvalidParam("Should be boolean", "force")
        mimetype_filtering = scan_options.get("mimetype_filtering",
                                              mimetype_filtering)
        if type(mimetype_filtering) is not bool:
            raise HTTPInvalidParam("Should be boolean",
                                   "mimetype_filtering")
        resubmit_files = scan_options.get("resubmit_files", resubmit_files)
        if type(resubmit_files) is not bool:
            raise HTTPInvalidParam("Should be boolean",
                                   "resubmit_files")
        probes = scan_options.get("probes", probes)

    session = db.session
    ip = request.remote_addr

    files_ext = []
    for fe_id in files_list:
        try:
            file_ext = FileExt.load_from_ext_id(fe_id, session)
        except IrmaDatabaseResultNotFound:
            raise HTTPInvalidParam("File %s not found" % fe_id,
                                   "files")
        if file_ext.file.path is None:
            raise HTTPInvalidParam("File with hash %s should be ("
                                   "re)uploaded" %
                                   file_ext.file.sha256,
                                   "files")
        if file_ext.scan is not None:
            raise HTTPInvalidParam("File %s already scanned" %
                                   fe_id,
                                   "files")
        files_ext.append(file_ext)

    scan = Scan(compat.timestamp(), ip,
                force=force, mimetype_filtering=mimetype_filtering,
                resubmit_files=resubmit_files, files_ext=files_ext,
                probes=probes)
    session.add(scan)
    session.commit()
    # launch_asynchronous scan via frontend task
    celery_frontend.scan_launch(str(scan.external_id))

    return scan_schema.dump(scan).data
Example #22
0
class TestFileExt(TestCase):

    def setUp(self):
        self.file = MagicMock()
        self.name = "name"
        self.scan = MagicMock()
        self.fw = FileExt(self.file, self.name)

    def tearDown(self):
        del self.fw

    def test_load_from_ext_id(self):
        m_session = MagicMock()
        ext_id = "whatever"
        FileExt.load_from_ext_id(ext_id, m_session)
        m_filter = m_session.query(FileExt).filter
        m_filter.is_called_once_with(FileExt.external_id == ext_id)

    def test_load_from_ext_id_raises_noresult(self):
        m_session = MagicMock()
        ext_id = "whatever"
        m_session.query().filter().one.side_effect = NoResultFound()
        with self.assertRaises(IrmaDatabaseResultNotFound):
            FileExt.load_from_ext_id(ext_id, m_session)

    def test_load_from_ext_id_raises_multiple(self):
        m_session = MagicMock()
        ext_id = "whatever"
        m_session.query().filter().one.side_effect = MultipleResultsFound()
        with self.assertRaises(IrmaDatabaseError):
            FileExt.load_from_ext_id(ext_id, m_session)

    @patch("api.files_ext.models.File")
    @patch("api.files_ext.models.Tag")
    def test_find_by_name(self, m_Tag, m_File):
        m_session = MagicMock()
        name = "something"
        tag = MagicMock()
        tag.id = randint(0, 10)
        tags = [tag.id]
        FileExt.query_find_by_name(name, tags, m_session)
        m_session.query.called_with(m_Tag)
        m_session.query().filter_by.assert_called_once_with(id=tag.id)
        m_session.query().filter_by().one.assert_called_once()

    @patch("api.files_ext.models.File")
    @patch("api.files_ext.models.Tag")
    def test_find_by_hash(self, m_Tag, m_File):
        m_session = MagicMock()
        hash_type, hash = "something", "anotherthing"
        tag = MagicMock()
        tag.id = randint(0, 10)
        tags = [tag.id]
        FileExt.query_find_by_hash(hash_type, hash, tags, m_session)
        m_session.query.called_with(FileExt)
        m_session.query().filter_by.assert_called_once_with(id=tag.id)
        m_session.query().filter_by().one.assert_called_once()

    @patch("api.files_ext.models.File")
    @patch("api.files_ext.models.Tag")
    def test_find_by_hash_distinct_false(self, m_Tag, m_File):
        m_session = MagicMock()
        hash_type, hash = "something", "anotherthing"
        tag = MagicMock()
        tag.id = randint(0, 10)
        tags = [tag.id]
        FileExt.query_find_by_hash(hash_type, hash, tags, m_session,
                                   distinct_name=False)
        m_session.query.called_with(FileExt)
        m_session.query().filter_by.assert_called_once_with(id=tag.id)
        m_session.query().filter_by().one.assert_called_once()

    def test_probes_finished(self):
        pr1, pr2 = MagicMock(), MagicMock()
        pr1.status = None
        pr2.status = 1
        self.fw.probe_results = [pr1, pr2]
        self.assertEqual(self.fw.probes_finished, 1)

    def test_probes_finished_all_none(self):
        pr1, pr2 = MagicMock(), MagicMock()
        pr1.status = None
        pr2.status = None
        self.fw.probe_results = [pr1, pr2]
        self.assertEqual(self.fw.probes_finished, 0)

    def test_status_0(self):
        pr1, pr2 = MagicMock(), MagicMock()
        pr1.type, pr1.status = IrmaProbeType.antivirus, 0
        pr2.type, pr2.status = IrmaProbeType.antivirus, 0
        self.fw.probe_results = [pr1, pr2]
        self.assertEqual(self.fw.status, 0)

    def test_status_1(self):
        pr1, pr2 = MagicMock(), MagicMock()
        pr1.type, pr1.status = IrmaProbeType.antivirus, 0
        pr2.type, pr2.status = IrmaProbeType.antivirus, 1
        self.fw.probe_results = [pr1, pr2]
        self.assertEqual(self.fw.status, 1)

    def test_status_2(self):
        pr1, pr2 = MagicMock(), MagicMock()
        pr1.type, pr1.status = IrmaProbeType.antivirus, None
        pr2.type, pr2.status = IrmaProbeType.antivirus, 1
        self.fw.probe_results = [pr1, pr2]
        self.assertEqual(self.fw.status, None)

    def test_get_probe_results_as_list(self):
        pr1, pr2 = MagicMock(), MagicMock()
        pr1.doc = "whatever"
        pr2.doc = "something"
        self.fw.probe_results = [pr1, pr2]
        self.assertCountEqual(self.fw.get_probe_results(results_as="list"),
                              [pr1.get_details(True),
                               pr2.get_details(True)])
        pr1.get_details.assert_called_with(True)
        pr2.get_details.assert_called_with(True)

    def test_get_probe_results_as_dict(self):
        pr1, pr2 = MagicMock(), MagicMock()
        pr3 = MagicMock()
        pr1.doc = "whatever"
        pr2.doc = "something"
        pr3.status = None
        self.fw.probe_results = [pr1, pr2, pr3]
        self.assertIsInstance(self.fw.get_probe_results(results_as="dict"),
                              dict)
        pr1.get_details.assert_called_with(True)
        pr2.get_details.assert_called_with(True)
        pr3.get_details.assert_not_called()

    def test_get_probe_results_errors1(self):
        pr1, pr2 = MagicMock(), MagicMock()
        pr1.doc = "whatever"
        pr2.doc = "something"
        self.fw.probe_results = [pr1, pr2]
        with self.assertRaises(ValueError):
            self.fw.get_probe_results(results_as="unknown")

    def test_fetch_probe_results(self):
        m_pr = MagicMock()
        probename = "probe1"
        m_pr.name = probename
        self.fw.probe_results = [m_pr]
        res = self.fw.fetch_probe_result(probename)
        self.assertEqual(res, m_pr)

    def test_fetch_probe_results_none(self):
        m_pr = MagicMock()
        probename = "probe1"
        m_pr.name = probename
        self.fw.probe_results = []
        with self.assertRaises(IrmaDatabaseError):
            self.fw.fetch_probe_result(probename)

    def test_fetch_probe_results_multiple_results(self):
        m_pr = MagicMock()
        probename = "probe1"
        m_pr.name = probename
        self.fw.probe_results = [m_pr, m_pr]
        with self.assertRaises(IrmaDatabaseError):
            self.fw.fetch_probe_result(probename)

    def test_from_fobj(self):
        filename = "file"
        m_file = MagicMock()
        fw = FileExt(m_file, filename)
        self.assertIs(type(fw), FileExt)
        self.assertEqual(fw.name, "file")

    def test_set_result(self):
        m_pr = MagicMock()
        m_pr.name = "probename"
        self.fw.probe_results = [m_pr]
        probe = "probename"
        result = {'status': 1, 'type': "something"}
        self.fw.file = MagicMock()
        self.fw.set_result(probe, result)

    def test_probes_empty(self):
        self.fw.probe_results = []
        self.assertEqual(self.fw.probes, [])

    def test_probes_not_empty(self):
        m_pr1, m_pr2 = MagicMock(), MagicMock()
        probename1, probename2 = "probename1", "probename2"
        m_pr1.name = probename1
        m_pr2.name = probename2
        self.fw.probe_results = [m_pr1, m_pr2]
        self.assertCountEqual(self.fw.probes, ["probename1", "probename2"])

    @patch("api.files_ext.models.inspect")
    def test_other_results(self, m_inspect):
        m_session = MagicMock()
        ret = MagicMock()
        ret.session = m_session
        m_inspect.return_value = ret
        res = self.fw.other_results
        self.assertEqual(res,
                         m_session.query().join().filter().order_by().all())

    @patch("api.files_ext.models.log")
    def test_hook_finished_submitter_id(self, m_log):
        self.scan.date = "scan_date"
        payload = {'submitter_id': "my_kiosk_id"}
        fw = module.FileKiosk(self.file, self.name, payload)
        fw.scan = self.scan
        fw.file.sha256 = "sha256"
        fw.name = "filename"
        fw.file.timestamp_first_scan = "ts_first_scan"
        fw.file.timestamp_last_scan = "ts_last_scan"
        fw.file.size = "size"
        pr1 = MagicMock()
        fw.probe_results = [pr1]
        pr1.name = "probe1"
        pr1.type = "antivirus"
        pr1.status = "status1"
        pr1.duration = "duration1"
        pr1.results = "results1"
        pr1.get_details.return_value = pr1
        fw.hook_finished()

        expected1 = "[files_results] date: %s file_id: %s scan_id: %s "
        expected1 += "status: %s probes: %s submitter: %s submitter_id: %s"
        call1 = call(expected1,
                     'scan_date',
                     fw.external_id,
                     fw.scan.external_id, 'Clean', 'probe1',
                     'kiosk', 'my_kiosk_id')

        expected2 = '[av_results] date: %s av_name: "%s" '
        expected2 += "status: %d virus_name: \"%s\" file_id: %s "
        expected2 += "file_sha256: %s scan_id: %s duration: %f "
        expected2 += "submitter: %s submitter_id: %s"
        call2 = call(expected2,
                     'scan_date',
                     'probe1',
                     'status1',
                     'results1',
                     fw.external_id,
                     'sha256', fw.scan.external_id, 'duration1',
                     'kiosk', 'my_kiosk_id')

        m_log.info.assert_has_calls([call1])
        m_log.info.assert_has_calls([call2])

    @patch("api.files_ext.models.log")
    def test_hook_finished(self, m_log):
        self.scan.date = "scan_date"
        self.fw.scan = self.scan
        self.fw.file.sha256 = "sha256"
        self.fw.name = "filename"
        self.fw.file.timestamp_first_scan = "ts_first_scan"
        self.fw.file.timestamp_last_scan = "ts_last_scan"
        self.fw.file.size = "size"
        pr1, pr2 = MagicMock(), MagicMock()
        self.fw.probe_results = [pr1, pr2]
        pr1.name = "probe1"
        pr1.type = "antivirus"
        pr1.status = "status1"
        pr1.duration = "duration1"
        pr1.results = "results1"
        pr2.name = "probe2"
        pr2.type = "metadata"
        pr2.status = "status2"
        pr2.duration = None
        pr2.results = "results2"
        pr1.get_details.return_value = pr1
        pr2.get_details.return_value = pr2
        self.fw.hook_finished()

        expected1 = "[files_results] date: %s file_id: %s scan_id: %s "
        expected1 += "status: %s probes: %s submitter: %s submitter_id: %s"
        call1 = call(expected1,
                     'scan_date',
                     self.fw.external_id,
                     self.fw.scan.external_id, 'Clean', 'probe1, probe2',
                     'unknown', 'undefined')

        expected2 = '[av_results] date: %s av_name: "%s" '
        expected2 += "status: %d virus_name: \"%s\" file_id: %s "
        expected2 += "file_sha256: %s scan_id: %s duration: %f "
        expected2 += "submitter: %s submitter_id: %s"
        call2 = call(expected2,
                     'scan_date',
                     'probe1',
                     'status1',
                     'results1',
                     self.fw.external_id,
                     'sha256', self.fw.scan.external_id, 'duration1',
                     'unknown', 'undefined')

        expected3 = '[probe_results] date: %s name: "%s" '
        expected3 += "status: %d file_sha256: %s file_id: %s "
        expected3 += "duration: %f submitter: %s submitter_id: %s"
        call3 = call(expected3,
                     'scan_date',
                     'probe2',
                     'status2',
                     self.fw.external_id,
                     'sha256', 0, 'unknown', 'undefined')

        m_log.info.assert_has_calls([call1])
        m_log.info.assert_has_calls([call2])
        m_log.info.assert_has_calls([call3])

    def test_FileProbeResult(self):
        pr = ProbeResult("doc", "name", "status", "type")
        fe = module.FileProbeResult(self.file, self.name, pr, "depth")
        self.assertEqual(fe.probe_result_parent, pr)
        self.assertEqual(fe.depth, "depth")

    def test_FileSuricata(self):
        fe = module.FileSuricata(self.file, self.name, "context")
        self.assertEqual(fe.context, "context")