15
15
16
16
from django .core .exceptions import ValidationError
17
17
from django .db import transaction
18
+ from django .db .models .query import QuerySet
18
19
19
20
from vulnerabilities .importer import AdvisoryData
20
21
from vulnerabilities .importer import Importer
@@ -96,23 +97,29 @@ def process_advisories(
96
97
Insert advisories into the database
97
98
Return the number of inserted advisories.
98
99
"""
100
+ from vulnerabilities .pipes .advisory import get_or_create_aliases
101
+ from vulnerabilities .utils import compute_content_id
102
+
99
103
count = 0
100
104
advisories = []
101
105
for data in advisory_datas :
106
+ content_id = compute_content_id (advisory_data = data )
102
107
try :
108
+ aliases = get_or_create_aliases (aliases = data .aliases )
103
109
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
+ unique_content_id = content_id ,
111
+ url = data .url ,
110
112
defaults = {
113
+ "summary" : data .summary ,
114
+ "affected_packages" : [pkg .to_dict () for pkg in data .affected_packages ],
115
+ "references" : [ref .to_dict () for ref in data .references ],
116
+ "date_published" : data .date_published ,
117
+ "weaknesses" : data .weaknesses ,
111
118
"created_by" : importer_name ,
112
119
"date_collected" : datetime .datetime .now (tz = datetime .timezone .utc ),
113
120
},
114
- url = data .url ,
115
121
)
122
+ obj .aliases .add (* aliases )
116
123
if not obj .date_imported :
117
124
advisories .append (obj )
118
125
except Exception as e :
@@ -148,6 +155,8 @@ def process_inferences(inferences: List[Inference], advisory: Advisory, improver
148
155
erroneous. Also, the atomic transaction for every advisory and its
149
156
inferences makes sure that date_imported of advisory is consistent.
150
157
"""
158
+ from vulnerabilities .pipes .advisory import get_or_create_aliases
159
+
151
160
inferences_processed_count = 0
152
161
153
162
if not inferences :
@@ -157,9 +166,10 @@ def process_inferences(inferences: List[Inference], advisory: Advisory, improver
157
166
logger .info (f"Improving advisory id: { advisory .id } " )
158
167
159
168
for inference in inferences :
169
+ aliases = get_or_create_aliases (inference .aliases )
160
170
vulnerability = get_or_create_vulnerability_and_aliases (
161
171
vulnerability_id = inference .vulnerability_id ,
162
- aliases = inference . aliases ,
172
+ aliases = aliases ,
163
173
summary = inference .summary ,
164
174
advisory = advisory ,
165
175
)
@@ -265,14 +275,13 @@ def create_valid_vulnerability_reference(url, reference_id=None):
265
275
266
276
267
277
def get_or_create_vulnerability_and_aliases (
268
- aliases : List [ str ] , vulnerability_id = None , summary = None , advisory = None
278
+ aliases : QuerySet , vulnerability_id = None , summary = None , advisory = None
269
279
):
270
280
"""
271
281
Get or create vulnerabilitiy and aliases such that all existing and new
272
282
aliases point to the same vulnerability
273
283
"""
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 )
284
+ new_aliases , existing_vulns = get_vulns_for_aliases_and_get_new_aliases (aliases )
276
285
277
286
# All aliases must point to the same vulnerability
278
287
vulnerability = None
@@ -310,11 +319,11 @@ def get_or_create_vulnerability_and_aliases(
310
319
# f"Inconsistent summary for {vulnerability.vulnerability_id}. "
311
320
# f"Existing: {vulnerability.summary!r}, provided: {summary!r}"
312
321
# )
313
- associate_vulnerability_with_aliases (vulnerability = vulnerability , aliases = new_alias_names )
322
+ associate_vulnerability_with_aliases (vulnerability = vulnerability , aliases = new_aliases )
314
323
else :
315
324
try :
316
325
vulnerability = create_vulnerability_and_add_aliases (
317
- aliases = new_alias_names , summary = summary
326
+ aliases = new_aliases , summary = summary
318
327
)
319
328
importer_name = get_importer_name (advisory )
320
329
VulnerabilityChangeLog .log_import (
@@ -324,24 +333,22 @@ def get_or_create_vulnerability_and_aliases(
324
333
)
325
334
except Exception as e :
326
335
logger .error (
327
- f"Cannot create vulnerability with summary { summary !r} and { new_alias_names !r} { e !r} .\n { traceback_format_exc ()} ."
336
+ f"Cannot create vulnerability with summary { summary !r} and { new_aliases !r} { e !r} .\n { traceback_format_exc ()} ."
328
337
)
329
338
return
330
339
331
340
return vulnerability
332
341
333
342
334
- def get_vulns_for_aliases_and_get_new_aliases (aliases ):
343
+ def get_vulns_for_aliases_and_get_new_aliases (aliases : QuerySet ):
335
344
"""
336
345
Return ``new_aliases`` that are not in the database and
337
346
``existing_vulns`` that point to the given ``aliases``.
338
347
"""
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
348
+ new_aliases = aliases .filter (vulnerability__isnull = True )
349
+ existing_vulns = [alias .vulnerability for alias in aliases .filter (vulnerability__isnull = False )]
350
+
351
+ return new_aliases , list (set (existing_vulns ))
345
352
346
353
347
354
@transaction .atomic
@@ -360,7 +367,5 @@ def create_vulnerability_and_add_aliases(aliases, summary):
360
367
361
368
362
369
def 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 } " )
370
+ aliases .update (vulnerability = vulnerability )
371
+ logger .info (f"New alias for { vulnerability !r} : { aliases } " )
0 commit comments