Merge ~litios/ubuntu-cve-tracker:oval/usns-only-fixed-cves into ubuntu-cve-tracker:master
- Git
- lp:~litios/ubuntu-cve-tracker
- oval/usns-only-fixed-cves
- Merge into master
Status: | Merged |
---|---|
Merge reported by: | David Fernandez Gonzalez |
Merged at revision: | 32dcaba0c7ada41f0e265d0f037c864bf83aab0e |
Proposed branch: | ~litios/ubuntu-cve-tracker:oval/usns-only-fixed-cves |
Merge into: | ubuntu-cve-tracker:master |
Diff against target: |
673 lines (+177/-164) 2 files modified
scripts/oval_lib.py (+111/-45) test/test_json_generation.py (+66/-119) |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Eduardo Barretto | Approve | ||
Review via email:
|
Commit message
Description of the change
[OVAL/JSON GEN] Only load CVEs into USN if affecting the release.
USN CVEs are now based on release. This ensures that only the affected
CVEs will be listed when generating for a specific release.
Since we have regressions that do not list a CVE and wrong
USN fixed version entries, there is no way we can retrieve the right
Package from the CVE so we are looking based on release and fixed version.
---------
USN loading is performed in the following way:
1. Get the listed releases in the USN. For each:
- Identify active ESM releases
- Get the packages mentioned in the USN released and fixed versions
- Based on the release, package and fixed version,
retrieve the appropriate Package and save it with the USN fixed version.
2. Get the CVE/LP bugs entries. For each CVE:
- Get each PkgRelEntry and check if is marked as fixed (or if USN is a regression)
and that the package and release are mentioned in the USN, if so, get CVE.
If there are no packages for the requested releases, skip USN.
---------
These changes introduced a diff in JSON generation:
* Only fixed/related CVEs will be listed on the USN entries.
* More USNs listed since now we do better handling of parent cases.
JSON generation code updated and tests updated.
Preview Diff
1 | diff --git a/scripts/oval_lib.py b/scripts/oval_lib.py |
2 | index 9127dad..a33cca2 100755 |
3 | --- a/scripts/oval_lib.py |
4 | +++ b/scripts/oval_lib.py |
5 | @@ -494,23 +494,29 @@ class USN: |
6 | |
7 | self.lp_bugs = lp_bugs |
8 | self.cves = cve_objs |
9 | - self.pkgs = self._generate_pkg_fixed_ver_tuple_dict(pkgs_by_rel) |
10 | - |
11 | - def _generate_pkg_fixed_ver_tuple_dict(self, pkgs_by_rel): |
12 | - tup_dict = {} |
13 | - for rel, pkgs in pkgs_by_rel.items(): |
14 | - tup_dict[rel] = {} |
15 | - for src_name, pkg_object in pkgs.items(): |
16 | - fixed_ver = self.releases[rel]['sources'][src_name]['version'] |
17 | - tup_dict[rel][src_name] = (pkg_object, fixed_ver) |
18 | - return tup_dict |
19 | + self.pkgs = pkgs_by_rel |
20 | |
21 | def get_pkg_fixed_version(self, package: Package): |
22 | + """Get the fixed version of a given package in the USN""" |
23 | if not self.is_package_present(package): return None |
24 | - return self.pkgs[package.rel][package.name][1] |
25 | + for rel in self.pkgs: |
26 | + if package.name in self.pkgs[rel]: |
27 | + return self.pkgs[rel][package.name][1] |
28 | |
29 | def is_package_present(self, package: Package): |
30 | - return package.rel in self.pkgs and package.name in self.pkgs[package.rel] |
31 | + """Check if a package is present in the USN, regardless of the release""" |
32 | + for rel in self.pkgs: |
33 | + if package.name in self.pkgs[rel]: |
34 | + return True |
35 | + |
36 | + return False |
37 | + |
38 | + def get_package_release_in_usn(self, package: Package): |
39 | + """Get the release of a given package in the USN""" |
40 | + if not self.is_package_present(package): return None |
41 | + for rel in self.pkgs: |
42 | + if package.name in self.pkgs[rel]: |
43 | + return self.pkgs[rel][package.name][0].rel |
44 | |
45 | def __str__(self) -> str: |
46 | # return f'description: {self.description}\nid: {self.id}\ncves: {self.cves}\npkgs: {self.pkgs}\n' # TODO: remove this ugly debug print |
47 | @@ -593,9 +599,11 @@ class OvalGenerator: |
48 | def _get_objects_including_parents(self, objects) -> dict: |
49 | all_objs = dict() |
50 | for parent_release in self.parent_releases[::-1]: |
51 | - all_objs.update(objects[parent_release]) |
52 | + if parent_release in objects: |
53 | + all_objs.update(objects[parent_release]) |
54 | |
55 | - all_objs.update(objects[self.release]) |
56 | + if self.release in objects: |
57 | + all_objs.update(objects[self.release]) |
58 | return all_objs |
59 | |
60 | def _add_structure(self, root) -> None: |
61 | @@ -1799,33 +1807,82 @@ class OvalGeneratorUSNs(OvalGenerator): |
62 | def _load_usns(self, usn_database): |
63 | usns = {} |
64 | # go thru every USN in the JSON |
65 | - for usn_id, usn_data in dict(sorted(usn_database.items())).items(): |
66 | + for usn_id, usn_data in usn_database.items(): |
67 | # take existing CVE and Package objects |
68 | - cve_objs = {} |
69 | - pkg_objs_by_rels = {} |
70 | + cves = {} |
71 | + pkgs = {} |
72 | lp_bugs = [] |
73 | + # Package - fixed version loading |
74 | for rel, info in usn_data['releases'].items(): |
75 | - # CVE stays the same across releases |
76 | - for cve in usn_data['cves']: |
77 | - if 'launchpad' in cve: |
78 | - lp_bugs.append(cve) |
79 | - elif cve_objs.get(cve) is None: |
80 | - try: |
81 | - cve_objs[cve] = self.cves[rel][cve] |
82 | - except KeyError: |
83 | - pass |
84 | - pkg_objs = {} |
85 | - for pkg, _ in info['sources'].items(): |
86 | - try: |
87 | - pkg_objs[pkg] = self.packages[rel][pkg] |
88 | - except KeyError: |
89 | - pass |
90 | - if pkg_objs: |
91 | - pkg_objs_by_rels[rel] = pkg_objs |
92 | + esm_rels = list(filter(lambda esm_rel: rel in esm_rel and rel != esm_rel, cve_lib.get_active_esm_releases())) |
93 | + all_rels = esm_rels.copy() |
94 | + all_rels.append(rel) |
95 | + |
96 | + # Sanity check to skip in case none of the releases was requested |
97 | + rel_exists = False |
98 | + for rel in all_rels: |
99 | + if rel in self.releases: rel_exists = True |
100 | + if not rel_exists: continue |
101 | + |
102 | + |
103 | + # Get package |
104 | + for pkg, pkg_info in info['sources'].items(): |
105 | + pkg_obj = None |
106 | + if 'esm' in pkg_info['version']: |
107 | + for current_rel in esm_rels: |
108 | + if current_rel not in self.packages: continue |
109 | + if pkg not in self.packages[current_rel]: continue |
110 | + pkg_obj = self.packages[current_rel][pkg] |
111 | + break |
112 | + if pkg_obj: |
113 | + pkgs.setdefault(current_rel, {}) |
114 | + pkgs[current_rel][pkg] = (pkg_obj, pkg_info['version']) |
115 | + else: |
116 | + if rel not in self.packages: continue |
117 | + if pkg not in self.packages[rel]: continue |
118 | + pkg_obj = self.packages[rel][pkg] |
119 | + pkgs.setdefault(rel, {}) |
120 | + pkgs[rel][pkg] = (pkg_obj, pkg_info['version']) |
121 | + |
122 | + # CVE loading |
123 | + for cve_text in usn_data['cves']: |
124 | + if 'launchpad.net' in cve_text: |
125 | + lp_bugs.append(cve_text) |
126 | + continue |
127 | + elif not re.search(r'CVE-\d{4}-\d{4,7}', cve_text): |
128 | + continue |
129 | + |
130 | + cve = None |
131 | + for rel in usn_data['releases']: |
132 | + if rel not in self.cves or \ |
133 | + cve_text not in self.cves[rel]: continue |
134 | + cve = self.cves[rel][cve_text] |
135 | + break |
136 | + |
137 | + if not cve: continue |
138 | + |
139 | + # Was the CVE fixed in this USN for any of the packages of the considered releases? |
140 | + for pkg_rel_entry in cve.pkg_rel_entries.values(): |
141 | + if pkg_rel_entry.orig_status != 'released' and 'regression' not in usn_data['title']: continue |
142 | + if 'esm' in pkg_rel_entry.release: |
143 | + rel = cve_lib.get_orig_rel_name(pkg_rel_entry.release) |
144 | + else: |
145 | + rel = pkg_rel_entry.release |
146 | + if rel not in usn_data['releases'] or \ |
147 | + pkg_rel_entry.pkg.name not in usn_data['releases'][rel]['sources']: continue |
148 | + # We have some cases like -2 USNs or wrong versions |
149 | + # so we cannot compare against CVE version, TBD once |
150 | + # we have fixed USN wrong versions. |
151 | + cves.setdefault(pkg_rel_entry.release, {}) |
152 | + pkg_info = usn_data['releases'][rel]['sources'][pkg_rel_entry.pkg.name] |
153 | + cves[pkg_rel_entry.release][cve.number] = cve |
154 | + |
155 | # create a USN object with fields in the USN and |
156 | # corresponding CVEs and Packages |
157 | - usns[usn_id] = USN(usn_data, cve_objs, pkg_objs_by_rels, lp_bugs) |
158 | - return usns |
159 | + if len(pkgs) == 0: continue |
160 | + usns[usn_id] = USN(usn_data, cves, pkgs, lp_bugs) |
161 | + |
162 | + return dict(sorted(usns.items())) |
163 | |
164 | def _generate_advisory(self, usn: USN) -> etree.Element: |
165 | severities = ['low', 'medium', 'high', 'critical'] |
166 | @@ -1833,7 +1890,7 @@ class OvalGeneratorUSNs(OvalGenerator): |
167 | severity = etree.SubElement(advisory, "severity") |
168 | issued = etree.SubElement(advisory, "issued") |
169 | severity = None |
170 | - for cve in usn.cves: |
171 | + for cve in usn.cves[self.release]: |
172 | cve_obj = self._generate_cve_tag(self.cves[cve]) |
173 | advisory.append(cve_obj) |
174 | |
175 | @@ -2731,10 +2788,12 @@ class JSONPkgGenerator(OvalGeneratorUSNs): |
176 | self.generator_type = 'json_pkg' |
177 | |
178 | def _generate_usn_info(self, usn: USN): |
179 | + cves = list(self._get_objects_including_parents(usn.cves).keys()) |
180 | + if len(cves) == 0 and len(usn.lp_bugs) == 0: return {} # If no CVEs or LP bugs, don't add the USN |
181 | return { |
182 | 'description': usn.description, |
183 | 'published_at': datetime.fromtimestamp(usn.timestamp).isoformat(timespec="seconds"), |
184 | - 'related_cves': list(usn.cves.keys()), |
185 | + 'related_cves': cves, |
186 | 'related_launchpad_bugs': usn.lp_bugs |
187 | } |
188 | |
189 | @@ -2794,15 +2853,21 @@ class JSONPkgGenerator(OvalGeneratorUSNs): |
190 | |
191 | def _generate_cve_pkg_info(self, package: Package) -> dict: |
192 | pkg_cves = {} |
193 | + all_releases = self.parent_releases.copy() |
194 | + all_releases.append(self.release) |
195 | + |
196 | for cve in package.cves: |
197 | cve_pkg_rel_entry = None |
198 | |
199 | for pkg_rel_entry_id in cve.pkg_rel_entries: |
200 | pkg_rel_entry_package, pkg_rel_entry_rel = pkg_rel_entry_id.split('/', maxsplit=1) |
201 | if pkg_rel_entry_package == package.name and \ |
202 | - pkg_rel_entry_rel == package.rel: |
203 | - cve_pkg_rel_entry = cve.pkg_rel_entries[pkg_rel_entry_id] |
204 | - break |
205 | + pkg_rel_entry_rel in all_releases: |
206 | + |
207 | + if cve_pkg_rel_entry and cve_pkg_rel_entry.status != 'fixed': |
208 | + cve_pkg_rel_entry = cve.pkg_rel_entries[pkg_rel_entry_id] |
209 | + elif not cve_pkg_rel_entry: |
210 | + cve_pkg_rel_entry = cve.pkg_rel_entries[pkg_rel_entry_id] |
211 | |
212 | if not cve_pkg_rel_entry: |
213 | print(f'CVE entry for {package.name} - {package.rel} in {cve.number} not found') |
214 | @@ -2820,11 +2885,12 @@ class JSONPkgGenerator(OvalGeneratorUSNs): |
215 | usns_pkg_info = dict() |
216 | usns_regression_pkg_info = dict() |
217 | for usn_id, usn in self.usns.items(): |
218 | - if usn.is_package_present(package): |
219 | + if usn.is_package_present(package) and \ |
220 | + (usn.get_package_release_in_usn(package) == self.release or \ |
221 | + usn.get_package_release_in_usn(package) in self.parent_releases): |
222 | usn_pkg_info = { |
223 | 'source_fixed_version': usn.get_pkg_fixed_version(package) |
224 | } |
225 | - |
226 | if 'regression' in usn.title.lower(): |
227 | usns_regression_pkg_info[f'USN-{usn_id}'] = usn_pkg_info |
228 | else: |
229 | @@ -2899,9 +2965,9 @@ class JSONPkgGenerator(OvalGeneratorUSNs): |
230 | self.release_codename = self.release_codename.replace('/', '_') |
231 | self.parent_releases = self._get_parent_releases(release) |
232 | if self._expand_release(self.release, self.expand): |
233 | - self.output_file = f'com.ubuntu.{self.release.replace("/", "_")}.pkg.json' |
234 | + self.output_file = f'com.ubuntu.{self.release.replace("/", "_")}.pkg.json' |
235 | else: |
236 | - self.output_file = f'com.ubuntu.{self.release_codename}.pkg.json' |
237 | + self.output_file = f'com.ubuntu.{self.release_codename}.pkg.json' |
238 | |
239 | def generate_json(self) -> None: |
240 | for release in self.releases: |
241 | diff --git a/test/test_json_generation.py b/test/test_json_generation.py |
242 | index 9f44642..6638b5d 100644 |
243 | --- a/test/test_json_generation.py |
244 | +++ b/test/test_json_generation.py |
245 | @@ -129,7 +129,6 @@ class EmptyJSONPkgGenerator(JSONPkgGenerator): |
246 | self.pkg_cache = None |
247 | self.expand = True |
248 | pass |
249 | - |
250 | #### TESTS #### |
251 | |
252 | @pytest.mark.parametrize("mock_cve", [ |
253 | @@ -202,55 +201,6 @@ def test_generate_cves_info(): |
254 | assert generated_info['cvss_score'] == (float |
255 | (mock_cve.cvss[0]['baseScore']) if mock_cve.cvss else None) |
256 | |
257 | -def test_generate_cves_info_parents(): |
258 | - cves_jammy = { |
259 | - 'CVE-0001-0001': generate_mock_cve(pkgs=dict(), cve_id='CVE-0001-0001'), |
260 | - 'CVE-0001-0002': generate_mock_cve(pkgs=dict(), cve_id='CVE-0001-0002', public_date='2020-08-04 17:00:00 PDT'), |
261 | - } |
262 | - |
263 | - cves_jammy_esm_apps = { |
264 | - 'CVE-0001-0003': generate_mock_cve(pkgs=dict(), cve_id='CVE-0001-0003', public_date='2020-08-04 17:00:00 PST'), |
265 | - } |
266 | - |
267 | - cves_jammy_esm_infra = { |
268 | - 'CVE-0001-0004': generate_mock_cve(pkgs=dict(), cve_id='CVE-0001-0004', cvss=None) |
269 | - } |
270 | - |
271 | - json_gen = EmptyJSONPkgGenerator() |
272 | - json_gen.cves = {'jammy': {}, 'esm-apps/jammy': {}, 'esm-infra/jammy': {}} |
273 | - |
274 | - for cve_id, cve in cves_jammy.items(): |
275 | - json_gen.cves['jammy'][cve_id] = cve |
276 | - |
277 | - for cve_id, cve in cves_jammy_esm_apps.items(): |
278 | - json_gen.cves['esm-apps/jammy'][cve_id] = cve |
279 | - |
280 | - for cve_id, cve in cves_jammy_esm_infra.items(): |
281 | - json_gen.cves['esm-infra/jammy'][cve_id] = cve |
282 | - |
283 | - |
284 | - json_gen._init_ids('jammy') |
285 | - generated_info_cves = json_gen._generate_cves_info() |
286 | - assert len(generated_info_cves) == 2 |
287 | - for cve_id in cves_jammy.keys(): |
288 | - assert cve_id in generated_info_cves.keys() |
289 | - |
290 | - json_gen._init_ids('esm-infra/jammy') |
291 | - json_gen.parent_releases = ['jammy'] |
292 | - generated_info_cves = json_gen._generate_cves_info() |
293 | - assert len(generated_info_cves) == 3 |
294 | - for cve_id in list(cves_jammy.keys()) + list(cves_jammy_esm_infra.keys()): |
295 | - assert cve_id in generated_info_cves.keys() |
296 | - |
297 | - |
298 | - json_gen._init_ids('esm-apps/jammy') |
299 | - json_gen.parent_releases = ['esm-infra/jammy', 'jammy'] |
300 | - generated_info_cves = json_gen._generate_cves_info() |
301 | - assert len(generated_info_cves) == 4 |
302 | - for cve_id in list(cves_jammy.keys()) + list(cves_jammy_esm_infra.keys()) + list(cves_jammy_esm_apps.keys()): |
303 | - assert cve_id in generated_info_cves.keys() |
304 | - |
305 | - |
306 | @pytest.mark.parametrize("status,note,json_status,fixed_version", [ |
307 | ("ignored", "not for us", "vulnerable", None), |
308 | ("needed", "", "vulnerable", None), |
309 | @@ -268,6 +218,7 @@ def test_generate_cve_pkg_info(status, note, json_status, fixed_version): |
310 | cve = generate_mock_cve(pkgs=dict(), cve_id='CVE-0001-0001', priority='critical') |
311 | cve.add_pkg(package, 'jammy', status, note) |
312 | json_gen = EmptyJSONPkgGenerator() |
313 | + json_gen._init_ids('jammy') |
314 | |
315 | info = json_gen._generate_cve_pkg_info(package) |
316 | info = info['CVE-0001-0001'] |
317 | @@ -280,29 +231,31 @@ def test_generate_cve_pkg_info(status, note, json_status, fixed_version): |
318 | generate_mock_usn( |
319 | description='this is a test description', |
320 | timestamp=1708590783, |
321 | - cve_objs={'CVE-0001-0001': None, 'CVE-0001-0002': None}, |
322 | + cve_objs={'jammy':{'CVE-0001-0001': None, 'CVE-0001-0002': None}}, |
323 | lp_bugs=['http://bug1.com', 'http://bug2.com'] |
324 | ), |
325 | generate_mock_usn( |
326 | description='this is a test description', |
327 | timestamp=1708590783, |
328 | + cve_objs={'jammy':{}}, |
329 | lp_bugs=['http://bug1.com', 'http://bug2.com'] |
330 | ), |
331 | generate_mock_usn( |
332 | description='this is a test description', |
333 | timestamp=1708590783, |
334 | - cve_objs={'CVE-0001-0001': None, 'CVE-0001-0002': None} |
335 | + cve_objs={'jammy':{'CVE-0001-0001': None, 'CVE-0001-0002': None}}, |
336 | ), |
337 | ]) |
338 | def test_generate_usn_info(usn): |
339 | # 1708590783 is ~2024-02-22T09:33:03+00:00 |
340 | date = datetime.fromtimestamp(1708590783).isoformat(timespec="seconds") |
341 | json_gen = EmptyJSONPkgGenerator() |
342 | + json_gen._init_ids('jammy') |
343 | |
344 | info = json_gen._generate_usn_info(usn) |
345 | assert info['description'] == usn.description |
346 | assert info['published_at'] == date |
347 | - assert info['related_cves'] == list(usn.cves.keys()) |
348 | + assert info['related_cves'] == list(usn.cves['jammy'].keys()) |
349 | assert info['related_launchpad_bugs'] == usn.lp_bugs |
350 | |
351 | def test_generate_usns_info(): |
352 | @@ -312,7 +265,7 @@ def test_generate_usns_info(): |
353 | id='1000-1', |
354 | description='this is a test description', |
355 | timestamp=1708590783, |
356 | - cve_objs={'CVE-0001-0001': None, 'CVE-0001-0002': None}, |
357 | + cve_objs={'jammy':{'CVE-0001-0001': None, 'CVE-0001-0002': None}}, |
358 | lp_bugs=['http://bug1.com', 'http://bug2.com'] |
359 | ), |
360 | generate_mock_usn( |
361 | @@ -325,7 +278,7 @@ def test_generate_usns_info(): |
362 | id='1000-3', |
363 | description='this is a test description', |
364 | timestamp=1708590783, |
365 | - cve_objs={'CVE-0001-0001': None, 'CVE-0001-0002': None} |
366 | + cve_objs={'jammy':{'CVE-0001-0001': None, 'CVE-0001-0002': None}}, |
367 | )] |
368 | |
369 | wrong_release_usn = generate_mock_usn( |
370 | @@ -333,11 +286,20 @@ def test_generate_usns_info(): |
371 | description='this is a test description', |
372 | timestamp=1708590783, |
373 | releases=['bionic'], |
374 | - cve_objs={'CVE-0001-0001': None, 'CVE-0001-0002': None} |
375 | + cve_objs={'bionic':{'CVE-0001-0001': None, 'CVE-0001-0002': None}}, |
376 | + ) |
377 | + |
378 | + other_release = generate_mock_usn( |
379 | + id='3000-1', |
380 | + description='this is a test description', |
381 | + timestamp=1708590783, |
382 | + releases=['jammy', 'bionic'], |
383 | + cve_objs={'jammy': {'CVE-0001-0001': None, 'CVE-0001-0002': None}, 'bionic': {'CVE-0001-0003'}} |
384 | ) |
385 | |
386 | final_usns = usns.copy() |
387 | final_usns.append(wrong_release_usn) |
388 | + final_usns.append(other_release) |
389 | usns_dict = dict(map(lambda usn: (usn.id, usn), final_usns)) |
390 | json_gen = EmptyJSONPkgGenerator() |
391 | json_gen.usns = usns_dict |
392 | @@ -345,20 +307,25 @@ def test_generate_usns_info(): |
393 | info = json_gen._generate_usns_info() |
394 | |
395 | assert 'USN-2000-1' not in info |
396 | + assert 'USN-3000-1' in info and 'CVE-0001-0003' not in info[f'USN-3000-1']['related_cves'] |
397 | |
398 | for usn in usns: |
399 | assert f'USN-{usn.id}' in info |
400 | assert info[f'USN-{usn.id}']['description'] == usn.description |
401 | assert info[f'USN-{usn.id}']['published_at'] == date |
402 | - assert info[f'USN-{usn.id}']['related_cves'] == list(usn.cves.keys()) |
403 | + if 'jammy' in usn.cves: |
404 | + assert info[f'USN-{usn.id}']['related_cves'] == list(usn.cves['jammy'].keys()) |
405 | + else: |
406 | + assert info[f'USN-{usn.id}']['related_cves'] == [] |
407 | assert info[f'USN-{usn.id}']['related_launchpad_bugs'] == usn.lp_bugs |
408 | + |
409 | |
410 | def test_generate_usns_info_parents(): |
411 | jammy_usns = [generate_mock_usn( |
412 | id='1000-1', |
413 | description='this is a test description', |
414 | timestamp=1708590783, |
415 | - cve_objs={'CVE-0001-0001': None, 'CVE-0001-0002': None}, |
416 | + cve_objs={'jammy': {'CVE-0001-0001': None, 'CVE-0001-0002': None}}, |
417 | lp_bugs=['http://bug1.com', 'http://bug2.com'] |
418 | ), |
419 | generate_mock_usn( |
420 | @@ -371,7 +338,8 @@ def test_generate_usns_info_parents(): |
421 | id='1000-3', |
422 | description='this is a test description', |
423 | timestamp=1708590783, |
424 | - cve_objs={'CVE-0001-0001': None, 'CVE-0001-0002': None} |
425 | + releases=['jammy'], |
426 | + cve_objs={'jammy': {'CVE-0001-0001': None, 'CVE-0001-0002': None}, 'bionic': {'CVE-0001-0003'}} |
427 | )] |
428 | |
429 | jammy_infra_usns = [ |
430 | @@ -379,8 +347,8 @@ def test_generate_usns_info_parents(): |
431 | id='2000-1', |
432 | description='this is a test description', |
433 | timestamp=1708590783, |
434 | - releases=['esm-infra/jammy'], |
435 | - cve_objs={'CVE-0001-0001': None, 'CVE-0001-0002': None} |
436 | + releases=['jammy'], |
437 | + cve_objs={'jammy': {'CVE-0001-0001': None, 'CVE-0001-0002': None}, 'bionic': {'CVE-0001-0003'}} |
438 | ) |
439 | ] |
440 | |
441 | @@ -389,8 +357,8 @@ def test_generate_usns_info_parents(): |
442 | id='3000-1', |
443 | description='this is a test description', |
444 | timestamp=1708590783, |
445 | - releases=['esm-apps/jammy'], |
446 | - cve_objs={'CVE-0001-0001': None, 'CVE-0001-0002': None} |
447 | + releases=['jammy'], |
448 | + cve_objs={'jammy': {'CVE-0001-0001': None, 'CVE-0001-0002': None}, 'bionic': {'CVE-0001-0003'}} |
449 | ) |
450 | ] |
451 | |
452 | @@ -400,22 +368,8 @@ def test_generate_usns_info_parents(): |
453 | json_gen.usns = usns_dict |
454 | json_gen._init_ids('jammy') |
455 | info = json_gen._generate_usns_info() |
456 | - assert len(info.keys()) == 3 |
457 | - for usn in jammy_usns: |
458 | - assert f'USN-{usn.id}' in info |
459 | - |
460 | - json_gen._init_ids('esm-infra/jammy') |
461 | - json_gen.parent_releases = ['jammy'] |
462 | - info = json_gen._generate_usns_info() |
463 | - assert len(info.keys()) == 4 |
464 | - for usn in jammy_usns + jammy_infra_usns: |
465 | - assert f'USN-{usn.id}' in info |
466 | - |
467 | - json_gen._init_ids('esm-apps/jammy') |
468 | - json_gen.parent_releases = ['esm-infra/jammy', 'jammy'] |
469 | - info = json_gen._generate_usns_info() |
470 | assert len(info.keys()) == 5 |
471 | - for usn in jammy_usns + jammy_infra_usns + jammy_apps_usns: |
472 | + for usn in jammy_usns: |
473 | assert f'USN-{usn.id}' in info |
474 | |
475 | def test_generate_usn_pkg_info(): |
476 | @@ -451,9 +405,9 @@ def test_generate_usn_pkg_info(): |
477 | id='1000-1', |
478 | description='this is a test description', |
479 | timestamp=1708590783, |
480 | - cve_objs={'CVE-0001-0001': None, 'CVE-0001-0002': None}, |
481 | + cve_objs={'jammy': {'CVE-0001-0001': None, 'CVE-0001-0002': None}}, |
482 | lp_bugs=['http://bug1.com', 'http://bug2.com'], |
483 | - pkgs_by_rel={'jammy': {'foo': pkg}}, |
484 | + pkgs_by_rel={'jammy': {'foo': (pkg, '1.0.0')}}, |
485 | releases=releases_1 |
486 | ) |
487 | |
488 | @@ -462,13 +416,15 @@ def test_generate_usn_pkg_info(): |
489 | title='Regression', |
490 | description='this is a test description', |
491 | timestamp=1708590783, |
492 | - cve_objs={'CVE-0001-0001': None, 'CVE-0001-0002': None}, |
493 | + cve_objs={'jammy': {'CVE-0001-0001': None, 'CVE-0001-0002': None}}, |
494 | lp_bugs=['http://bug1.com', 'http://bug2.com'], |
495 | - pkgs_by_rel={'jammy': {'foo': pkg}}, |
496 | + pkgs_by_rel={'jammy': {'foo': (pkg, '2.0.0')}}, |
497 | releases=releases_2 |
498 | ) |
499 | |
500 | json_gen = EmptyJSONPkgGenerator() |
501 | + json_gen._init_ids('jammy') |
502 | + |
503 | usns_dict = dict(map(lambda usn: (usn.id, usn), [usn, usn_regression])) |
504 | json_gen.usns = usns_dict |
505 | |
506 | @@ -482,6 +438,7 @@ def test_generate_usn_pkg_info(): |
507 | assert usn_info['USN-1000-1']['source_fixed_version'] == '1.0.0' |
508 | assert usn_reg_info['USN-1000-2']['source_fixed_version'] == '2.0.0' |
509 | |
510 | + json_gen._init_ids('bionic') |
511 | usn_info, usn_reg_info = json_gen._generate_usn_pkg_info(pkg_not) |
512 | |
513 | assert 'USN-1000-1' not in usn_info |
514 | @@ -554,20 +511,20 @@ def test_generate_package_info(mocker): |
515 | id='1000-1', |
516 | description='this is a test description', |
517 | timestamp=1708590783, |
518 | - cve_objs={'CVE-0001-0001': None, 'CVE-0001-0002': None}, |
519 | + cve_objs={'jammy': {'CVE-0001-0001': None, 'CVE-0001-0002': None}}, |
520 | lp_bugs=['http://bug1.com', 'http://bug2.com'], |
521 | - pkgs_by_rel={'jammy': {'foo': pkg}}, |
522 | + pkgs_by_rel={'jammy': {'foo': (pkg, '1.0.0')}}, |
523 | releases=releases_1 |
524 | ) |
525 | |
526 | usn_regression = generate_mock_usn( |
527 | id='1000-2', |
528 | - title='Regression', |
529 | + title='A regression', |
530 | description='this is a test description', |
531 | timestamp=1708590783, |
532 | - cve_objs={'CVE-0001-0001': None, 'CVE-0001-0002': None}, |
533 | + cve_objs={'bionic': {'CVE-0001-0001': None, 'CVE-0001-0002': None}}, |
534 | lp_bugs=['http://bug1.com', 'http://bug2.com'], |
535 | - pkgs_by_rel={'bionic': {'bar': pkg2}}, |
536 | + pkgs_by_rel={'bionic': {'bar': (pkg2, '2.0.0')}}, |
537 | releases=releases_2 |
538 | ) |
539 | |
540 | @@ -644,9 +601,9 @@ def test_generate_packages_info(mocker): |
541 | id='1000-1', |
542 | description='this is a test description', |
543 | timestamp=1708590783, |
544 | - cve_objs={'CVE-0001-0001': None, 'CVE-0001-0002': None}, |
545 | + cve_objs={'jammy': {'CVE-0001-0001': None, 'CVE-0001-0002': None}}, |
546 | lp_bugs=['http://bug1.com', 'http://bug2.com'], |
547 | - pkgs_by_rel={'jammy': {'foo': pkg}}, |
548 | + pkgs_by_rel={'jammy': {'foo': (pkg, '1.0.0')}}, |
549 | releases=releases_1 |
550 | ) |
551 | |
552 | @@ -655,9 +612,9 @@ def test_generate_packages_info(mocker): |
553 | title='Regression', |
554 | description='this is a test description', |
555 | timestamp=1708590783, |
556 | - cve_objs={'CVE-0001-0001': None, 'CVE-0001-0002': None}, |
557 | + cve_objs={'bionic': {'CVE-0001-0001': None, 'CVE-0001-0002': None}}, |
558 | lp_bugs=['http://bug1.com', 'http://bug2.com'], |
559 | - pkgs_by_rel={'bionic': {'bar': pkg2}}, |
560 | + pkgs_by_rel={'bionic': {'bar': (pkg2, '2.0.0')}}, |
561 | releases=releases_2 |
562 | ) |
563 | |
564 | @@ -706,7 +663,7 @@ def test_generate_packages_info_parents(mocker): |
565 | } |
566 | |
567 | releases_infra_jammy = { |
568 | - 'esm-infra/jammy': { |
569 | + 'jammy': { |
570 | 'sources': { |
571 | 'bar': { |
572 | 'version': '2.0.0' |
573 | @@ -716,7 +673,7 @@ def test_generate_packages_info_parents(mocker): |
574 | } |
575 | |
576 | releases_apps_jammy = { |
577 | - 'esm-apps/jammy': { |
578 | + 'jammy': { |
579 | 'sources': { |
580 | 'dodo': { |
581 | 'version': '3.0.0' |
582 | @@ -747,9 +704,9 @@ def test_generate_packages_info_parents(mocker): |
583 | id='1000-1', |
584 | description='this is a test description', |
585 | timestamp=1708590783, |
586 | - cve_objs={'CVE-0001-0001': None, 'CVE-0001-0002': None}, |
587 | + cve_objs={'jammy': {'CVE-0001-0001': None, 'CVE-0001-0002': None}}, |
588 | lp_bugs=['http://bug1.com', 'http://bug2.com'], |
589 | - pkgs_by_rel={'jammy': {'foo': pkg}}, |
590 | + pkgs_by_rel={'jammy': {'foo': (pkg, '1.0.0')}}, |
591 | releases=releases_jammy |
592 | ) |
593 | |
594 | @@ -758,9 +715,9 @@ def test_generate_packages_info_parents(mocker): |
595 | title='Infra', |
596 | description='this is a test description', |
597 | timestamp=1708590783, |
598 | - cve_objs={'CVE-0001-0001': None, 'CVE-0001-0002': None}, |
599 | + cve_objs={'jammy': {'CVE-0001-0001': None, 'CVE-0001-0002': None}}, |
600 | lp_bugs=['http://bug1.com', 'http://bug2.com'], |
601 | - pkgs_by_rel={'esm-infra/jammy': {'bar': pkg2}}, |
602 | + pkgs_by_rel={'jammy': {'bar': (pkg2, '2.0.0')}}, |
603 | releases=releases_infra_jammy |
604 | ) |
605 | |
606 | @@ -769,9 +726,9 @@ def test_generate_packages_info_parents(mocker): |
607 | title='Apps', |
608 | description='this is a test description', |
609 | timestamp=1708590783, |
610 | - cve_objs={'CVE-0001-0001': None, 'CVE-0001-0002': None}, |
611 | + cve_objs={'jammy': {'CVE-0001-0001': None, 'CVE-0001-0002': None}}, |
612 | lp_bugs=['http://bug1.com', 'http://bug2.com'], |
613 | - pkgs_by_rel={'esm-apps/jammy': {'dodo': pkg3}}, |
614 | + pkgs_by_rel={'jammy': {'dodo': (pkg3, '3.0.0')}}, |
615 | releases=releases_apps_jammy |
616 | ) |
617 | |
618 | @@ -787,10 +744,10 @@ def test_generate_packages_info_parents(mocker): |
619 | json_gen = EmptyJSONPkgGenerator() |
620 | usns_dict = dict(map(lambda usn: (usn.id, usn), [usn, usn_infra, usn_apps])) |
621 | json_gen.usns = usns_dict |
622 | - json_gen.cves = {'jammy': {}, 'esm-apps/jammy': {}, 'esm-infra/jammy': {}} |
623 | + json_gen.cves = {'jammy': {}} |
624 | json_gen.cves['jammy']['CVE-0001-0001'] = cve |
625 | - json_gen.cves['esm-infra/jammy']['CVE-0001-0002'] = cve2 |
626 | - json_gen.cves['esm-apps/jammy']['CVE-0001-0003'] = cve3 |
627 | + json_gen.cves['jammy']['CVE-0001-0002'] = cve2 |
628 | + json_gen.cves['jammy']['CVE-0001-0003'] = cve3 |
629 | |
630 | json_gen.packages = { |
631 | 'jammy': { |
632 | @@ -805,25 +762,10 @@ def test_generate_packages_info_parents(mocker): |
633 | } |
634 | } |
635 | |
636 | - json_gen._init_ids('jammy') |
637 | - info = json_gen._generate_packages_info() |
638 | - assert 'foo' in info |
639 | - assert 'bar' not in info |
640 | - assert 'dodo' not in info |
641 | - assert info['foo']['cves']['CVE-0001-0001']['status'] == 'vulnerable' |
642 | - |
643 | json_gen._init_ids('esm-infra/jammy') |
644 | - json_gen.parent_releases = ['jammy'] |
645 | - info = json_gen._generate_packages_info() |
646 | - assert 'foo' in info |
647 | - assert 'bar' in info |
648 | - assert 'dodo' not in info |
649 | - assert info['foo']['cves']['CVE-0001-0001']['status'] == 'vulnerable' |
650 | - assert info['bar']['cves']['CVE-0001-0002']['status'] == 'fixed' |
651 | - assert info['bar']['ubuntu_security_notices']['USN-2000-1']['source_fixed_version'] == '2.0.0' |
652 | + json_gen.parent_releases = ['esm-apps/jammy', 'jammy'] |
653 | + json_gen.orig_parent = 'jammy' |
654 | |
655 | - json_gen._init_ids('esm-apps/jammy') |
656 | - json_gen.parent_releases = ['esm-infra/jammy', 'jammy'] |
657 | info = json_gen._generate_packages_info() |
658 | assert 'foo' in info |
659 | assert 'bar' in info |
660 | @@ -832,8 +774,13 @@ def test_generate_packages_info_parents(mocker): |
661 | assert info['bar']['cves']['CVE-0001-0002']['status'] == 'fixed' |
662 | assert info['dodo']['cves']['CVE-0001-0003']['status'] == 'fixed' |
663 | assert info['foo']['cves']['CVE-0001-0001']['source_fixed_version'] == '4' |
664 | + assert info['bar']['cves']['CVE-0001-0002']['source_fixed_version'] == '1' |
665 | + assert info['dodo']['cves']['CVE-0001-0003']['source_fixed_version'] == '2' |
666 | + assert info['foo']['ubuntu_security_notices']['USN-1000-1']['source_fixed_version'] == '1.0.0' |
667 | + assert info['bar']['ubuntu_security_notices']['USN-2000-1']['source_fixed_version'] == '2.0.0' |
668 | assert info['dodo']['ubuntu_security_notices']['USN-3000-1']['source_fixed_version'] == '3.0.0' |
669 | |
670 | + |
671 | @pytest.mark.parametrize("expand,release,filename", [ |
672 | (False, 'esm-apps/bionic', 'com.ubuntu.bionic.pkg.json'), |
673 | (True, 'esm-apps/bionic', 'com.ubuntu.esm-apps_bionic.pkg.json'), |
tested locally and looks good to me!
thanks!