Skip to content

Commit

Permalink
fix: duplicate cves in system/cves
Browse files Browse the repository at this point in the history
RHINENG-7735
  • Loading branch information
psegedy authored and jdobes committed Jan 7, 2025
1 parent a626c24 commit abc57b4
Showing 1 changed file with 44 additions and 53 deletions.
97 changes: 44 additions & 53 deletions manager/system_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,14 @@

import dateutil.parser
from connexion import context
from peewee import CTE
from peewee import JOIN
from peewee import SQL
from peewee import Case
from peewee import Column
from peewee import DoesNotExist
from peewee import NodeList
from peewee import Query
from peewee import Value
from peewee import fn

Expand All @@ -20,6 +23,7 @@
from common.logging import get_logger
from common.peewee_conditions import system_is_active
from common.peewee_conditions import system_is_vulnerable
from common.peewee_model import BaseModel
from common.peewee_model import BusinessRisk
from common.peewee_model import CveAccountData
from common.peewee_model import CveImpact
Expand Down Expand Up @@ -81,57 +85,30 @@ def __init__(self, account_data, list_args, query_args, parsed_args, uri, ids_on
filter_types.CVE_PUBLIC_DATE,
filter_types.CVE_KNOWN_EXPLOITS,
]

self.unpatched_columns = ["id", "cve_name", "cvss3_score", "cvss2_score", "impact", "public_date", "cve_description", "exploit_data",
"impact_id", "cve_status_id", "status_id", "status_text", "when_mitigated", "first_reported", "advisories",
"cve_status_text", "business_risk_id", "business_risk_text", "business_risk", "rule_id", "description_text",
"summary_text", "reboot_required", "playbook_count", "change_risk", "kbase_node_id", "rule_active",
"generate_autoplaybook", "advisory_available", "remediation_type_id"]
self.unpatched_id_columns = ["id", "cve_name", "status_id", "status_text", "rule_id", "cve_status_id", "cve_status_text", "remediation"]

fixed_cte, unfixed_cte = None, None
if not account_data.cves_without_errata:
query = (self._full_query(account_data.id, query_args, parsed_args, filters, remediation_filter=DEFAULT_REMEDIATION_FILTER) if not ids_only
else self._id_query(account_data.id, query_args, parsed_args, filters, remediation_filter=DEFAULT_REMEDIATION_FILTER))
else:
query = (self._unpatched_full_query(account_data.id, query_args, parsed_args, filters) if not ids_only
else self._unpatched_id_query(account_data.id, query_args, parsed_args, filters))
query, fixed_cte, unfixed_cte = (self._unpatched_full_query(account_data.id, query_args, parsed_args, filters) if not ids_only
else self._unpatched_id_query(account_data.id, query_args, parsed_args, filters))

if not ids_only:
query = query.select_from(
query.c.id,
query.c.cve_name,
query.c.cvss3_score,
query.c.cvss2_score,
query.c.impact,
query.c.public_date,
query.c.cve_description,
query.c.exploit_data,
query.c.impact_id,
query.c.cve_status_id,
query.c.status_id,
query.c.status_text,
query.c.when_mitigated,
query.c.first_reported,
query.c.advisories,
query.c.cve_status_text,
query.c.business_risk_id,
query.c.business_risk_text,
query.c.business_risk,
query.c.rule_id,
query.c.description_text,
query.c.summary_text,
query.c.reboot_required,
query.c.playbook_count,
query.c.change_risk,
query.c.kbase_node_id,
query.c.rule_active,
query.c.generate_autoplaybook,
query.c.advisory_available,
query.c.remediation_type_id,
)
query = query.select_from(*self._get_query_columns(query, self.unpatched_columns))
else:
query = query.select_from(
query.c.id,
query.c.cve_name,
query.c.status_id,
query.c.status_text,
query.c.rule_id,
query.c.cve_status_id,
query.c.cve_status_text,
query.c.remediation,
)
query = query.select_from(*self._get_query_columns(query, self.unpatched_id_columns))

if fixed_cte and unfixed_cte:
# we need to use CTE here because if `with_cte` is used earlier then the final query
# has invalid sytax (missing parantheses) due to a bug in peewee
query = query.with_cte(fixed_cte, unfixed_cte)
query = query.dicts()

sortable_columns = {
Expand Down Expand Up @@ -230,8 +207,7 @@ def _full_query(rh_account_id, query_args, parsed_args, filters, remediation_fil
subq = cyndi_join(subq)
return apply_filters(subq, parsed_args, filters, {"unfixed": [False]})

@staticmethod
def _unpatched_full_query(rh_account_id, query_args, parsed_args, filters):
def _unpatched_full_query(self, rh_account_id, query_args, parsed_args, filters) -> tuple[Query, CTE | None, CTE | None]:
# pylint: disable=singleton-comparison
remediation_filter, return_only_first_subq = get_remediation_filter(parsed_args["advisory_available"])

Expand Down Expand Up @@ -287,9 +263,9 @@ def _unpatched_full_query(rh_account_id, query_args, parsed_args, filters):
unfixed_subq = apply_filters(unfixed_subq, parsed_args, filters, {"unfixed": [True]})

if return_only_first_subq:
return fixed_subq
return fixed_subq, None, None
else:
return (fixed_subq + unfixed_subq)
return self._unpatched_query_w_cte(fixed_subq, unfixed_subq, self.unpatched_columns)

@staticmethod
def _id_query(rh_account_id, query_args, parsed_args, filters, remediation_filter=None):
Expand Down Expand Up @@ -338,8 +314,7 @@ def _id_query(rh_account_id, query_args, parsed_args, filters, remediation_filte
subq = cyndi_join(subq)
return apply_filters(subq, parsed_args, filters, {})

@staticmethod
def _unpatched_id_query(rh_account_id, query_args, parsed_args, filters):
def _unpatched_id_query(self, rh_account_id, query_args, parsed_args, filters) -> tuple[Query, CTE | None, CTE | None]:
# pylint: disable=singleton-comparison
remediation_filter, return_only_first_subq = get_remediation_filter(parsed_args["advisory_available"])

Expand Down Expand Up @@ -386,9 +361,25 @@ def _unpatched_id_query(rh_account_id, query_args, parsed_args, filters):
unfixed_subq = apply_filters(unfixed_subq, parsed_args, filters, {"unfixed": [True]})

if return_only_first_subq:
return fixed_subq
return fixed_subq, None, None
else:
return (fixed_subq + unfixed_subq)
return self._unpatched_query_w_cte(fixed_subq, unfixed_subq, self.unpatched_id_columns)

def _get_query_columns(self, query: Query, columns: list[str]) -> list[Column]:
return [getattr(query.c, column) for column in columns]

def _unpatched_query_w_cte(self, fixed_subq: Query, unfixed_subq: Query, columns: list[str]) -> tuple[Query, CTE, CTE]:
fixed_cte = CTE("fixed_cte", fixed_subq)
unfixed_cte = CTE("unfixed_cte", unfixed_subq)
# use `BaseModel.select().from_()` instead of `cte.select_from` to avoid generating unnecessary CTEs
unfixed_subq = BaseModel.select(*self._get_query_columns(unfixed_cte, columns)).from_(unfixed_cte)
fixed_subq = (
BaseModel.select(*self._get_query_columns(fixed_cte, columns))
.from_(fixed_cte)
.join(unfixed_cte, JOIN.LEFT_OUTER, on=(fixed_cte.c.cve_name == unfixed_cte.c.cve_name))
.where(unfixed_cte.c.cve_name.is_null())
)
return (fixed_subq + unfixed_subq), fixed_cte, unfixed_cte


class SystemView(ListView):
Expand Down

0 comments on commit abc57b4

Please sign in to comment.