def handle_get(cls, **kwargs): """Get system details""" inventory_id = kwargs['inventory_id'] stale = kwargs.get('stale', False) try: system = (SystemPlatform.select( SystemPlatform.last_evaluation, SystemPlatform.advisor_evaluated, SystemPlatform.opt_out, SystemPlatform.last_upload, SystemPlatform.stale).join( RHAccount, on=(SystemPlatform.rh_account_id == RHAccount.id)).where( SystemPlatform.inventory_id == inventory_id).where( RHAccount.name == connexion.context['user']).where( SystemPlatform.stale == stale).get()) except DoesNotExist: raise ApplicationException( 'inventory_id must exist and inventory_id must be visible to user', 404) return { 'data': { 'last_evaluation': system.last_evaluation, 'rules_evaluation': system.advisor_evaluated, 'opt_out': system.opt_out, 'last_upload': system.last_upload, 'stale': system.stale } }
def _system_exists_and_visible(cls, inventory_id): system = (SystemPlatform.select() .join(RHAccount, on=(SystemPlatform.rh_account_id == RHAccount.id)) .where((RHAccount.name == connexion.context['user']) & (SystemPlatform.inventory_id == inventory_id))) if not system.exists(): raise ApplicationException("inventory_id must exist and inventory_id must be visible to user", 404)
def handle_get(cls, **kwargs): """Get system details""" inventory_id = kwargs['inventory_id'] try: selectables = [SystemPlatform.last_evaluation, SystemPlatform.advisor_evaluated, SystemPlatform.opt_out, SystemPlatform.last_upload, SystemPlatform.stale] if CYNDI_ENABLED: selectables.append(InventoryHosts.tags) selectables.append(InventoryHosts.updated) query = (SystemPlatform.select(*selectables) .join(RHAccount, on=(SystemPlatform.rh_account_id == RHAccount.id)) .where(SystemPlatform.inventory_id == inventory_id) .where(RHAccount.name == connexion.context['user']) .where(SystemPlatform.when_deleted.is_null(True)).dicts()) system = cyndi_query(query).get() except DoesNotExist: raise ApplicationException('inventory_id must exist and inventory_id must be visible to user', 404) return {'data': {'last_evaluation': system['last_evaluation'], 'rules_evaluation': system['advisor_evaluated'], 'opt_out': system['opt_out'], 'last_upload': system['last_upload'], 'stale': system['stale'], 'tags': system['tags'] if CYNDI_ENABLED and system['tags'] is not None else [], 'updated': system['updated'] if CYNDI_ENABLED else system['last_upload']}}
def handle_get(cls, **kwargs): """Get system details""" inventory_id = kwargs['inventory_id'] try: selectables = [SystemPlatform.last_evaluation, SystemPlatform.advisor_evaluated, SystemPlatform.opt_out, SystemPlatform.last_upload, SystemPlatform.stale, InventoryHosts.tags, InventoryHosts.updated, InventoryHosts.insights_id, OS_INFO_QUERY.alias('os'), ] query = (SystemPlatform.select(*selectables) .join(RHAccount, on=(SystemPlatform.rh_account_id == RHAccount.id)) .where(SystemPlatform.inventory_id == inventory_id) .where(RHAccount.name == connexion.context['user']) .where(SystemPlatform.when_deleted.is_null(True)).dicts()) system = cyndi_join(query).get() except DoesNotExist as exc: raise ApplicationException('inventory_id must exist and inventory_id must be visible to user', 404) from exc return {'data': {'last_evaluation': system['last_evaluation'], 'rules_evaluation': system['advisor_evaluated'], 'opt_out': system['opt_out'], 'last_upload': system['last_upload'], 'stale': system['stale'], 'os': system.get('os', 'N/A'), 'tags': system['tags'] if system['tags'] is not None else [], 'updated': system['updated'], 'insights_id': system['insights_id']}}
def _full_query(rh_account_id): # pylint: disable=singleton-comparison selectables = [ SystemPlatform.inventory_id, SystemPlatform.display_name, SystemPlatform.last_evaluation, SystemPlatform.advisor_evaluated.alias('rules_evaluation'), SystemPlatform.opt_out, SystemPlatform.last_upload, SystemPlatform.stale_timestamp, SystemPlatform.stale_warning_timestamp, SystemPlatform.culled_timestamp, Case(None, (((SystemPlatform.opt_out == False), SystemPlatform.cve_count_cache), ), None).alias("cve_count"), InventoryHosts.tags, InventoryHosts.updated, InventoryHosts.insights_id, OS_INFO_QUERY.alias('os'), ] return (SystemPlatform.select(*selectables).where( SystemPlatform.rh_account_id == rh_account_id).where( SystemPlatform.last_evaluation.is_null(False) | SystemPlatform.advisor_evaluated.is_null(False)).where( SystemPlatform.when_deleted.is_null(True)).dicts())
def __init__(self, list_args, query_args, filter_args, parsed_args, uri): # pylint: disable=singleton-comparison query = (SystemPlatform.select( SystemPlatform.inventory_id, SystemPlatform.last_evaluation, SystemPlatform.opt_out, SystemPlatform.cve_count_cache.alias("cve_count"), SystemPlatform.last_upload, ).join(RHAccount, on=(RHAccount.id == SystemPlatform.rh_account_id)).where( RHAccount.name == query_args['rh_account_number']).where( SystemPlatform.last_evaluation.is_null(False)).dicts()) if 'opt_out' in filter_args and filter_args['opt_out']: query = query.where( SystemPlatform.opt_out == filter_args['opt_out']) else: query = query.where(SystemPlatform.opt_out == False) # noqa: E712 sortable_columns = { 'id': SystemPlatform.id, 'cve_count': SystemPlatform.cve_count_cache, 'inventory_id': SystemPlatform.inventory_id, 'last_evaluation': SystemPlatform.last_evaluation, 'last_upload': SystemPlatform.last_upload } default_sort_columns = ['id'] filterable_columns = {'inventory_id': SystemPlatform.inventory_id} super(SystemView, self).__init__(query, sortable_columns, default_sort_columns, filterable_columns, list_args, parsed_args, uri)
def _system_exists(cls, inventory_id): if inventory_id is None: raise ApplicationException("invalid inventory_id", 400) system = (SystemPlatform.select().where( SystemPlatform.inventory_id == inventory_id)) if not system.exists(): raise ApplicationException("inventory_id must exist", 404)
def handle_patch(cls, **kwargs): """Update the 'status' field for a system/cve combination""" data = kwargs['data'] in_inventory_id = data['inventory_id'] in_cve = data['cve'] in_status_id = data['status_id'] LOGGER.debug('SYSID [%s] CVE [%s] STATUS-ID [%s] ACCT [%s]', in_inventory_id, in_cve, in_status_id, connexion.context['user']) try: plat = (SystemPlatform.select(SystemPlatform.inventory_id) .where((SystemPlatform.rh_account == connexion.context['user']) & (SystemPlatform.inventory_id == in_inventory_id) & (SystemPlatform.opt_out == False))) # pylint: disable=singleton-comparison if cls.hide_satellite_managed(): plat = plat.where(SystemPlatform.satellite_managed == False) # pylint: disable=singleton-comparison vuln = (SystemVulnerabilities.update(status_id=in_status_id) .from_(plat) .where((SystemVulnerabilities.inventory_id == in_inventory_id) & (SystemVulnerabilities.cve == in_cve))) rows_modified = vuln.execute() if rows_modified == 0: # sysid/cve/acct combination does not exist return cls.format_exception('inventory_id/cve must exist and inventory_id must be visible to user', 404) except (IntegrityError, ValueError, psycopg2IntegrityError) as integ_error: # usually means bad-status-id DB.rollback() return cls.format_exception(str(integ_error), 500) return ''
def _id_query(query_args): return (SystemPlatform.select(SystemPlatform.inventory_id, ).join( RHAccount, on=(RHAccount.id == SystemPlatform.rh_account_id)).where( RHAccount.name == query_args['rh_account_number']).where( SystemPlatform.last_evaluation.is_null(False) | SystemPlatform.advisor_evaluated.is_null(False)).where( SystemPlatform.when_deleted.is_null(True)).dicts())
def get_system_count(rh_account): """Get count of nonstale, nonoptouted, evaluated user systems""" # pylint: disable=singleton-comparison return SystemPlatform.select(fn.COUNT(SystemPlatform.id).alias('count')) \ .where((SystemPlatform.rh_account_id == rh_account) & ((SystemPlatform.last_evaluation.is_null(False)) | (SystemPlatform.advisor_evaluated.is_null(False))) & ((SystemPlatform.opt_out == False) & (SystemPlatform.stale == False) & (SystemPlatform.when_deleted.is_null(True)))) \ .first().count # noqa: E712
def handle_get(cls, **kwargs): """Gets affected CVEs for a system""" inventory_id = kwargs['inventory_id'] args_desc = [{'arg_name': 'cvss_from', 'convert_func': None}, {'arg_name': 'cvss_to', 'convert_func': None}, {'arg_name': 'public_from', 'convert_func': dateutil.parser.parse}, {'arg_name': 'public_to', 'convert_func': dateutil.parser.parse}, {'arg_name': 'impact', 'convert_func': parse_int_list}, {'arg_name': 'status_id', 'convert_func': parse_int_list}, {'arg_name': 'business_risk_id', 'convert_func': parse_int_list}, {'arg_name': 'stale', 'convert_func': None} ] args = cls._parse_arguments(kwargs, args_desc) list_arguments = cls._parse_list_arguments(kwargs) # check if system was evaluated try: system = (SystemPlatform.select( SystemPlatform.last_evaluation, SystemPlatform.opt_out) .join(RHAccount, on=(SystemPlatform.rh_account_id == RHAccount.id)) .where(SystemPlatform.inventory_id == inventory_id) .where(RHAccount.name == connexion.context['user']) .get()) except DoesNotExist: raise ApplicationException('inventory_id must exist and inventory_id must be visible to user', 404) if system.last_evaluation is None: raise ApplicationException('inventory_id exists but is not evaluated', 404) cves_view = SystemCvesView(list_arguments, {"rh_account_number": connexion.context['user'], 'inventory_id': inventory_id}, args, args, connexion.request.path) response = {} result = [] for cve in cves_view: record = {} record['synopsis'] = cve['cve_name'] record['public_date'] = cve['public_date'].isoformat() if cve['public_date'] else None record['impact'] = cve['impact'] record['description'] = cve['cve_description'] # Store everything we know about CVSS - maybe UI needs to decide what to show record['cvss2_score'] = str(cve['cvss2_score']) if cve['cvss2_score'] is not None else None record['cvss3_score'] = str(cve['cvss3_score']) if cve['cvss3_score'] is not None else None # Store status information record['cve_status_id'] = cve['cve_status_id'] record['status_id'] = cve['status_id'] record['status'] = cve['status_name'] record['status_text'] = cve['status_text'] record['business_risk'] = cve['business_risk'] record['business_risk_id'] = cve['business_risk_id'] record['business_risk_text'] = cve['business_risk_text'] result.append({'type': 'cve', 'id': cve['cve_name'], 'attributes': record}) response['meta'] = cves_view.get_metadata() response['meta']['opt_out'] = system.opt_out response['links'] = cves_view.get_pagination_links() response['data'] = cls._format_data(list_arguments["data_format"], result) return response
def _account_exists(cls, account): if account is None: raise ApplicationException("invalid account_id", 400) systems = (SystemPlatform.select().join( RHAccount, on=(SystemPlatform.rh_account_id == RHAccount.id)).where( RHAccount.name == account)) if not systems.exists(): raise ApplicationException("account_id must exist", 404)
def handle_patch(cls, **kwargs): """Update the 'status' field for a system/cve combination""" # pylint: disable=singleton-comparison data = kwargs['data'] try: in_inventory_id_list, in_cve_list, status_to_cves_map, status_text_to_cves_map = cls._prepare_data(data) rh_account = get_or_create_account() systems = (SystemPlatform.select(SystemPlatform.id) .where((SystemPlatform.rh_account_id == rh_account[0].id) & (SystemPlatform.opt_out == False))) # noqa: E712 if in_inventory_id_list is not None: systems = systems.where(SystemPlatform.inventory_id << in_inventory_id_list) rows_modified = set() # set statuses and their CVE lists for status_id, status_cve_list in status_to_cves_map.items(): status_id_update = (SystemVulnerabilities.update(status_id=status_id) .where((SystemVulnerabilities.system_id << systems) & (SystemVulnerabilities.cve_id << (CveMetadata.select(CveMetadata.id).where( CveMetadata.cve << status_cve_list)))) .returning(SystemVulnerabilities.id)) rows_modified.update([row.id for row in status_id_update]) cls._update_divergent_status_count(in_cve_list, rh_account[0].id) for status_text, status_cve_list in status_text_to_cves_map.items(): status_text_update = (SystemVulnerabilities.update(status_text=status_text) .where((SystemVulnerabilities.system_id << systems) & (SystemVulnerabilities.cve_id << (CveMetadata.select(CveMetadata.id).where( CveMetadata.cve << status_cve_list)))) .returning(SystemVulnerabilities.id)) rows_modified.update([row.id for row in status_text_update]) updated_details = (SystemVulnerabilities.select(SystemPlatform.inventory_id, CveMetadata.cve) .join(CveMetadata, on=(SystemVulnerabilities.cve_id == CveMetadata.id)) .join(SystemPlatform, on=(SystemVulnerabilities.system_id == SystemPlatform.id)) .where(SystemVulnerabilities.id << list(rows_modified)) .dicts()) updated = [] for updated_row in updated_details: updated.append({"inventory_id": updated_row["inventory_id"], "cve": updated_row["cve"]}) if not updated: # sysid/cve/acct combination does not exist return cls.format_exception('inventory_id/cve must exist and inventory_id must be visible to user', 404) except (IntegrityError, psycopg2IntegrityError, DataError) as value_error: # usually means bad-status-id LOGGER.error(str(value_error)) DB.rollback() return cls.format_exception(f'status_id={list(status_to_cves_map.keys())} is invalid', 400) except ValueError as value_error: LOGGER.exception('Error during setting status (ValueError):') DB.rollback() return cls.format_exception(f'status_text or other key value is invalid ({value_error})', 400) return {"updated": updated}
def _id_query(rh_account_id, list_args): selectables = [SystemPlatform.inventory_id, SystemPlatform.opt_out] # pylint: disable=singleton-comparison if list_args["sort"] and "cve_count" in list_args["sort"]: selectables.append( Case(None, (((SystemPlatform.opt_out == False), SystemPlatform.cve_count_cache), ), None).alias("cve_count")) query = (SystemPlatform.select(*selectables).where( SystemPlatform.rh_account_id == rh_account_id).where( SystemPlatform.last_evaluation.is_null(False) | SystemPlatform.advisor_evaluated.is_null(False)).where( SystemPlatform.when_deleted.is_null(True)).dicts()) return query
def _full_query(query_args): return (SystemPlatform.select( SystemPlatform.inventory_id, SystemPlatform.display_name, SystemPlatform.last_evaluation, SystemPlatform.advisor_evaluated.alias('rules_evaluation'), SystemPlatform.opt_out, SystemPlatform.cve_count_cache.alias("cve_count"), SystemPlatform.last_upload, SystemPlatform.stale_timestamp, SystemPlatform.stale_warning_timestamp, ).join( RHAccount, on=(RHAccount.id == SystemPlatform.rh_account_id)).where( RHAccount.name == query_args['rh_account_number']).where( SystemPlatform.last_evaluation.is_null(False) | SystemPlatform.advisor_evaluated.is_null(False)).where( SystemPlatform.when_deleted.is_null(True)).dicts())
def __init__(self, list_args, query_args, filter_args, parsed_args, uri): # pylint: disable=singleton-comparison query = (SystemPlatform.select( SystemPlatform.inventory_id, SystemPlatform.display_name, SystemPlatform.last_evaluation, SystemPlatform.advisor_evaluated.alias('rules_evaluation'), SystemPlatform.opt_out, SystemPlatform.cve_count_cache.alias("cve_count"), SystemPlatform.last_upload, SystemPlatform.stale_timestamp, SystemPlatform.stale_warning_timestamp, ).join( RHAccount, on=(RHAccount.id == SystemPlatform.rh_account_id)).where( RHAccount.name == query_args['rh_account_number']).where( SystemPlatform.last_evaluation.is_null(False) | SystemPlatform.advisor_evaluated.is_null(False)).dicts()) if 'opt_out' in filter_args and filter_args['opt_out']: query = query.where( SystemPlatform.opt_out == filter_args['opt_out']) else: query = query.where(SystemPlatform.opt_out == False) # noqa: E712 if 'stale' in filter_args and filter_args['stale']: query = query.where(SystemPlatform.stale == filter_args['stale']) else: query = query.where(SystemPlatform.stale == False) # noqa: E712 if 'uuid' in filter_args and filter_args['uuid']: query = query.where( SystemPlatform.inventory_id.contains(filter_args['uuid'])) sortable_columns = { 'id': SystemPlatform.id, 'cve_count': SystemPlatform.cve_count_cache, 'inventory_id': SystemPlatform.inventory_id, 'last_evaluation': SystemPlatform.last_evaluation, 'last_upload': SystemPlatform.last_upload, 'display_name': SystemPlatform.display_name, 'rules_evaluation': SystemPlatform.advisor_evaluated } default_sort_columns = ['-last_upload', 'id'] filterable_columns = {'display_name': SystemPlatform.display_name} super(SystemView, self).__init__(query, sortable_columns, default_sort_columns, filterable_columns, list_args, parsed_args, uri)
def get_system_count(rh_account, include_cyndi=True, filters=None, filters_args=None): """Get count of nonstale, nonoptouted, evaluated user systems""" # pylint: disable=singleton-comparison query = SystemPlatform.select(fn.COUNT(SystemPlatform.id).alias('count'))\ .where((SystemPlatform.rh_account_id == rh_account) & ((SystemPlatform.last_evaluation.is_null(False)) | (SystemPlatform.advisor_evaluated.is_null(False))) & ((SystemPlatform.opt_out == False) & (SystemPlatform.stale == False) & (SystemPlatform.when_deleted.is_null(True)))) if include_cyndi: query = query.join( InventoryHosts, JOIN.INNER, on=(SystemPlatform.inventory_id == InventoryHosts.id)) if filters: query = apply_filters(query, filters_args, filters, {}) return query.first().count
def __init__(self, list_args, query_args, filter_args, parsed_args, uri): query = (SystemPlatform.select( SystemPlatform.inventory_id, SystemPlatform.satellite_managed, SystemPlatform.last_evaluation, SystemPlatform.opt_out, SystemPlatform.cve_count_cache.alias("cve_count")).where( SystemPlatform.rh_account == query_args['rh_account_number']).where( SystemPlatform.last_evaluation.is_null(False)).dicts()) if query_args['hide_satellite_managed']: query = query.where(SystemPlatform.satellite_managed == False) # pylint: disable=singleton-comparison if 'opt_out' in filter_args and filter_args['opt_out']: query = query.where( SystemPlatform.opt_out == filter_args['opt_out']) else: query = query.where(SystemPlatform.opt_out == False) # pylint: disable=singleton-comparison sortable_columns = { 'cve_count': SystemPlatform.cve_count_cache, 'inventory_id': SystemPlatform.inventory_id, 'last_evaluation': SystemPlatform.last_evaluation } filterable_columns = {'inventory_id': SystemPlatform.inventory_id} super(SystemView, self).__init__(query, sortable_columns, filterable_columns, list_args, parsed_args, uri)
""" import math from common.peewee_model import SystemPlatform from manager.base import InvalidArgumentException from manager.list_view import ListView from .vuln_testcase import FlaskTestCase SORTABLE = { 'inventory_id': SystemPlatform.inventory_id, 'vmaas_json': SystemPlatform.vmaas_json, 'last_evaluation': SystemPlatform.last_evaluation } FILTERABLE = {} QUERY = (SystemPlatform.select(SystemPlatform.inventory_id)) URI = 'http://localhost:6666/api/v1/vulnerability/systems' TOTAL_ITEMS = 127 LIMIT = 5 LIST_ARGS = { 'page': 4, 'page_size': 5, 'pages': 66, 'opt_out': 'foo', 'limit': LIMIT, 'offset': 15, 'total_items': TOTAL_ITEMS } QUERY_ARGS = {
def handle_get(cls, **kwargs): # pylint: disable=too-many-statements,too-many-branches """Gets affected CVEs for a system""" inventory_id = kwargs['inventory_id'] args_desc = [ { 'arg_name': 'cvss_from', 'convert_func': None }, { 'arg_name': 'cvss_to', 'convert_func': None }, { 'arg_name': 'public_from', 'convert_func': dateutil.parser.parse }, { 'arg_name': 'public_to', 'convert_func': dateutil.parser.parse }, { 'arg_name': 'impact', 'convert_func': parse_int_list }, { 'arg_name': 'status_id', 'convert_func': parse_int_list }, { 'arg_name': 'business_risk_id', 'convert_func': parse_int_list }, { 'arg_name': 'rule_presence', 'convert_func': unique_bool_list }, { 'arg_name': 'show_advisories', 'convert_func': None }, { 'arg_name': 'advisory', 'convert_func': None }, { 'arg_name': 'rule_key', 'convert_func': None }, { 'arg_name': 'known_exploit', 'convert_func': unique_bool_list }, { 'arg_name': 'first_reported_from', 'convert_func': dateutil.parser.parse }, { 'arg_name': 'first_reported_to', 'convert_func': dateutil.parser.parse }, { 'arg_name': 'advisory_available', 'convert_func': unique_bool_list }, { 'arg_name': 'remediation', 'convert_func': parse_int_list }, ] args = cls._parse_arguments(kwargs, args_desc) list_arguments = cls._parse_list_arguments(kwargs) # check if advisory parameter comes with show_advisories parameter if 'advisory' in args and args['advisory'] and ( 'show_advisories' not in args or not args['show_advisories']): raise ApplicationException( "Advisory parameter shouldn't be used without show_advisories parameter", 400) # check if system was evaluated try: system = (SystemPlatform.select( SystemPlatform.last_evaluation, SystemPlatform.advisor_evaluated, SystemPlatform.opt_out).join( RHAccount, on=(SystemPlatform.rh_account_id == RHAccount.id)). where(SystemPlatform.inventory_id == inventory_id).where( RHAccount.name == connexion.context['user']).where( SystemPlatform.when_deleted.is_null(True)).get()) except DoesNotExist as exc: raise ApplicationException( 'inventory_id must exist and inventory_id must be visible to user', 404) from exc if system.last_evaluation is None and system.advisor_evaluated is None: raise ApplicationException( 'inventory_id exists but is not evaluated', 404) rh_account_id, _, _ = get_account_data(connexion.context['user']) cve_advisories = {} patch_access = None if 'show_advisories' in args and args[ 'show_advisories'] and 'advisory' in args and args['advisory']: raw_cve_names = (SystemVulnerabilities.select( CveMetadata.cve.alias('cve_name'), ).join( SystemPlatform, on=(SystemVulnerabilities.system_id == SystemPlatform.id) ).join( CveMetadata, on=(SystemVulnerabilities.cve_id == CveMetadata.id)).join( CveAccountData, JOIN.LEFT_OUTER, on=((CveAccountData.cve_id == CveMetadata.id) & (CveAccountData.rh_account_id == rh_account_id)) ).where( SystemVulnerabilities.rh_account_id == rh_account_id ).where( SystemPlatform.inventory_id == inventory_id)).dicts() cve_names = [cve['cve_name'] for cve in raw_cve_names] # get advisory data from PATCH cve_advisories, patch_access = cls._get_advisories_per_cve( cve_names, inventory_id, adv=args['advisory']) # filter advisories by advisory name cve_advisories = filter_by_advisory(args['advisory'], cve_advisories) cves_view = SystemCvesView(rh_account_id, list_arguments, {'inventory_id': inventory_id}, args, args, connexion.request.path, cls._ids_only, cve_advisories) cves = list(cves_view) elif 'show_advisories' in args and args['show_advisories'] and ( 'advisory' not in args or not args['advisory']): cves_view = SystemCvesView(rh_account_id, list_arguments, {'inventory_id': inventory_id}, args, args, connexion.request.path, cls._ids_only) cves = list(cves_view) cve_names = [ cve['cve_name'] if not cls._ids_only else cve['id'] for cve in cves ] # get advisory data from PATCH cve_advisories, patch_access = cls._get_advisories_per_cve( cve_names, inventory_id) else: cves_view = SystemCvesView(rh_account_id, list_arguments, {'inventory_id': inventory_id}, args, args, connexion.request.path, cls._ids_only) cves = list(cves_view) response = {} result = [] if not cls._ids_only: for cve in cves: if 'show_advisories' in args and args['show_advisories']: record = cls._build_attributes( cve, cve_advisories.get(cve['cve_name'], [])) result.append({ 'type': 'cve', 'id': cve['cve_name'], 'attributes': record }) else: record = cls._build_attributes(cve) result.append({ 'type': 'cve', 'id': cve['cve_name'], 'attributes': record }) else: result = cves response['meta'] = cves_view.get_metadata() response['meta'][ 'patch_access'] = patch_access.status if patch_access else None response['links'] = cves_view.get_pagination_links() response['data'] = cls._format_data(list_arguments["data_format"], result) return response
def handle_get(cls, **kwargs): # pylint: disable=singleton-comparison cve_count_by_severity = [] retval = { 'system_count': 0, 'cves_total': 0, 'cves_by_severity': { '0to3.9': { 'percentage': 0, 'count': 0 }, '4to7.9': { 'percentage': 0, 'count': 0 }, '8to10': { 'percentage': 0, 'count': 0 } }, 'recent_cves': { 'last7days': 0, 'last30days': 0, 'last90days': 0 }, 'top_cves': [] } rh_account = RHAccount.select(RHAccount.id).where(RHAccount.name == connexion.context['user']).first() if rh_account is None: return retval rh_account = rh_account.id retval['system_count'] = SystemPlatform.select(fn.COUNT(SystemPlatform.id).alias('count')).where( (SystemPlatform.rh_account_id == rh_account) & (SystemPlatform.last_evaluation.is_null(False)) & (SystemPlatform.opt_out == False)).first().count # noqa: E712 if retval['system_count'] == 0: return retval cves_total = CveAccountData.select(CveAccountData.cve_id).where((CveAccountData.rh_account_id == rh_account) & (CveAccountData.systems_affected > 0)) if cves_total.count() == 0: return retval retval['cves_total'] = cves_total.count() cve_details = CveMetadata.select(fn.COALESCE(CveMetadata.cvss3_score, CveMetadata.cvss2_score).alias('cvss'), CveMetadata.public_date).where(CveMetadata.id << cves_total) retval['cves_by_severity']['0to3.9']['count'] = cve_details.select_from(fn.COUNT('*').alias('count')).where(cve_details.c.cvss < 4).first().count retval['cves_by_severity']['4to7.9']['count'] = cve_details.select_from( fn.COUNT('*').alias('count')).where((cve_details.c.cvss >= 4) & (cve_details.c.cvss < 8)).first().count retval['cves_by_severity']['8to10']['count'] = cve_details.select_from(fn.COUNT('*').alias('count')).where(cve_details.c.cvss >= 8).first().count cve_count_by_severity = [v['count'] for v in retval['cves_by_severity'].values()] rounded_percentage = round_to_100_percent(cve_count_by_severity) for indx, keys in enumerate(retval['cves_by_severity']): retval['cves_by_severity'][keys]['percentage'] = rounded_percentage[indx] today = datetime.utcnow().date() retval['recent_cves']['last7days'] = cve_details.select_from( fn.COUNT('*').alias('count')).where(cve_details.c.public_date >= (today - timedelta(days=7))).first().count retval['recent_cves']['last30days'] = cve_details.select_from( fn.COUNT('*').alias('count')).where(cve_details.c.public_date >= (today - timedelta(days=30))).first().count retval['recent_cves']['last90days'] = cve_details.select_from( fn.COUNT('*').alias('count')).where(cve_details.c.public_date >= (today - timedelta(days=90))).first().count top_cves = CveMetadata.select(CveMetadata.cve, CveMetadata.cvss3_score, CveMetadata.cvss2_score, CveMetadata.description, CveAccountData.systems_affected).join(CveAccountData, on=(CveMetadata.id == CveAccountData.cve_id)).where( (CveAccountData.rh_account_id == rh_account) & (CveAccountData.systems_affected > 0)).order_by( CveAccountData.systems_affected.desc(), fn.COALESCE(CveMetadata.cvss3_score, CveMetadata.cvss2_score).desc(nulls='LAST'), CveMetadata.id).limit(3) for cve in top_cves: cve_dict = {} cve_dict['synopsis'] = cve.cve cve_dict['cvss2_score'] = str(cve.cvss2_score) cve_dict['cvss3_score'] = str(cve.cvss3_score) cve_dict['description'] = cve.description cve_dict['systems_affected'] = cve.cveaccountdata.systems_affected retval['top_cves'].append(cve_dict) return retval
def handle_get(cls, **kwargs): # pylint: disable=singleton-comparison retval = { 'system_count': 0, 'cves_total': 0, 'cves_by_severity': { '0to3.9': { 'percentage': 0, 'count': 0 }, '4to7.9': { 'percentage': 0, 'count': 0 }, '8to10': { 'percentage': 0, 'count': 0 } }, 'recent_cves': { 'last7days': 0, 'last30days': 0, 'last90days': 0 }, 'top_cves': [] } rh_account = RHAccount.select(RHAccount.id).where(RHAccount.name == connexion.context['user']).first() if rh_account is None: return retval rh_account = rh_account.id retval['system_count'] = SystemPlatform.select(fn.COUNT(SystemPlatform.id).alias('count')).where( (SystemPlatform.rh_account_id == rh_account) & ((SystemPlatform.last_evaluation.is_null(False)) | (SystemPlatform.advisor_evaluated.is_null(False))) & ((SystemPlatform.opt_out == False) & (SystemPlatform.stale == False))).first().count # noqa: E712 if retval['system_count'] == 0: return retval cves_total = CveAccountData.select(CveAccountData.cve_id).where((CveAccountData.rh_account_id == rh_account) & (CveAccountData.systems_affected > 0)) if cves_total.count() == 0: return retval retval['cves_total'] = cves_total.count() cve_details = CveMetadata.select(fn.COALESCE(CveMetadata.cvss3_score, CveMetadata.cvss2_score).alias('cvss'), CveMetadata.public_date).where(CveMetadata.id << cves_total) retval['cves_by_severity']['0to3.9']['count'] = cve_details.select_from(fn.COUNT('*').alias('count')).where(cve_details.c.cvss < 4).first().count retval['cves_by_severity']['4to7.9']['count'] = cve_details.select_from( fn.COUNT('*').alias('count')).where((cve_details.c.cvss >= 4) & (cve_details.c.cvss < 8)).first().count retval['cves_by_severity']['8to10']['count'] = cve_details.select_from(fn.COUNT('*').alias('count')).where(cve_details.c.cvss >= 8).first().count cve_count_by_severity = [v['count'] for v in retval['cves_by_severity'].values()] rounded_percentage = round_to_100_percent(cve_count_by_severity) for indx, keys in enumerate(retval['cves_by_severity']): retval['cves_by_severity'][keys]['percentage'] = rounded_percentage[indx] today = datetime.utcnow().date() retval['recent_cves']['last7days'] = cve_details.select_from( fn.COUNT('*').alias('count')).where(cve_details.c.public_date >= (today - timedelta(days=7))).first().count retval['recent_cves']['last30days'] = cve_details.select_from( fn.COUNT('*').alias('count')).where(cve_details.c.public_date >= (today - timedelta(days=30))).first().count retval['recent_cves']['last90days'] = cve_details.select_from( fn.COUNT('*').alias('count')).where(cve_details.c.public_date >= (today - timedelta(days=90))).first().count # The algorithm searches for CVEs with cvss score between 8 and 10, and then sort by a number of affected # systems if there are not 3 CVE in the 8 to 10 range, then it looks for CVEs in 4 to 8 range, sorted by a # number of systems affected. The high-end range check is exclusive that is why 11 here. cves_limit = 3 top_cves = cls._get_top_cves_by_cvss(8.0, 11, rh_account, limit=cves_limit) cls._build_top_cves(top_cves, retval) cves_count = top_cves.count() if cves_count < cves_limit: next_tier_top = cls._get_top_cves_by_cvss(4.0, 8.0, rh_account, limit=cves_limit-cves_count) cls._build_top_cves(next_tier_top, retval) next_cves_count = next_tier_top.count() if next_cves_count < (cves_limit - cves_count): last_tier_top = cls._get_top_cves_by_cvss(0.0, 4.0, rh_account, limit=cves_limit-(cves_count+next_cves_count)) cls._build_top_cves(last_tier_top, retval) return retval
def handle_get(cls, **kwargs): """Gets affected CVEs for a system""" inventory_id = kwargs['inventory_id'] args_desc = [{ 'arg_name': 'cvss_from', 'convert_func': None }, { 'arg_name': 'cvss_to', 'convert_func': None }, { 'arg_name': 'public_from', 'convert_func': dateutil.parser.parse }, { 'arg_name': 'public_to', 'convert_func': dateutil.parser.parse }, { 'arg_name': 'impact', 'convert_func': parse_int_list }, { 'arg_name': 'status_id', 'convert_func': parse_int_list }, { 'arg_name': 'business_risk_id', 'convert_func': parse_int_list }, { 'arg_name': 'security_rule', 'convert_func': None }, { 'arg_name': 'rule_presence', 'convert_func': unique_bool_list }] args = cls._parse_arguments(kwargs, args_desc) list_arguments = cls._parse_list_arguments(kwargs) # check if system was evaluated try: system = (SystemPlatform.select( SystemPlatform.last_evaluation, SystemPlatform.advisor_evaluated, SystemPlatform.opt_out).join( RHAccount, on=(SystemPlatform.rh_account_id == RHAccount.id)). where(SystemPlatform.inventory_id == inventory_id).where( RHAccount.name == connexion.context['user']).where( SystemPlatform.when_deleted.is_null(True)).get()) except DoesNotExist: raise ApplicationException( 'inventory_id must exist and inventory_id must be visible to user', 404) if system.last_evaluation is None and system.advisor_evaluated is None: raise ApplicationException( 'inventory_id exists but is not evaluated', 404) cves_view = SystemCvesView( list_arguments, { "rh_account_number": connexion.context['user'], 'inventory_id': inventory_id }, args, args, connexion.request.path, cls._ids_only) response = {} result = [] if not cls._ids_only: for cve in cves_view: record = {} record['synopsis'] = cve['cve_name'] record['public_date'] = cve['public_date'].isoformat( ) if cve['public_date'] else None record['impact'] = cve['impact'] record['description'] = cve['cve_description'] # Store everything we know about CVSS - maybe UI needs to decide what to show record['cvss2_score'] = str( cve['cvss2_score'] ) if cve['cvss2_score'] is not None else None record['cvss3_score'] = str( cve['cvss3_score'] ) if cve['cvss3_score'] is not None else None # Store status information record['cve_status_id'] = cve['cve_status_id'] record['status_id'] = cve['status_id'] record['status'] = cve['status_name'] record['status_text'] = cve['status_text'] record['cve_status_text'] = cve['cve_status_text'] record['business_risk'] = cve['business_risk'] record['business_risk_id'] = cve['business_risk_id'] record['business_risk_text'] = cve['business_risk_text'] record['reporter'] = ( reporter.VMAAS.value if not cve['when_mitigated'] else 0) | (reporter.RULE.value if cve['rule_active'] else 0) if cve['rule_active']: record['rule'] = { 'rule_id': cve['rule_id'], 'description': cve['description_text'], 'summary': cve['summary_text'], 'generic': cve['generic_text'], 'reboot_required': cve['reboot_required'], 'playbook_count': cve['playbook_count'], 'change_risk': cve['change_risk'], 'kbase_node_id': cve['kbase_node_id'], } else: record['rule'] = None result.append({ 'type': 'cve', 'id': cve['cve_name'], 'attributes': record }) else: for cve in cves_view: result.append(cve['cve_name']) response['meta'] = cves_view.get_metadata() response['meta']['opt_out'] = system.opt_out response['links'] = cves_view.get_pagination_links() response['data'] = cls._format_data(list_arguments["data_format"], result) return response
def handle_get(cls, **kwargs): # pylint: disable=too-many-statements """Gets affected CVEs for a system""" inventory_id = kwargs['inventory_id'] args_desc = [{'arg_name': 'cvss_from', 'convert_func': None}, {'arg_name': 'cvss_to', 'convert_func': None}, {'arg_name': 'public_from', 'convert_func': dateutil.parser.parse}, {'arg_name': 'public_to', 'convert_func': dateutil.parser.parse}, {'arg_name': 'impact', 'convert_func': parse_int_list}, {'arg_name': 'status_id', 'convert_func': parse_int_list}, {'arg_name': 'business_risk_id', 'convert_func': parse_int_list}, {'arg_name': 'security_rule', 'convert_func': None}, {'arg_name': 'rule_presence', 'convert_func': unique_bool_list}, {'arg_name': 'show_advisories', 'convert_func': None}, {'arg_name': 'advisory', 'convert_func': None}] args = cls._parse_arguments(kwargs, args_desc) list_arguments = cls._parse_list_arguments(kwargs) # check if system was evaluated try: system = (SystemPlatform.select( SystemPlatform.last_evaluation, SystemPlatform.advisor_evaluated, SystemPlatform.opt_out) .join(RHAccount, on=(SystemPlatform.rh_account_id == RHAccount.id)) .where(SystemPlatform.inventory_id == inventory_id) .where(RHAccount.name == connexion.context['user']) .where(SystemPlatform.when_deleted.is_null(True)) .get()) except DoesNotExist: raise ApplicationException('inventory_id must exist and inventory_id must be visible to user', 404) if system.last_evaluation is None and system.advisor_evaluated is None: raise ApplicationException('inventory_id exists but is not evaluated', 404) cves_view = SystemCvesView(list_arguments, {"rh_account_number": connexion.context['user'], 'inventory_id': inventory_id}, args, args, connexion.request.path, cls._ids_only) patch_access = None cve_advisories = {} cve_advisories_filtered = {} if 'show_advisories' in args and args['show_advisories'] is True: cve_names = [] for cve in cves_view: cve_names.append(cve['cve_name']) cve_advisories, patch_access = cls._get_advisories_per_cve(cve_names, inventory_id) if 'advisory' in args and args['advisory']: cve_advisories_filtered = {cve: advisories for cve, advisories in cve_advisories.items() if args['advisory'] in advisories} response = {} result = [] if not cls._ids_only: for cve in cves_view: if 'advisory' in args and args['advisory']: if cve['cve_name'] in cve_advisories_filtered: record = cls._build_attributes(cve, cve_advisories_filtered) result.append({'type': 'cve', 'id': cve['cve_name'], 'attributes': record}) else: record = cls._build_attributes(cve, cve_advisories) result.append({'type': 'cve', 'id': cve['cve_name'], 'attributes': record}) else: for cve in cves_view: result.append(cve['cve_name']) response['meta'] = cves_view.get_metadata() response['meta']['opt_out'] = system.opt_out response['meta']['patch_access'] = patch_access response['links'] = cves_view.get_pagination_links() response['data'] = cls._format_data(list_arguments["data_format"], result) return response