def launch(scanid, db): """ Launch a scan. The request should be performed using a POST request method. """ try: validate_id(scanid) scan = Scan.load_from_ext_id(scanid, db) probes = None # handle scan parameter / cached results: "force" if 'force' in request.json and request.json.get('force'): scan.force = True db.commit() # V1 retro compatibility scan.mimetype_filtering = False scan.file_resubmit = False # handle scan parameter / probelist: "probes" if 'probes' in request.json: probes = request.json.get('probes').split(',') msg = "scanid: %s Force %s MimeF %s" msg += "Resub %s Probes %s" log.debug(msg, scanid, scan.force, scan.mimetype_filtering, scan.resubmit_files, probes) scan_ctrl.check_probe(scan, probes, db) # launch_asynchronous scan via frontend task celery_frontend.scan_launch(scanid) response.content_type = "application/json; charset=UTF-8" return scan_schema.dumps(scan).data except Exception as e: log.exception(e) process_error(e)
def add_files(scanid, db): """ Attach a file to a scan. The request should be performed using a POST request method. """ try: log.debug("scanid: %s", scanid) validate_id(scanid) scan = Scan.load_from_ext_id(scanid, db) if len(request.files) == 0: raise ValueError("No files uploaded") files = {} for f in request.files: upfile = request.files.get(f) filename = decode_utf8(upfile.raw_filename) data = upfile.file files[filename] = data scan_ctrl.add_files(scan, files, db) response.content_type = "application/json; charset=UTF-8" return scan_schema.dumps(scan).data except Exception as e: log.exception(e) process_error(e)
def list(db): """ Get a list of all scans which have been launched. """ try: offset = int(request.query.offset) if request.query.offset else 0 limit = int(request.query.limit) if request.query.limit else 5 log.debug("offset %d limit %d", offset, limit) base_query = db.query(Scan) items = base_query.limit(limit).offset(offset).all() if offset == 0 and len(items) < limit: total = len(items) else: total = base_query.count() log.debug("found %d scans", total) response.content_type = "application/json; charset=UTF-8" return { "total": total, "offset": offset, "limit": limit, "data": scan_schema.dump(items, many=True).data, } except Exception as e: log.exception(e) process_error(e)
def list(db): """ Get a list of all scans which have been launched. """ try: offset = int(request.query.offset) if request.query.offset else 0 limit = int(request.query.limit) if request.query.limit else 5 log.debug("offset %d limit %d", offset, limit) base_query = db.query(Scan) items = base_query.limit(limit).offset(offset).all() if offset == 0 and len(items) < limit: total = len(items) else: total = base_query.count() log.debug("found %d scans", total) response.content_type = "application/json; charset=UTF-8" return { "total": total, "offset": offset, "limit": limit, "data": scan_schema.dump(items, many=True).data, } except Exception as e: log.exception(e) process_error(e)
def add_files(scanid, db): """ Attach a file to a scan. The request should be performed using a POST request method. """ try: log.debug("scanid: %s", scanid) validate_id(scanid) scan = Scan.load_from_ext_id(scanid, db) if len(request.files) == 0: raise ValueError("No files uploaded") files = {} for f in request.files: upfile = request.files.get(f) filename = decode_utf8(upfile.raw_filename) data = upfile.file files[filename] = data scan_ctrl.add_files(scan, files, db) response.content_type = "application/json; charset=UTF-8" return scan_schema.dumps(scan).data except Exception as e: log.exception(e) process_error(e)
def launch(scanid, db): """ Launch a scan. The request should be performed using a POST request method. """ try: validate_id(scanid) scan = Scan.load_from_ext_id(scanid, db) probes = None # handle scan parameter / cached results: "force" if 'force' in request.json and request.json.get('force'): scan.force = True db.commit() # V1 retro compatibility scan.mimetype_filtering = False scan.file_resubmit = False # handle scan parameter / probelist: "probes" if 'probes' in request.json: probes = request.json.get('probes').split(',') msg = "scanid: %s Force %s MimeF %s" msg += "Resub %s Probes %s" log.debug(msg, scanid, scan.force, scan.mimetype_filtering, scan.resubmit_files, probes) scan_ctrl.check_probe(scan, probes, db) # launch_asynchronous scan via frontend task celery_frontend.scan_launch(scanid) response.content_type = "application/json; charset=UTF-8" return scan_schema.dumps(scan).data except Exception as e: log.exception(e) process_error(e)
def test004_process_database_error(self, m_sys, m_abort): m_sys.exc_info.return_value = (MagicMock(), None, MagicMock()) error = IrmaDatabaseError("message_error") exp_code = 402 exp_error = api_errors.ApiError("database_error") api_errors.process_error(error) m_abort.assert_called_once() call_args = m_abort.call_args[0] self.assertEqual(call_args[0], exp_code) self.assertEqual(str(call_args[1]), str(exp_error))
def test003_process_notfound_error(self, m_sys, m_abort): m_sys.exc_info.return_value = (MagicMock(), None, MagicMock()) error = IrmaDatabaseResultNotFound("message_error") exp_code = 404 exp_error = api_errors.ApiError("request_error", "Object not Found") api_errors.process_error(error) m_abort.assert_called_once() call_args = m_abort.call_args[0] self.assertEqual(call_args[0], exp_code) self.assertEqual(str(call_args[1]), str(exp_error))
def get(scanid, db): """ Retrieve information for a specific scan """ try: log.debug("scanid: %s", scanid) validate_id(scanid) scan = Scan.load_from_ext_id(scanid, db) response.content_type = "application/json; charset=UTF-8" return scan_schema.dumps(scan).data except Exception as e: log.exception(e) process_error(e)
def get(scanid, db): """ Retrieve information for a specific scan """ try: log.debug("scanid: %s", scanid) validate_id(scanid) scan = Scan.load_from_ext_id(scanid, db) response.content_type = "application/json; charset=UTF-8" return scan_schema.dumps(scan).data except Exception as e: log.exception(e) process_error(e)
def list(): """ get active probe list. This list is used to launch a scan. """ try: probelist = celery_brain.probe_list() log.debug("probe list: %s", "-".join(probelist)) response.content_type = "application/json; charset=UTF-8" return { "total": len(probelist), "data": probelist } except Exception as e: log.exception(e) process_error(e)
def get_results(scanid, db): """ Retrieve results for a scan. Results are the same as in the get() method, i.e. a summary for each scanned files. The request should be performed using a GET request method. """ try: log.debug("scanid: %s", scanid) validate_id(scanid) scan = Scan.load_from_ext_id(scanid, db) file_web_schema = FileWebSchema_v1(exclude=('probe_results', 'file_infos')) response.content_type = "application/json; charset=UTF-8" return file_web_schema.dumps(scan.files_web, many=True).data except Exception as e: log.exception(e) process_error(e)
def cancel(scanid, db): """ Cancel a scan. The request should be performed using a POST request method. """ try: log.debug("scanid: %s", scanid) validate_id(scanid) scan = Scan.load_from_ext_id(scanid, db) scan_ctrl.cancel(scan, db) response.content_type = "application/json; charset=UTF-8" return scan_schema.dumps(scan).data except Exception as e: log.exception(e) process_error(e)
def get_results(scanid, db): """ Retrieve results for a scan. Results are the same as in the get() method, i.e. a summary for each scanned files. The request should be performed using a GET request method. """ try: log.debug("scanid: %s", scanid) validate_id(scanid) scan = Scan.load_from_ext_id(scanid, db) file_web_schema = FileWebSchema_v1(exclude=('probe_results', 'file_infos')) response.content_type = "application/json; charset=UTF-8" return file_web_schema.dumps(scan.files_web, many=True).data except Exception as e: log.exception(e) process_error(e)
def cancel(scanid, db): """ Cancel a scan. The request should be performed using a POST request method. """ try: log.debug("scanid: %s", scanid) validate_id(scanid) scan = Scan.load_from_ext_id(scanid, db) scan_ctrl.cancel(scan, db) response.content_type = "application/json; charset=UTF-8" return scan_schema.dumps(scan).data except Exception as e: log.exception(e) process_error(e)
def new(db): """ Create a new scan. The request should be performed using a POST request method. """ try: ip = request.remote_addr scan = Scan(compat.timestamp(), ip) db.add(scan) scan.set_status(IrmaScanStatus.empty) db.commit() log.debug("scanid: %s", scan.external_id) response.content_type = "application/json; charset=UTF-8" return scan_schema.dumps(scan).data except Exception as e: log.exception(e) process_error(e)
def new(db): """ Create a new scan. The request should be performed using a POST request method. """ try: ip = request.remote_addr scan = Scan(compat.timestamp(), ip) db.add(scan) scan.set_status(IrmaScanStatus.empty) db.commit() log.debug("scanid: %s", scan.external_id) response.content_type = "application/json; charset=UTF-8" return scan_schema.dumps(scan).data except Exception as e: log.exception(e) process_error(e)
def get_result(scanid, resultid, db): """ Retrieve a single fileweb result, with details. The request should be performed using a GET request method. """ try: log.debug("scanid: %s resultid %s", scanid, resultid) formatted = False if request.query.formatted == 'no' else True validate_id(resultid) fw = FileWeb.load_from_ext_id(resultid, db) file_web_schema = FileWebSchema_v1(exclude=('mimetype', 'file_sha256', 'parent_file_sha256')) file_web_schema.context = {'formatted': formatted} response.content_type = "application/json; charset=UTF-8" return file_web_schema.dumps(fw).data except Exception as e: log.exception(e) process_error(e)
def get_result(scanid, resultid, db): """ Retrieve a single fileweb result, with details. The request should be performed using a GET request method. """ try: log.debug("scanid: %s resultid %s", scanid, resultid) formatted = False if request.query.formatted == 'no' else True validate_id(resultid) fw = FileWeb.load_from_ext_id(resultid, db) file_web_schema = FileWebSchema_v1(exclude=('mimetype', 'file_sha256', 'parent_file_sha256')) file_web_schema.context = {'formatted': formatted} response.content_type = "application/json; charset=UTF-8" return file_web_schema.dumps(fw).data except Exception as e: log.exception(e) process_error(e)
def files(db): """ Search a file using query filters (hash or name). Support pagination. :param all params are send using query method :rtype: dict of 'total': int, 'page': int, 'per_page': int, 'items': list of file(s) found :return: on success 'items' contains a list of files found on error 'msg' gives reason message """ try: name = None if 'name' in request.query: name = decode_utf8(request.query['name']) h_value = request.query.get('hash') log.debug("name %s h_value %s", name, h_value) if name is not None and h_value is not None: raise ValueError("Can't find using both name and hash") # Get values from Query or Default offset = request.query.get("offset", default=0) offset = int(offset) limit = request.query.get("limit", default=25) limit = int(limit) if name is not None: base_query = FileWeb.query_find_by_name(name, None, db) elif h_value is not None: h_type = guess_hash_type(h_value) if h_type is None: raise ValueError("Hash not supported") base_query = FileWeb.query_find_by_hash(h_type, h_value, None, db) else: # FIXME this is just a temporary way to output # all files, need a dedicated # file route and controller base_query = FileWeb.query_find_by_name("", None, db) # TODO: Find a way to move pagination as a BaseQuery like in # flask_sqlalchemy. # https://github.com/mitsuhiko/flask-sqlalchemy/blob/master/flask_sqlalchemy/__init__.py#L422 items = base_query.limit(limit).offset(offset).all() if offset == 0 and len(items) < limit: total = len(items) else: total = base_query.count() log.debug("Found %s results", total) response.content_type = "application/json; charset=UTF-8" return { 'total': total, 'offset': offset, 'limit': limit, 'items': file_web_schema.dump(items, many=True).data, } except Exception as e: log.exception(e) process_error(e)
def files(db): """ Search a file using query filters (hash or name). Support pagination. :param all params are send using query method :rtype: dict of 'total': int, 'page': int, 'per_page': int, 'items': list of file(s) found :return: on success 'items' contains a list of files found on error 'msg' gives reason message """ try: name = None if 'name' in request.query: name = decode_utf8(request.query['name']) h_value = request.query.hash or None log.debug("name %s h_value %s", name, h_value) if name is not None and h_value is not None: raise ValueError("Can't find using both name and hash") # Options query offset = int(request.query.offset) if request.query.offset else 0 limit = int(request.query.limit) if request.query.limit else 25 if name is not None: base_query = FileWeb.query_find_by_name(name, None, db) elif h_value is not None: h_type = guess_hash_type(h_value) if h_type is None: raise ValueError("Hash not supported") base_query = FileWeb.query_find_by_hash(h_type, h_value, None, db) else: # FIXME this is just a temporary way to output # all files, need a dedicated # file route and controller base_query = FileWeb.query_find_by_name("", None, db) # TODO: Find a way to move pagination as a BaseQuery like in # flask_sqlalchemy. # https://github.com/mitsuhiko/flask-sqlalchemy/blob/master/flask_sqlalchemy/__init__.py#L422 items = base_query.limit(limit).offset(offset).all() if offset == 0 and len(items) < limit: total = len(items) else: total = base_query.count() log.debug("Found %s results", total) response.content_type = "application/json; charset=UTF-8" return { 'total': total, 'offset': offset, 'limit': limit, 'items': file_web_schema.dump(items, many=True).data, } except Exception as e: log.exception(e) process_error(e)