Skip to content

Commit 3c15415

Browse files
committed
Bulk load advisories for grouping
Signed-off-by: Tushar Goel <tushar.goel.dav@gmail.com>
1 parent bfd9eb6 commit 3c15415

4 files changed

Lines changed: 90 additions & 13 deletions

File tree

vulnerabilities/api_v3.py

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@
1010
from collections import defaultdict
1111
from urllib.parse import urlencode
1212

13-
from django.contrib.postgres.aggregates import ArrayAgg, JSONBAgg
13+
from django.contrib.postgres.aggregates import ArrayAgg
14+
from django.contrib.postgres.aggregates import JSONBAgg
1415
from django.db.models import Exists
1516
from django.db.models import F
1617
from django.db.models import Max
@@ -736,11 +737,9 @@ def get_impacts_bulk(packages):
736737
impact_map = defaultdict(dict)
737738

738739
for impact in impacts:
739-
impact_map[
740-
impact["package_id"]
741-
][
742-
impact["impacted_package__advisory__avid"]
743-
] = impact["fixed_by_packages"] or []
740+
impact_map[impact["package_id"]][impact["impacted_package__advisory__avid"]] = (
741+
impact["fixed_by_packages"] or []
742+
)
744743

745744
return impact_map
746745

vulnerabilities/models.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2963,6 +2963,20 @@ def latest_affecting_advisories_for_purls(self, purls):
29632963
)
29642964
return self.filter(id__in=Subquery(adv_ids))
29652965

2966+
def latest_affecting_advisory_purls_pairs(self, purls):
2967+
return (
2968+
ImpactedPackage.objects.filter(
2969+
affecting_packages__package_url__in=purls,
2970+
advisory__is_latest=True,
2971+
advisory___all_impacts_unfurled=True,
2972+
)
2973+
.values_list(
2974+
"affecting_packages__package_url",
2975+
"advisory_id",
2976+
)
2977+
.distinct()
2978+
)
2979+
29662980
def latest_affecting_advisories_for_packages(self, packages):
29672981
adv_ids = ImpactedPackage.objects.filter(
29682982
affecting_packages__in=packages,
@@ -2997,6 +3011,20 @@ def latest_fixed_by_advisories_for_purls(self, purls):
29973011

29983012
return self.filter(id__in=Subquery(adv_ids))
29993013

3014+
def latest_fixed_by_advisory_purls_pairs(self, purls):
3015+
return (
3016+
ImpactedPackage.objects.filter(
3017+
fixed_by_packages__package_url__in=purls,
3018+
advisory__is_latest=True,
3019+
advisory___all_impacts_unfurled=True,
3020+
)
3021+
.values_list(
3022+
"fixed_by_packages__package_url",
3023+
"advisory_id",
3024+
)
3025+
.distinct()
3026+
)
3027+
30003028
def latest_advisories_for_purls(self, purls):
30013029
adv_ids = (
30023030
ImpactedPackage.objects.filter(

vulnerabilities/pipelines/v2_improvers/mark_unfurl_version_range.py

Lines changed: 45 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
# See https://aboutcode.org for more information about nexB OSS projects.
88
#
99

10+
from collections import defaultdict
11+
1012
from django.db import transaction
1113
from django.db.models import Exists
1214
from django.db.models import Min
@@ -21,6 +23,7 @@
2123
from vulnerabilities.models import PipelineSchedule
2224
from vulnerabilities.pipelines import VulnerableCodePipeline
2325
from vulnerabilities.pipes.group_advisories import group_advisory_for_package
26+
from vulnerabilities.pipes.group_advisories import group_single_package_with_provided_advisories
2427
from vulnerabilities.pipes.risk_score import compute_package_risk_score_bulk
2528
from vulnerabilities.utils import TYPES_WITH_MULTIPLE_IMPORTERS
2629

@@ -151,7 +154,46 @@ def complete_advisories_import(advisory_ids, successful_advisory_ids=[]):
151154

152155
group_package_ids = affecting_package_ids | fixed_by_package_ids
153156

154-
for package in PackageV2.objects.filter(
157+
packages = PackageV2.objects.filter(
155158
id__in=group_package_ids, type__in=TYPES_WITH_MULTIPLE_IMPORTERS
156-
).iterator(chunk_size=2000):
157-
group_advisory_for_package(package)
159+
).only("package_url", "id")
160+
161+
group_advisories_for_packages_bulk_marking(packages)
162+
163+
164+
def group_advisories_for_packages_bulk_marking(packages):
165+
purls = [package.package_url for package in packages]
166+
167+
affecting_pairs = AdvisoryV2.objects.latest_affecting_advisory_purls_pairs(purls)
168+
169+
fixed_pairs = AdvisoryV2.objects.latest_fixed_by_advisory_purls_pairs(purls)
170+
171+
affecting_ids = {adv_id for _, adv_id in affecting_pairs}
172+
fixed_ids = {adv_id for _, adv_id in fixed_pairs}
173+
174+
all_adv_ids = affecting_ids | fixed_ids
175+
176+
advisories = AdvisoryV2.objects.filter(id__in=all_adv_ids).prefetch_related(
177+
"aliases",
178+
"impacted_packages__affecting_packages",
179+
"impacted_packages__fixed_by_packages",
180+
)
181+
182+
advisory_map = {a.id: a for a in advisories}
183+
184+
affecting_by_purl = defaultdict(list)
185+
186+
for purl, advisory_id in affecting_pairs:
187+
affecting_by_purl[purl].append(advisory_map[advisory_id])
188+
189+
fixed_by_purl = defaultdict(list)
190+
191+
for purl, advisory_id in fixed_pairs:
192+
fixed_by_purl[purl].append(advisory_map[advisory_id])
193+
194+
for package in packages:
195+
group_single_package_with_provided_advisories(
196+
package=package,
197+
affecting_advisories=affecting_by_purl.get(package.purl, []),
198+
fixed_by_advisories=fixed_by_purl.get(package.purl, []),
199+
)

vulnerabilities/pipes/group_advisories.py

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -130,17 +130,25 @@ def group_advisory_for_package(package, logger=None):
130130
)
131131

132132
try:
133-
affected_groups: List[Group] = merge_advisories(affecting_advisories, package)
134-
fixed_by_groups: List[Group] = merge_advisories(fixed_by_advisories, package)
135-
delete_and_save_advisory_set(affected_groups, package, relation="affecting")
136-
delete_and_save_advisory_set(fixed_by_groups, package, relation="fixing")
133+
group_single_package_with_provided_advisories(
134+
package, affecting_advisories, fixed_by_advisories
135+
)
137136
logger(f"Successfully rebuilt advisory sets for package {package.purl}")
138137
except Exception as e:
139138
if logger:
140139
logger(f"Failed rebuilding advisory sets for package {package.purl}: {e!r}")
141140
return
142141

143142

143+
def group_single_package_with_provided_advisories(
144+
package, affecting_advisories, fixed_by_advisories
145+
):
146+
affected_groups: List[Group] = merge_advisories(affecting_advisories, package)
147+
fixed_by_groups: List[Group] = merge_advisories(fixed_by_advisories, package)
148+
delete_and_save_advisory_set(affected_groups, package, relation="affecting")
149+
delete_and_save_advisory_set(fixed_by_groups, package, relation="fixing")
150+
151+
144152
def compute_advisory_content_hash(adv, version_less_purl_str: str):
145153
"""
146154
Compute a content hash for an advisory.

0 commit comments

Comments
 (0)