Example #1
0
    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}
Example #2
0
 def _cve_exists(synopsis):
     try:
         (CveMetadata.select(CveMetadata.cve)
          .where(CveMetadata.cve == synopsis)
          .get())
     except DoesNotExist:
         raise ApplicationException('No such CVE ID', 404)
Example #3
0
    def __init__(self, list_args, cve_list, uri):
        cve_list = [remove_str_nulls(elem) for elem in cve_list]
        query = (CveMetadata.select(CveMetadata.cve,
                                    fn.COALESCE(CveMetadata.cvss3_score, CveMetadata.cvss2_score).alias('cvss_score'),
                                    CveImpact.name.alias('impact'))
                 .join(CveImpact, on=(CveMetadata.impact_id == CveImpact.id))
                 .where(CveMetadata.cve.in_(cve_list))
                 .dicts())

        sortable_columns = {
            'synopsis': CVE_SYNOPSIS_SORT,
            # This assumes we only show one score, and that cvss3 wins over cvss2
            'cvss_score': Case(None, ((CveMetadata.cvss3_score.is_null(True), CveMetadata.cvss2_score),), \
                               CveMetadata.cvss3_score),
            'impact_id': CveMetadata.impact_id,
            'impact': CveMetadata.impact_id,
        }
        filterable_columns = {
            'synopsis': CveMetadata.cve,
        }
        default_sort_columns = {
            'default': 'synopsis'
        }

        super().__init__(query, sortable_columns, default_sort_columns, filterable_columns, {}, list_args, [], uri)
Example #4
0
 def _get_cve_details(synopsis):
     try:
         data = (CveMetadata.select(CveImpact.name.alias('impact'), CveMetadata.cve.alias('synopsis'),
                                    CveMetadata.description, CveMetadata.cvss2_metrics,
                                    CveMetadata.cvss2_score, CveMetadata.cvss3_score,
                                    CveMetadata.cvss3_metrics, CveMetadata.modified_date,
                                    CveMetadata.public_date, CveMetadata.redhat_url,
                                    CveMetadata.secondary_url, CveMetadata.id)
                 .join(CveImpact, on=(CveMetadata.impact_id == CveImpact.id))
                 .where(CveMetadata.cve == synopsis)).dicts()[0]
         rules_map = get_rules_for_cves([data['id']])
         return {
             "cvss2_metrics": str_or_none(data['cvss2_metrics']),
             "cvss2_score": str_or_none(data['cvss2_score']),
             "cvss3_metrics": str_or_none(data['cvss3_metrics']),
             "cvss3_score": str_or_none(data['cvss3_score']),
             "description": data['description'],
             "impact": data['impact'],
             "public_date": format_datetime(data['public_date']),
             "modified_date": format_datetime(data['modified_date']),
             "redhat_url": data['redhat_url'],
             "rules": rules_map.get(data['id'], []),
             "secondary_url": data['secondary_url'],
             "synopsis": data['synopsis'],
         }
     except IndexError:
         raise ApplicationException('No such CVE ID', 404)
Example #5
0
 def _get_top_cves_by_cvss(cvss_from, cvss_to, count_query, limit=3):
     # pylint: disable=singleton-comparison
     rules = (CveRuleMapping.select(
         CveRuleMapping.cve_id, CveRuleMapping.rule_id).join(
             InsightsRule,
             on=((CveRuleMapping.rule_id == InsightsRule.id)
                 & (InsightsRule.active == True) &
                 (~InsightsRule.rule_only))))
     return (CveMetadata.select(
         CveMetadata.cve, CveMetadata.cvss3_score, CveMetadata.cvss2_score,
         CveMetadata.description, CveMetadata.exploits,
         count_query.c.systems_affected_.alias("systems_affected"),
         fn.ARRAY_AGG(rules.c.rule_id).alias('has_rule')).join(
             count_query,
             on=(CveMetadata.id == count_query.c.cve_id_)).join(
                 rules,
                 JOIN.LEFT_OUTER,
                 on=(CveMetadata.id == rules.c.cve_id)).where(
                     (fn.COALESCE(CveMetadata.cvss3_score,
                                  CveMetadata.cvss2_score) >= cvss_from)
                     & (fn.COALESCE(CveMetadata.cvss3_score,
                                    CveMetadata.cvss2_score) < cvss_to)).
             order_by(
                 count_query.c.systems_affected_.desc(),
                 fn.COALESCE(CveMetadata.cvss3_score,
                             CveMetadata.cvss2_score).desc(nulls='LAST'),
                 CveMetadata.id).group_by(
                     CveMetadata.id, CveMetadata.cve,
                     CveMetadata.cvss3_score, CveMetadata.cvss2_score,
                     CveMetadata.description,
                     count_query.c.systems_affected_.alias(
                         "systems_affected")).limit(limit).dicts())
 def _full_query(rh_account_id, join_type, count_subquery):
     return (CveMetadata.select(
         CveMetadata.id.alias("cve_id"), CveMetadata.cve.alias("cve_name"),
         CveMetadata.cvss3_score, CveMetadata.cvss2_score,
         CveMetadata.impact_id, CveMetadata.public_date,
         CveMetadata.description.alias("cve_description"),
         CveMetadata.exploits,
         fn.COALESCE(CveAccountData.business_risk_id,
                     0).alias("business_risk_id"),
         CveAccountData.business_risk_text.alias("business_risk_text"),
         fn.COALESCE(BusinessRisk.name,
                     DEFAULT_BUSINESS_RISK).alias("business_risk"),
         fn.COALESCE(CveAccountData.status_id, 0).alias("status_id"),
         CveAccountData.status_text.alias("status_text"),
         fn.COALESCE(Status.name, DEFAULT_STATUS).alias("status"),
         fn.COALESCE(count_subquery.c.systems_affected_,
                     0).alias("systems_affected"),
         fn.COALESCE(
             count_subquery.c.systems_status_divergent_,
             0).alias("systems_status_divergent")).join(
                 count_subquery,
                 join_type,
                 on=(CveMetadata.id == count_subquery.c.cve_id_)).join(
                     CveAccountData,
                     JOIN.LEFT_OUTER,
                     on=((CveMetadata.id == CveAccountData.cve_id)
                         &
                         (CveAccountData.rh_account_id == rh_account_id))).
             join(BusinessRisk,
                  JOIN.LEFT_OUTER,
                  on=(CveAccountData.business_risk_id == BusinessRisk.id
                      )).join(Status,
                              JOIN.LEFT_OUTER,
                              on=(CveAccountData.status_id == Status.id)))
Example #7
0
    def _update_divergent_status_count(in_cve_list, rh_account_id):
        """Update cached count how many systems-CVE pairs have different status than CVE-level status is"""

        cve_ids = CveMetadata.select(CveMetadata.id).where(CveMetadata.cve << in_cve_list)
        # pylint: disable=singleton-comparison
        div_counts = (SystemVulnerabilities.select(SystemVulnerabilities.cve_id,
                                                   fn.Count(SystemVulnerabilities.id).alias('systems_status_divergent'))
                      .join(SystemPlatform, on=(SystemVulnerabilities.system_id == SystemPlatform.id))
                      .where(SystemPlatform.rh_account_id == rh_account_id)
                      .where(SystemPlatform.opt_out == False)  # noqa: E712
                      .where(SystemVulnerabilities.cve_id << cve_ids)
                      .where(SystemVulnerabilities.when_mitigated.is_null(True))
                      .where(SystemVulnerabilities.status_id != fn.COALESCE(
                          (CveAccountData.select(CveAccountData.status_id)
                           .where(CveAccountData.rh_account_id == rh_account_id)
                           .where(CveAccountData.cve_id == SystemVulnerabilities.cve_id)), 0))
                      .group_by(SystemVulnerabilities.cve_id))

        divergent_systems = {}
        for cve_id in cve_ids:
            divergent_systems[cve_id] = 0
        for div_count in div_counts:
            divergent_systems[div_count.cve_id] = div_count.systems_status_divergent

        if divergent_systems:
            values_to_update = ValuesList([(cve_id, systems_status_divergent) for cve_id, systems_status_divergent
                                           in divergent_systems.items()],
                                          columns=('cve_id', 'systems_status_divergent'))
            query = (CveAccountData.update(systems_status_divergent=values_to_update.c.systems_status_divergent)
                     .from_(values_to_update)
                     .where(CveAccountData.cve_id == values_to_update.c.cve_id)
                     .where(CveAccountData.rh_account_id == rh_account_id))
            query.execute()
    def handle_patch(cls, **kwargs):
        """Set status for a CVE"""
        data = kwargs['data']
        cve_list = data['cve']
        if isinstance(cve_list, str):
            cve_list = [cve_list]

        values = {}
        updated = []
        if 'status_id' in data:
            values['status_id'] = data['status_id']
        if 'status_text' in data:
            try:
                values['status_text'] = data['status_text'].strip() \
                                        if data['status_text'].strip() else None
            except AttributeError:
                values['status_text'] = None
        if not values:
            return cls.format_exception(
                'At least one of the "status_id" or "status_text" parameters is required.', 400)
        try:
            to_insert = []
            cves = CveMetadata.select(CveMetadata.id, CveMetadata.cve).where(CveMetadata.cve << cve_list)
            rh_account = get_or_create_account()
            for cve in cves:
                updated.append(cve.cve)
                if 'status_id' in data:
                    # refresh number of divergent statuses in CVE-system pairs
                    # pylint: disable=singleton-comparison
                    query = (SystemVulnerabilities.select(fn.Count(SystemVulnerabilities.id).alias('systems'))
                             .join(SystemPlatform, on=(SystemVulnerabilities.system_id == SystemPlatform.id))
                             .join(InsightsRule, JOIN.LEFT_OUTER, on=(InsightsRule.id == SystemVulnerabilities.rule_id))
                             .where(SystemPlatform.rh_account_id == rh_account[0].id)
                             .where((SystemPlatform.opt_out == False)  # noqa: E712
                                    & (SystemPlatform.stale == False)  # noqa: E712
                                    & (SystemPlatform.when_deleted.is_null(True)))
                             .where(SystemVulnerabilities.cve_id == cve.id)
                             .where((SystemVulnerabilities.mitigation_reason.is_null(True)) | (InsightsRule.active == False))
                             .where((SystemVulnerabilities.when_mitigated.is_null(True)) | (InsightsRule.active == True))
                             .where(SystemVulnerabilities.status_id != values.get('status_id', 0))
                             .dicts())
                    values['systems_status_divergent'] = query[0]['systems']

                to_insert.append((cve.id, rh_account[0].id, values.get('status_id', 0),
                                  values.get('status_text', None), values.get('systems_status_divergent', 0)))
            if not to_insert:
                return cls.format_exception('At least one given CVE must exist', 404)
            (CveAccountData.insert_many(to_insert, fields=cls._fields)
             .on_conflict(conflict_target=cls._conflict_target, preserve=[], update=values).execute())
        except (IntegrityError, psycopg2IntegrityError, DataError):
            # usually means bad status
            LOGGER.exception('Error during setting status (IntegrityError):')
            DB.rollback()
            return cls.format_exception(f"status_id={data['status_id']} 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}
Example #9
0
 def _get_advisories_per_cve_from_db(synopsis: str):
     """Get advisories per CVE from DB"""
     try:
         data = (CveMetadata.select(CveMetadata.advisories_list)
                 .where(CveMetadata.cve == synopsis)).dicts()[0]['advisories_list']
     except IndexError:
         data = []
     return data
    def handle_patch(cls, **kwargs):
        """Set status for a CVE"""
        data = kwargs['data']
        cve_list = data['cve']
        if isinstance(cve_list, str):
            cve_list = [cve_list]

        values = {}
        updated = []
        if 'status_id' in data:
            values['status_id'] = data['status_id']
        if 'status_text' in data:
            try:
                values['status_text'] = data['status_text'].strip() \
                    if data['status_text'].strip() else None
            except AttributeError:
                values['status_text'] = None
        if not values:
            return cls.format_exception(
                'At least one of the "status_id" or "status_text" parameters is required.',
                400)
        try:
            to_insert = []
            cves = CveMetadata.select(
                CveMetadata.id,
                CveMetadata.cve).where(CveMetadata.cve << cve_list)
            rh_account = get_or_create_account()
            for cve in cves:  # pylint: disable=not-an-iterable
                updated.append(cve.cve)
                to_insert.append(
                    (cve.id, rh_account[0].id, values.get('status_id', 0),
                     values.get('status_text', None)))
            if not to_insert:
                return cls.format_exception(
                    'At least one given CVE must exist', 404)
            (CveAccountData.insert_many(
                to_insert, fields=cls._fields).on_conflict(
                    conflict_target=cls._conflict_target,
                    preserve=[],
                    update=values).execute())
            RHAccount.update(
                last_status_change=datetime.now(timezone.utc)).where(
                    RHAccount.id == rh_account[0].id).execute()
        except (IntegrityError, psycopg2IntegrityError, DataError):
            # usually means bad status
            LOGGER.exception('Error during setting status (IntegrityError):')
            DB.rollback()
            return cls.format_exception(
                f"status_id={data['status_id']} 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}
Example #11
0
    def handle_patch(cls, **kwargs):
        """Set business risk for a CVE"""
        data = kwargs['data']
        cve_list = data['cve']
        if isinstance(cve_list, str):
            cve_list = [cve_list]

        values = {}
        updated = []
        if 'business_risk_id' in data:
            values['business_risk_id'] = data['business_risk_id']
        if 'business_risk_text' in data:
            try:
                values['business_risk_text'] = data['business_risk_text'].strip() \
                                               if data['business_risk_text'].strip() else None
            except AttributeError:
                values['business_risk_text'] = None
        if not values:
            return cls.format_exception(
                'At least one of the "business_risk_id" or "business_risk_text" parameters is required.',
                400)
        try:
            to_insert = []
            cves = CveMetadata.select(
                CveMetadata.id,
                CveMetadata.cve).where(CveMetadata.cve << cve_list)
            rh_account = get_or_create_account()
            for cve in cves:
                updated.append(cve.cve)
                to_insert.append((cve.id, rh_account[0].id,
                                  values.get('business_risk_id', 0),
                                  values.get('business_risk_text', None)))
            if not to_insert:
                return cls.format_exception(
                    'At least one given CVE must exist', 404)
            (CveAccountData.insert_many(
                to_insert, fields=cls._fields).on_conflict(
                    conflict_target=cls._conflict_target,
                    preserve=[],
                    update=values).execute())
        except (IntegrityError, psycopg2IntegrityError, DataError):
            # usually means bad business_risk_id
            LOGGER.exception(
                'Error during setting business risk (IntegrityError):')
            DB.rollback()
            return cls.format_exception(
                f'business_risk_id=%s is invalid' % data['business_risk_id'],
                400)
        except ValueError as value_error:
            LOGGER.exception(
                'Error during setting business risk (ValueError):')
            DB.rollback()
            return cls.format_exception(
                f'business_risk_text or other key value is invalid ({value_error})',
                400)
        return {'updated': updated}
Example #12
0
 def _get_top_cves_by_cvss(cvss_from, cvss_to, rh_account, limit=3):
     return 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) & (
             (fn.COALESCE(CveMetadata.cvss3_score, CveMetadata.cvss2_score) >= cvss_from) &
             (fn.COALESCE(CveMetadata.cvss3_score, CveMetadata.cvss2_score) < cvss_to)))\
         .order_by(CveAccountData.systems_affected.desc(),
                   fn.COALESCE(CveMetadata.cvss3_score, CveMetadata.cvss2_score).desc(nulls='LAST'), CveMetadata.id)\
         .limit(limit)
Example #13
0
 def _build_update_condition(systems, status_cve_list):
     # pylint: disable=singleton-comparison
     return ((SystemVulnerabilities.system_id << systems) &
             (SystemVulnerabilities.cve_id << (CveMetadata.select(
                 CveMetadata.id).where(CveMetadata.cve << status_cve_list)))
             & ((SystemVulnerabilities.mitigation_reason.is_null(True)) |
                (SystemVulnerabilities.rule_id << (InsightsRule.select(
                    InsightsRule.id).where(InsightsRule.active == True)))) &
             ((SystemVulnerabilities.when_mitigated.is_null(True)) |
              (SystemVulnerabilities.rule_id <<
               (InsightsRule.select(InsightsRule.id).where(
                   InsightsRule.active == True)))  # noqa: E712
              ))
Example #14
0
def get_advisories_per_cve_from_db(synopsis: str):
    """Get advisories per CVE from DB
        Args:
            synopsis (str): cve name
        Returns:
            list: List with advisories for CVE
    """
    try:
        query = (CveMetadata.select(
            CveMetadata.advisories_list).where(CveMetadata.cve == synopsis))
        data = query.dicts()[0]['advisories_list']
    except IndexError:
        data = []
    return data or []
    def handle_patch(cls, **kwargs):
        """Set status for a CVE"""
        data = kwargs['data']
        cve_list = data['cve']
        if isinstance(cve_list, str):
            cve_list = [cve_list]

        values = {}
        updated = []
        if 'status_id' in data:
            values['status_id'] = data['status_id']
        if 'status_text' in data:
            values['status_text'] = data['status_text'].strip(
            ) if data['status_text'].strip() else None
        if not values:
            return cls.format_exception(
                'At least one of the "status_id" or "status_text" parameters is required.',
                400)
        try:
            to_insert = []
            cves = CveMetadata.select(
                CveMetadata.id,
                CveMetadata.cve).where(CveMetadata.cve << cve_list)
            rh_account = RHAccount.select(RHAccount.id).where(
                RHAccount.name == connexion.context['user'])
            for cve in cves:
                updated.append(cve.cve)
                to_insert.append(
                    (cve.id, rh_account[0].id, values.get('status_id', 0),
                     values.get('status_text', None)))
            if not to_insert:
                return cls.format_exception(
                    'At least one given CVE must exist', 404)
            (CveAccountData.insert_many(
                to_insert, fields=cls._fields).on_conflict(
                    conflict_target=cls._conflict_target,
                    preserve=[],
                    update=values).execute())
        except (IntegrityError, psycopg2IntegrityError):
            # usually means bad status
            LOGGER.exception('Error during setting status (IntegrityError):')
            DB.rollback()
            return cls.format_exception(
                f'status_id=%s is invalid' % data['status_id'], 400)
        except ValueError as value_error:
            LOGGER.exception('Error during setting status (ValueError):')
            DB.rollback()
            return cls.format_exception(str(value_error), 500)
        return {'updated': updated}
    def _get_cve_details(synopsis, args):
        try:
            data = (CveMetadata.select(
                CveImpact.name.alias('impact'),
                CveMetadata.cve.alias('synopsis'), CveMetadata.description,
                CveMetadata.cvss2_metrics, CveMetadata.cvss2_score,
                CveMetadata.cvss3_score, CveMetadata.cvss3_metrics,
                CveMetadata.modified_date, CveMetadata.celebrity_name,
                CveMetadata.public_date, CveMetadata.redhat_url,
                CveMetadata.secondary_url, CveMetadata.id,
                CveMetadata.advisories_list, CveMetadata.exploits).join(
                    CveImpact,
                    on=(CveMetadata.impact_id == CveImpact.id)).where(
                        CveMetadata.cve == synopsis)).dicts()[0]
            rules_map = get_rules_for_cves([data['id']],
                                           connexion.context['user'])
            retval = {
                "celebrity_name": str_or_none(data['celebrity_name']),
                "cvss2_metrics": str_or_none(data['cvss2_metrics']),
                "cvss2_score": str_or_none(data['cvss2_score']),
                "cvss3_metrics": str_or_none(data['cvss3_metrics']),
                "cvss3_score": str_or_none(data['cvss3_score']),
                "description": data['description'],
                "impact": data['impact'],
                "public_date": format_datetime(data['public_date']),
                "modified_date": format_datetime(data['modified_date']),
                "redhat_url": data['redhat_url'],
                "rules": rules_map.get(data['id'], []),
                "secondary_url": data['secondary_url'],
                "synopsis": data['synopsis'],
                "known_exploit": bool(data['exploits'])
            }

            advisories_list = [] if data.get(
                'advisories_list') is None else data['advisories_list']
            if 'show_advisories_details' in args and args[
                    'show_advisories_details'] is True and advisories_list:
                retval["advisories_list"] = GetCves._patch_request_advisories(
                    advisories_list)
            else:
                retval["advisories_list"] = advisories_list
        except IndexError as exc:
            raise ApplicationException('No such CVE ID', 404) from exc
        return retval
    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
Example #18
0
    def handle_get(cls, **kwargs):
        # pylint: disable=singleton-comparison, too-many-branches, too-many-statements
        retval = {
            'system_count': 0,
            'cves_total': 0,
            'cves_by_severity': {
                '0to3.9': {
                    'percentage': 0,
                    'count': 0,
                    'known_exploit_count': 0
                },
                '4to7.9': {
                    'percentage': 0,
                    'count': 0,
                    'known_exploit_count': 0
                },
                '8to10': {
                    'percentage': 0,
                    'count': 0,
                    'known_exploit_count': 0
                },
                'na': {
                    'percentage': 0,
                    'count': 0,
                    'known_exploit_count': 0
                }
            },
            'recent_cves': {
                'last7days': 0,
                'last30days': 0,
                'last90days': 0
            },
            'rules_total': 0,
            'rules_by_severity': {
                1: {
                    'rule_count': 0,
                    'systems_affected': 0
                },
                2: {
                    'rule_count': 0,
                    'systems_affected': 0
                },
                3: {
                    'rule_count': 0,
                    'systems_affected': 0
                },
                4: {
                    'rule_count': 0,
                    'systems_affected': 0
                },
            },
            'top_cves': [],
            'top_rules': [],
        }
        rh_account, cve_cache_from, cve_cache_keepalive = get_account_data(
            connexion.context['user'])
        if rh_account is None:
            return retval
        retval['system_count'] = get_system_count(rh_account)
        if retval['system_count'] == 0:
            return retval

        # API using cache, set keepalive for account to enable maintaining cache
        update_cve_cache_keepalive(rh_account, cve_cache_keepalive)

        # Use cache if not disabled + cache exists
        if not DISABLE_ACCOUNT_CACHE and cve_cache_from:
            count_query = (CveAccountCache.select(
                CveAccountCache.cve_id.alias("cve_id_"),
                CveAccountCache.systems_affected.alias("systems_affected_")).
                           where(CveAccountCache.rh_account_id == rh_account))
        else:
            count_query = (
                SystemVulnerabilities.select(
                    SystemVulnerabilities.cve_id.alias("cve_id_"),
                    fn.Count(
                        SystemVulnerabilities.id).alias("systems_affected_")).
                join(SystemPlatform,
                     on=(SystemVulnerabilities.system_id == SystemPlatform.id)
                     & (SystemPlatform.rh_account_id == rh_account) &
                     (SystemPlatform.opt_out == False) &
                     (SystemPlatform.stale == False) &
                     (SystemPlatform.when_deleted.is_null(True))).where(
                         SystemVulnerabilities.rh_account_id == rh_account).
                where((SystemVulnerabilities.mitigation_reason.is_null(True))
                      | (SystemVulnerabilities.rule_id << InsightsRule.select(
                          InsightsRule.id).where((InsightsRule.active == False)
                                                 & (~InsightsRule.rule_only))))
                .where((SystemVulnerabilities.when_mitigated.is_null(True))
                       | (SystemVulnerabilities.rule_id << InsightsRule.select(
                           InsightsRule.id).where(
                               (InsightsRule.active == True) &
                               (~InsightsRule.rule_only)))).group_by(
                                   SystemVulnerabilities.cve_id))
            count_query = cyndi_join(count_query)

        cve_query = (CveMetadata.select(
            CveMetadata.id.alias("cve_id"),
            fn.COALESCE(CveMetadata.cvss3_score,
                        CveMetadata.cvss2_score).alias('cvss_score'),
            CveMetadata.public_date, CveMetadata.exploits).join(
                count_query,
                JOIN.INNER,
                on=(CveMetadata.id == count_query.c.cve_id_)).dicts())

        cve_data = [(cve["cvss_score"], cve["public_date"], cve["exploits"])
                    for cve in cve_query]

        cves_total = len(cve_data)
        if cves_total == 0:
            return retval

        retval['cves_total'] = cves_total

        today = datetime.now(timezone.utc).replace(
            hour=0, minute=0, second=0, microsecond=0)  # offset-aware
        last7 = today - timedelta(days=7)
        last30 = today - timedelta(days=30)
        last90 = today - timedelta(days=90)

        for cvss_score, public_date, exploits in cve_data:
            if cvss_score is None:
                retval["cves_by_severity"]["na"]["count"] += 1
                if exploits:
                    retval["cves_by_severity"]["na"][
                        "known_exploit_count"] += 1
            elif cvss_score < 4:
                retval["cves_by_severity"]["0to3.9"]["count"] += 1
                if exploits:
                    retval["cves_by_severity"]["0to3.9"][
                        "known_exploit_count"] += 1
            elif 4 <= cvss_score < 8:
                retval["cves_by_severity"]["4to7.9"]["count"] += 1
                if exploits:
                    retval["cves_by_severity"]["4to7.9"][
                        "known_exploit_count"] += 1
            elif cvss_score >= 8:
                retval["cves_by_severity"]["8to10"]["count"] += 1
                if exploits:
                    retval["cves_by_severity"]["8to10"][
                        "known_exploit_count"] += 1

            if public_date is not None:
                if public_date >= last7:
                    retval["recent_cves"]["last7days"] += 1
                if public_date >= last30:
                    retval["recent_cves"]["last30days"] += 1
                if public_date >= last90:
                    retval["recent_cves"]["last90days"] += 1

        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]

        # 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,
                                             count_query,
                                             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,
                                                      count_query,
                                                      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,
                    count_query,
                    limit=cves_limit - (cves_count + next_cves_count))
                cls._build_top_cves(last_tier_top, retval)

        rules_breakdown = (SystemVulnerabilities.select(
            fn.COUNT(fn.Distinct(InsightsRule.id)).alias('rule_count'),
            InsightsRule.rule_impact.alias('severity'),
            fn.COUNT(fn.Distinct(
                SystemVulnerabilities.system_id)).alias('systems_affected')
        ).join(
            InsightsRule,
            on=(SystemVulnerabilities.rule_id == InsightsRule.id)
        ).join(
            SystemPlatform,
            on=(SystemVulnerabilities.system_id == SystemPlatform.id) &
            (SystemPlatform.rh_account_id == rh_account) &
            (SystemPlatform.opt_out == False) & (SystemPlatform.stale == False)
            & (SystemPlatform.when_deleted.is_null(True)) &
            (SystemPlatform.last_evaluation.is_null(False)
             | SystemPlatform.advisor_evaluated.is_null(False))).where(
                 SystemVulnerabilities.rh_account_id == rh_account).where(
                     (SystemVulnerabilities.mitigation_reason.is_null(True))
                     & (SystemVulnerabilities.rule_id << InsightsRule.select(
                         InsightsRule.id).where(
                             (InsightsRule.active == True)
                             & (~InsightsRule.rule_only)))).group_by(
                                 InsightsRule.rule_impact).dicts())

        rules_breakdown = cyndi_join(rules_breakdown)

        for section in rules_breakdown:
            retval['rules_by_severity'][
                section['severity']]['rule_count'] = section['rule_count']
            retval['rules_by_severity'][section['severity']][
                'systems_affected'] = section['systems_affected']

        retval['rules_total'] = sum(
            [item['rule_count'] for item in rules_breakdown])

        top_rules = (SystemVulnerabilities.select(
            InsightsRule.name.alias('rule_id'),
            InsightsRule.description_text.alias('name'),
            InsightsRule.rule_impact.alias('severity'),
            InsightsRule.summary_text.alias('description'),
            fn.COUNT(fn.Distinct(
                SystemVulnerabilities.system_id)).alias('systems_affected'),
            fn.ARRAY_AGG(fn.Distinct(CveMetadata.cve)).alias('associated_cves')
        ).join(
            InsightsRule,
            on=(SystemVulnerabilities.rule_id == InsightsRule.id)).join(
                CveRuleMapping,
                on=(InsightsRule.id == CveRuleMapping.rule_id)).join(
                    CveMetadata, on=(CveRuleMapping.cve_id == CveMetadata.id)
                ).join(
                    SystemPlatform,
                    on=(SystemVulnerabilities.system_id == SystemPlatform.id) &
                    (SystemPlatform.rh_account_id == rh_account) &
                    (SystemPlatform.opt_out == False) &
                    (SystemPlatform.stale == False) &
                    (SystemPlatform.when_deleted.is_null(True)) &
                    (SystemPlatform.last_evaluation.is_null(False)
                     | SystemPlatform.advisor_evaluated.is_null(False))).where(
                         SystemVulnerabilities.rh_account_id == rh_account).
                     where((
                         SystemVulnerabilities.mitigation_reason.is_null(True))
                           & (SystemVulnerabilities.rule_id <<
                              InsightsRule.select(InsightsRule.id).where(
                                  (InsightsRule.active == True)
                                  & (~InsightsRule.rule_only)))).group_by(
                                      InsightsRule.name,
                                      InsightsRule.description_text,
                                      InsightsRule.rule_impact,
                                      InsightsRule.summary_text).order_by(
                                          InsightsRule.rule_impact.desc(),
                                          SQL('systems_affected desc'),
                                          InsightsRule.description_text,
                                          InsightsRule.name).limit(3).dicts())

        top_rules = cyndi_join(top_rules)

        for top_rule in top_rules:
            retval['top_rules'].append(top_rule)

        return retval
Example #19
0
 def _get_advisories_per_cve_from_db(synopsis):
     """Get advisories per CVE from DB"""
     query = (CveMetadata.select(
         CveMetadata.advisories_list).where(CveMetadata.cve == synopsis))
     return query
 def _cve_exists(cls, cve):
     if cve is None:
         raise ApplicationException("invalid cve_id", 400)
     cve = (CveMetadata.select().where(CveMetadata.cve == cve))
     if not cve.exists():
         raise ApplicationException("cve_id must exist", 404)
Example #21
0
    def handle_get(cls, **kwargs):
        # pylint: disable=singleton-comparison, too-many-branches, too-many-statements
        retval = {
            'cves_total': 0,
            'cves_by_severity': {
                '0to3.9': {
                    'percentage': 0,
                    'count': 0,
                    'known_exploits': 0
                },
                '4to7.9': {
                    'percentage': 0,
                    'count': 0,
                    'known_exploits': 0
                },
                '8to10': {
                    'percentage': 0,
                    'count': 0,
                    'known_exploits': 0
                },
                'na': {
                    'percentage': 0,
                    'count': 0,
                    'known_exploits': 0
                }
            },
            'exploited_cves_count': 0,
            'system_count': 0,
            'recent_cves': {
                'last7days': 0,
                'last30days': 0,
                'last90days': 0
            },
            'recent_rules': [],
            'rules_cves_total': 0,
        }

        args_desc = [{
            'arg_name': 'tags',
            'convert_func': parse_tags
        }, {
            'arg_name': 'sap_system',
            'convert_func': None
        }, {
            'arg_name': 'sap_sids',
            'convert_func': None
        }]
        args = cls._parse_arguments(kwargs, args_desc)
        cyndi_request = is_cyndi_request(args)
        rh_account, cve_cache_from, cve_cache_keepalive = get_account_data(
            connexion.context['user'])
        retval['system_count'] = get_system_count(rh_account, True, [
            filter_types.SYSTEM_TAGS, filter_types.SYSTEM_SAP,
            filter_types.SYSTEM_SAP_SIDS
        ], args)

        # API using cache, set keepalive for account to enable maintaining cache
        update_cve_cache_keepalive(rh_account, cve_cache_keepalive)

        # Use cache if not disabled + systems are not filtered + cache exists
        if not DISABLE_ACCOUNT_CACHE and not cyndi_request and cve_cache_from:
            active_cves_subquery = (CveAccountCache.select(
                CveAccountCache.cve_id.alias("cve_id_")).where(
                    CveAccountCache.rh_account_id == rh_account))
        else:
            active_cves_subquery = (
                SystemVulnerabilities.select(
                    fn.Distinct(SystemVulnerabilities.cve_id).alias("cve_id_")
                ).join(
                    SystemPlatform,
                    on=((SystemVulnerabilities.system_id == SystemPlatform.id)
                        & (SystemPlatform.rh_account_id == rh_account) &
                        (SystemPlatform.opt_out == False) &  # noqa: E712
                        (SystemPlatform.stale == False) &  # noqa: E712
                        (SystemPlatform.when_deleted.is_null(True)))).where(
                            SystemVulnerabilities.rh_account_id == rh_account).
                where((SystemVulnerabilities.mitigation_reason.is_null(True))
                      | (SystemVulnerabilities.rule_id << InsightsRule.select(
                          InsightsRule.id).where((InsightsRule.active == False)
                                                 & (~InsightsRule.rule_only))))
                .where((SystemVulnerabilities.when_mitigated.is_null(True)) | (
                    SystemVulnerabilities.rule_id << InsightsRule.select(
                        InsightsRule.id).where((InsightsRule.active == True) &
                                               (~InsightsRule.rule_only)))))
            if cyndi_request:
                active_cves_subquery = cyndi_join(active_cves_subquery)
                active_cves_subquery = apply_filters(
                    active_cves_subquery, args, [
                        filter_types.SYSTEM_TAGS, filter_types.SYSTEM_SAP,
                        filter_types.SYSTEM_SAP_SIDS
                    ], {})

        query = (CveMetadata.select(
            CveMetadata.cve,
            fn.COALESCE(CveMetadata.cvss3_score,
                        CveMetadata.cvss2_score).alias('cvss_score'),
            CveMetadata.public_date, CveMetadata.id,
            CveMetadata.exploits).join(
                active_cves_subquery,
                on=(CveMetadata.id == active_cves_subquery.c.cve_id_)).dicts())

        cve_data = [(cve["cvss_score"], cve["public_date"], cve["exploits"])
                    for cve in query]

        retval["cves_total"] = len(cve_data)
        retval["exploited_cves_count"] = len(
            [row[2] for row in cve_data if row[2] is True])

        today = datetime.now(timezone.utc).replace(
            hour=0, minute=0, second=0, microsecond=0)  # offset-aware
        last7 = today - timedelta(days=7)
        last30 = today - timedelta(days=30)
        last90 = today - timedelta(days=90)
        rules_date = today - timedelta(days=CFG.dashboard_rules_age)

        for cvss_score, public_date, exploit in cve_data:
            if cvss_score is None:
                retval["cves_by_severity"]["na"]["count"] += 1
                if exploit:
                    retval["cves_by_severity"]["na"]["known_exploits"] += 1
            elif cvss_score < 4:
                retval["cves_by_severity"]["0to3.9"]["count"] += 1
                if exploit:
                    retval["cves_by_severity"]["0to3.9"]["known_exploits"] += 1
            elif 4 <= cvss_score < 8:
                retval["cves_by_severity"]["4to7.9"]["count"] += 1
                if exploit:
                    retval["cves_by_severity"]["4to7.9"]["known_exploits"] += 1
            elif cvss_score >= 8:
                retval["cves_by_severity"]["8to10"]["count"] += 1
                if exploit:
                    retval["cves_by_severity"]["8to10"]["known_exploits"] += 1

            if public_date is not None:
                if public_date >= last7:
                    retval["recent_cves"]["last7days"] += 1
                if public_date >= last30:
                    retval["recent_cves"]["last30days"] += 1
                if public_date >= last90:
                    retval["recent_cves"]["last90days"] += 1

        rounded_percentage = round_to_100_percent(
            [v['count'] for v in retval['cves_by_severity'].values()])

        for indx, keys in enumerate(retval['cves_by_severity']):
            retval['cves_by_severity'][keys][
                'percentage'] = rounded_percentage[indx]

        rules_breakdown = (
            SystemVulnerabilities.select(
                fn.COUNT(fn.Distinct(SystemVulnerabilities.cve_id)).
                alias('rules_cves_count')).join(
                    CveRuleMapping,
                    on=(SystemVulnerabilities.cve_id == CveRuleMapping.cve_id
                        )).join(InsightsRule,
                                on=((CveRuleMapping.rule_id == InsightsRule.id)
                                    & (InsightsRule.active == True) &
                                    (~InsightsRule.rule_only))).
            join(
                SystemPlatform,
                on=((SystemVulnerabilities.system_id == SystemPlatform.id) &
                    (SystemPlatform.rh_account_id == rh_account) &
                    (SystemPlatform.when_deleted.is_null(True)) &
                    (SystemPlatform.stale == False) &
                    (SystemPlatform.opt_out == False) &  # noqa: E712
                    (SystemPlatform.last_evaluation.is_null(False)
                     | SystemPlatform.advisor_evaluated.is_null(False)))
            ).where(SystemVulnerabilities.rh_account_id == rh_account).where(
                SystemVulnerabilities.mitigation_reason.is_null(True)))

        if cyndi_request:
            rules_breakdown = cyndi_join(rules_breakdown)
            rules_breakdown = apply_filters(rules_breakdown, args, [
                filter_types.SYSTEM_TAGS, filter_types.SYSTEM_SAP,
                filter_types.SYSTEM_SAP_SIDS
            ], {})
        rules_breakdown = rules_breakdown.first()

        retval['rules_cves_total'] = rules_breakdown.rules_cves_count

        counts_query = (SystemVulnerabilities.select(
            SystemVulnerabilities.rule_id.alias("rule_id_"),
            fn.Count(fn.Distinct(
                SystemVulnerabilities.system_id)).alias("systems_affected_")
        ).join(
            SystemPlatform,
            on=((SystemVulnerabilities.system_id == SystemPlatform.id) &
                (SystemPlatform.rh_account_id == rh_account) &
                (SystemPlatform.opt_out == False) &
                (SystemPlatform.stale == False) &
                (SystemPlatform.when_deleted.is_null(True)))).where(
                    SystemVulnerabilities.rh_account_id == rh_account
                ).where((SystemVulnerabilities.rule_id << InsightsRule.select(
                    InsightsRule.id).where((InsightsRule.active == True)
                                           & (~InsightsRule.rule_only)))
                        & (SystemVulnerabilities.mitigation_reason.is_null(
                            True))).group_by(SystemVulnerabilities.rule_id))
        if cyndi_request:
            counts_query = cyndi_join(counts_query)
            counts_query = apply_filters(counts_query, args, [
                filter_types.SYSTEM_TAGS, filter_types.SYSTEM_SAP,
                filter_types.SYSTEM_SAP_SIDS
            ], {})

        recent_rules = (
            InsightsRule.select(
                InsightsRule.description_text.alias('name'),
                InsightsRule.summary_text.alias('description'),
                counts_query.c.systems_affected_.alias('systems_affected'),
                InsightsRule.rule_impact.alias('severity'),
                InsightsRule.kbase_node_id.alias('node_id'),
                fn.ARRAY_AGG(fn.Distinct(
                    CveMetadata.cve)).alias('associated_cves'),
                InsightsRule.name.alias('id'),
                InsightsRule.publish_date.alias('public_date')).join(
                    CveRuleMapping,
                    on=(InsightsRule.id == CveRuleMapping.rule_id)).join(
                        counts_query,
                        on=(InsightsRule.id == counts_query.c.rule_id_)).join(
                            CveMetadata,
                            on=(CveRuleMapping.cve_id == CveMetadata.id
                                )).where(
                                    (InsightsRule.publish_date >= rules_date) &
                                    (InsightsRule.active == True) &
                                    (~InsightsRule.rule_only))  # noqa: E712
            .group_by(InsightsRule.description_text, InsightsRule.publish_date,
                      InsightsRule.rule_impact, InsightsRule.kbase_node_id,
                      SQL('systems_affected'), InsightsRule.name,
                      InsightsRule.publish_date,
                      InsightsRule.summary_text).order_by(
                          InsightsRule.publish_date.desc(),
                          InsightsRule.rule_impact,
                          InsightsRule.description_text).dicts())

        recent_rules = apply_filters(recent_rules, args, [],
                                     {"count_subquery": counts_query})

        for rule in recent_rules:
            retval['recent_rules'].append(rule)

        return retval
Example #22
0
    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