1515
1616from django .core .exceptions import ValidationError
1717from django .db import transaction
18+ from django .db .models .query import QuerySet
1819
1920from vulnerabilities .importer import AdvisoryData
2021from vulnerabilities .importer import Importer
@@ -96,25 +97,37 @@ def process_advisories(
9697 Insert advisories into the database
9798 Return the number of inserted advisories.
9899 """
100+ from vulnerabilities .pipes .advisory import get_or_create_aliases
101+ from vulnerabilities .utils import compute_content_id
102+
99103 count = 0
100104 advisories = []
101105 for data in advisory_datas :
106+ content_id = compute_content_id (advisory_data = data )
107+ advisory = {
108+ "summary" : data .summary ,
109+ "affected_packages" : [pkg .to_dict () for pkg in data .affected_packages ],
110+ "references" : [ref .to_dict () for ref in data .references ],
111+ "date_published" : data .date_published ,
112+ "weaknesses" : data .weaknesses ,
113+ "created_by" : importer_name ,
114+ "date_collected" : datetime .datetime .now (tz = datetime .timezone .utc ),
115+ }
102116 try :
117+ aliases = get_or_create_aliases (aliases = data .aliases )
103118 obj , created = Advisory .objects .get_or_create (
104- aliases = data .aliases ,
105- summary = data .summary ,
106- affected_packages = [pkg .to_dict () for pkg in data .affected_packages ],
107- references = [ref .to_dict () for ref in data .references ],
108- date_published = data .date_published ,
109- weaknesses = data .weaknesses ,
110- defaults = {
111- "created_by" : importer_name ,
112- "date_collected" : datetime .datetime .now (tz = datetime .timezone .utc ),
113- },
119+ unique_content_id = content_id ,
114120 url = data .url ,
121+ defaults = advisory ,
115122 )
123+ obj .aliases .add (* aliases )
116124 if not obj .date_imported :
117125 advisories .append (obj )
126+ except Advisory .MultipleObjectsReturned :
127+ logger .error (
128+ f"Multiple Advisories returned: unique_content_id: { content_id } , url: { data .url } , advisory: { advisory !r} "
129+ )
130+ raise
118131 except Exception as e :
119132 logger .error (
120133 f"Error while processing { data !r} with aliases { data .aliases !r} : { e !r} \n { traceback_format_exc ()} "
@@ -148,6 +161,8 @@ def process_inferences(inferences: List[Inference], advisory: Advisory, improver
148161 erroneous. Also, the atomic transaction for every advisory and its
149162 inferences makes sure that date_imported of advisory is consistent.
150163 """
164+ from vulnerabilities .pipes .advisory import get_or_create_aliases
165+
151166 inferences_processed_count = 0
152167
153168 if not inferences :
@@ -157,9 +172,10 @@ def process_inferences(inferences: List[Inference], advisory: Advisory, improver
157172 logger .info (f"Improving advisory id: { advisory .id } " )
158173
159174 for inference in inferences :
175+ aliases = get_or_create_aliases (inference .aliases )
160176 vulnerability = get_or_create_vulnerability_and_aliases (
161177 vulnerability_id = inference .vulnerability_id ,
162- aliases = inference . aliases ,
178+ aliases = aliases ,
163179 summary = inference .summary ,
164180 advisory = advisory ,
165181 )
@@ -265,14 +281,13 @@ def create_valid_vulnerability_reference(url, reference_id=None):
265281
266282
267283def get_or_create_vulnerability_and_aliases (
268- aliases : List [ str ] , vulnerability_id = None , summary = None , advisory = None
284+ aliases : QuerySet , vulnerability_id = None , summary = None , advisory = None
269285):
270286 """
271287 Get or create vulnerabilitiy and aliases such that all existing and new
272288 aliases point to the same vulnerability
273289 """
274- aliases = set (alias .strip () for alias in aliases if alias and alias .strip ())
275- new_alias_names , existing_vulns = get_vulns_for_aliases_and_get_new_aliases (aliases )
290+ new_aliases , existing_vulns = get_vulns_for_aliases_and_get_new_aliases (aliases )
276291
277292 # All aliases must point to the same vulnerability
278293 vulnerability = None
@@ -310,11 +325,11 @@ def get_or_create_vulnerability_and_aliases(
310325 # f"Inconsistent summary for {vulnerability.vulnerability_id}. "
311326 # f"Existing: {vulnerability.summary!r}, provided: {summary!r}"
312327 # )
313- associate_vulnerability_with_aliases (vulnerability = vulnerability , aliases = new_alias_names )
328+ associate_vulnerability_with_aliases (vulnerability = vulnerability , aliases = new_aliases )
314329 else :
315330 try :
316331 vulnerability = create_vulnerability_and_add_aliases (
317- aliases = new_alias_names , summary = summary
332+ aliases = new_aliases , summary = summary
318333 )
319334 importer_name = get_importer_name (advisory )
320335 VulnerabilityChangeLog .log_import (
@@ -324,24 +339,22 @@ def get_or_create_vulnerability_and_aliases(
324339 )
325340 except Exception as e :
326341 logger .error (
327- f"Cannot create vulnerability with summary { summary !r} and { new_alias_names !r} { e !r} .\n { traceback_format_exc ()} ."
342+ f"Cannot create vulnerability with summary { summary !r} and { new_aliases !r} { e !r} .\n { traceback_format_exc ()} ."
328343 )
329344 return
330345
331346 return vulnerability
332347
333348
334- def get_vulns_for_aliases_and_get_new_aliases (aliases ):
349+ def get_vulns_for_aliases_and_get_new_aliases (aliases : QuerySet ):
335350 """
336351 Return ``new_aliases`` that are not in the database and
337352 ``existing_vulns`` that point to the given ``aliases``.
338353 """
339- new_aliases = set (aliases )
340- existing_vulns = set ()
341- for alias in Alias .objects .filter (alias__in = aliases ):
342- existing_vulns .add (alias .vulnerability )
343- new_aliases .remove (alias .alias )
344- return new_aliases , existing_vulns
354+ new_aliases = aliases .filter (vulnerability__isnull = True )
355+ existing_vulns = [alias .vulnerability for alias in aliases .filter (vulnerability__isnull = False )]
356+
357+ return new_aliases , list (set (existing_vulns ))
345358
346359
347360@transaction .atomic
@@ -360,7 +373,5 @@ def create_vulnerability_and_add_aliases(aliases, summary):
360373
361374
362375def associate_vulnerability_with_aliases (aliases , vulnerability ):
363- for alias_name in aliases :
364- alias = Alias (alias = alias_name , vulnerability = vulnerability )
365- alias .save ()
366- logger .info (f"New alias for { vulnerability !r} : { alias_name } " )
376+ aliases .update (vulnerability = vulnerability )
377+ logger .info (f"New alias for { vulnerability !r} : { aliases } " )
0 commit comments