Merge ~litios/ubuntu-cve-tracker:oval_pkg_parent_support into ubuntu-cve-tracker:master

Proposed by David Fernandez Gonzalez
Status: Merged
Merged at revision: 6a3b15b2839e890e1ce769204a674f23f90f1e57
Proposed branch: ~litios/ubuntu-cve-tracker:oval_pkg_parent_support
Merge into: ubuntu-cve-tracker:master
Diff against target: 240 lines (+54/-50)
2 files modified
scripts/generate-oval (+1/-1)
scripts/oval_lib.py (+53/-49)
Reviewer Review Type Date Requested Status
Eduardo Barretto Approve
Review via email: mp+443550@code.launchpad.net

Description of the change

Previously, ESM-related releases were only generating OVAL data for the packages and versions contained in those ESM PPAs. This PR address this issue so they include the information regarding the parent release.

It has also been added an improvement so the filename generated is based on the class attribute.

To post a comment you must log in.
Revision history for this message
Eduardo Barretto (ebarretto) wrote :

lgtm, thanks!

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/scripts/generate-oval b/scripts/generate-oval
2index e7d13b7..5bab03c 100755
3--- a/scripts/generate-oval
4+++ b/scripts/generate-oval
5@@ -581,7 +581,7 @@ def generate_oval_usn(outdir, usn, usn_release, cve_dir, usn_db_dir, ociprefix=N
6
7 return True
8
9-def generate_oval_package(release, outdir, cve_prefix_dir, pkg_cache, cve_cache, oci, no_progress, packages, pathnames, fixed_only, ociprefix=None, ocioutdir=None):
10+def generate_oval_package(release, outdir, cve_prefix_dir, pkg_cache, cve_cache, oci, no_progress, packages, pathnames, fixed_only, ociprefix='', ocioutdir=None):
11 if not no_progress:
12 print(f'[*] Generating OVAL for packages in release {release}')
13 ov = oval_lib.OvalGeneratorPkg(release, release_name(release), pathnames, packages, not no_progress,pkg_cache=pkg_cache, fixed_only=fixed_only, cve_cache=cve_cache, oval_format='oci' if oci else 'dpkg', outdir=outdir, cve_prefix_dir=cve_prefix_dir, prefix=ociprefix)
14diff --git a/scripts/oval_lib.py b/scripts/oval_lib.py
15index b67ab51..d657cd6 100644
16--- a/scripts/oval_lib.py
17+++ b/scripts/oval_lib.py
18@@ -146,17 +146,15 @@ class OvalGenerator:
19 supported_oval_elements = ('definition', 'test', 'object', 'state', 'variable')
20 generator_version = '1.1'
21 oval_schema_version = '5.11.1'
22- def __init__(self, release, release_name, parent = None, warn_method=False, outdir='./', prefix='', oval_format='dpkg') -> None:
23+ def __init__(self, release, release_name = None, warn_method=False, outdir='./', prefix='', oval_format='dpkg') -> None:
24 self.release = release
25 # e.g. codename for trusty/esm should be trusty
26- self.release_codename = parent if parent else self.release.replace('/', '_')
27+ self.release_codename = cve_lib.release_progenitor(release) if cve_lib.release_progenitor(release) else self.release.replace('/', '_')
28 self.release_name = release_name
29 #self.warn = warn_method or self.warn
30 self.tmpdir = tempfile.mkdtemp(prefix='oval_lib-')
31 self.output_dir = outdir
32 self.oval_format = oval_format
33- self.output_filepath = \
34- '{0}com.ubuntu.{1}.cve.oval.xml'.format(prefix, self.release.replace('/', '_'))
35 self.ns = 'oval:com.ubuntu.{0}'.format(self.release_codename)
36 self.id = 100
37 self.host_def_id = self.id
38@@ -342,12 +340,13 @@ class OvalGenerator:
39 return family_state, state
40
41 class CVEPkgRelEntry:
42- def __init__(self, pkg, cve, status, note) -> None:
43+ def __init__(self, pkg, release, cve, status, note) -> None:
44 self.pkg = pkg
45 self.cve = cve
46 self.orig_status = status
47 self.orig_note = note
48- cve_info = CVEPkgRelEntry.parse_package_status(pkg.rel, pkg.name, status, note, cve.number, None)
49+ self.release = release
50+ cve_info = CVEPkgRelEntry.parse_package_status(self.release, pkg.name, status, note, cve.number, None)
51
52 self.note = cve_info['note']
53 self.status = cve_info['status']
54@@ -456,9 +455,9 @@ class CVE:
55 self.pkg_rel_entries = {}
56 self.pkgs = pkgs
57
58- def add_pkg(self, pkg_object, state, note):
59- cve_pkg_entry = CVEPkgRelEntry(pkg_object, self, state, note)
60- self.pkg_rel_entries[Package.get_unique_id(pkg_object.name, pkg_object.rel)] = cve_pkg_entry
61+ def add_pkg(self, pkg_object, release, state, note):
62+ cve_pkg_entry = CVEPkgRelEntry(pkg_object, release, self, state, note)
63+ self.pkg_rel_entries[pkg_object.name] = cve_pkg_entry
64 self.pkgs.append(pkg_object)
65
66 def __str__(self) -> str:
67@@ -492,10 +491,6 @@ class Package:
68 self.binaries = binaries if binaries else []
69 self.cves = []
70
71- @staticmethod
72- def get_unique_id(name, rel):
73- return f'{name}/{rel}'
74-
75 def add_cve(self, cve) -> None:
76 self.cves.append(cve)
77
78@@ -506,8 +501,8 @@ class Package:
79 return self.__str__()
80
81 class OvalGeneratorPkg(OvalGenerator):
82- def __init__(self, release, release_name, cve_paths, packages, progress, pkg_cache, fixed_only=True, cve_cache=None, cve_prefix_dir=None, parent=None, warn_method=False, outdir='./', prefix='', oval_format='dpkg') -> None:
83- super().__init__(release, release_name, parent, warn_method, outdir, prefix, oval_format)
84+ def __init__(self, release, release_name, cve_paths, packages, progress, pkg_cache, fixed_only=True, cve_cache=None, cve_prefix_dir=None, warn_method=False, outdir='./', prefix='', oval_format='dpkg') -> None:
85+ super().__init__(release, release_name, warn_method, outdir, prefix, oval_format)
86 ###
87 # ID schema: 2204|00001|0001
88 # * The first four digits are the ubuntu release number
89@@ -518,6 +513,8 @@ class OvalGeneratorPkg(OvalGenerator):
90 self.definition_id = release_code * 10 ** 10
91 self.definition_step = 1 * 10 ** 5
92 self.criterion_step = 10
93+ self.output_filepath = \
94+ '{0}com.ubuntu.{1}.pkg.oval.xml'.format(prefix, self.release.replace('/', '_'))
95 self.progress = progress
96 self.cve_cache = cve_cache
97 self.pkg_cache = pkg_cache
98@@ -531,11 +528,10 @@ class OvalGeneratorPkg(OvalGenerator):
99 component = etree.SubElement(advisory, "component")
100 version = etree.SubElement(advisory, "current_version")
101
102- pkg_id = Package.get_unique_id(package.name, self.release)
103 for cve in package.cves:
104- if cve.pkg_rel_entries[pkg_id].status == 'not-vulnerable':
105+ if cve.pkg_rel_entries[package.name].status == 'not-vulnerable':
106 continue
107- elif self.fixed_only and cve.pkg_rel_entries[pkg_id].status != 'fixed':
108+ elif self.fixed_only and cve.pkg_rel_entries[package.name].status != 'fixed':
109 continue
110 cve_obj = self._generate_cve_object(cve)
111 advisory.append(cve_obj)
112@@ -991,7 +987,6 @@ class OvalGeneratorPkg(OvalGenerator):
113 return test, object, var, state
114
115 def _populate_pkg(self, package, root_element):
116- pkg_id = Package.get_unique_id(package.name, self.release)
117 tests = root_element.find("tests")
118 objects = root_element.find("objects")
119 variables = root_element.find("variables")
120@@ -1008,7 +1003,7 @@ class OvalGeneratorPkg(OvalGenerator):
121 cve_added = False
122
123 for cve in package.cves:
124- pkg_rel_entry = cve.pkg_rel_entries[pkg_id]
125+ pkg_rel_entry = cve.pkg_rel_entries[package.name]
126 if pkg_rel_entry.status == 'vulnerable' and not self.fixed_only:
127 cve_added = True
128 if one_time_added_id:
129@@ -1052,7 +1047,6 @@ class OvalGeneratorPkg(OvalGenerator):
130 self._increase_id(is_definition=True)
131
132 def _populate_kernel_pkg(self, package, root_element, running_kernel_id):
133- pkg_id = Package.get_unique_id(package.name, self.release)
134 tests = root_element.find("tests")
135 objects = root_element.find("objects")
136 variables = root_element.find("variables")
137@@ -1075,7 +1069,7 @@ class OvalGeneratorPkg(OvalGenerator):
138 self._add_to_criteria(definition_element, criteria, operator='AND')
139
140 for cve in package.cves:
141- pkg_rel_entry = cve.pkg_rel_entries[pkg_id]
142+ pkg_rel_entry = cve.pkg_rel_entries[package.name]
143 if pkg_rel_entry.status == 'vulnerable' and not self.fixed_only:
144 cve_added = True
145 if one_time_added_id:
146@@ -1104,6 +1098,22 @@ class OvalGeneratorPkg(OvalGenerator):
147 definitions.append(definition_element)
148 self._increase_id(is_definition=True)
149
150+ def _add_new_package(self, package_name, cve, release, cve_data, packages) -> None:
151+ if package_name not in packages:
152+ binaries = self.pkg_cache.get_binarypkgs(package_name, release)
153+ version = ''
154+ if binaries:
155+ version = self.pkg_cache.pkgcache[package_name]['Releases'][release]['source_version']
156+
157+ pkg_obj = Package(package_name, release, binaries, version)
158+ packages[package_name] = pkg_obj
159+
160+ pkg_obj = packages[package_name]
161+ if cve not in pkg_obj.cves:
162+ pkg_obj.cves.append(cve)
163+
164+ cve.add_pkg(pkg_obj, release, cve_data['pkgs'][package_name][release][0],cve_data['pkgs'][package_name][release][1])
165+
166 def _load_pkgs(self, cve_prefix_dir, packages_filter=None) -> None:
167 cve_lib.load_external_subprojects()
168
169@@ -1118,12 +1128,20 @@ class OvalGeneratorPkg(OvalGenerator):
170 )
171
172 packages = {}
173- sources[self.release] = load(releases=[self.release], skip_eol_releases=False)[self.release]
174- orig_name = cve_lib.get_orig_rel_name(self.release)
175- if '/' in orig_name:
176- orig_name = orig_name.split('/', maxsplit=1)[1]
177- source_map_binaries[self.release] = load(data_type='packages',releases=[orig_name], skip_eol_releases=False)[orig_name] \
178- if self.release not in cve_lib.external_releases else {}
179+ releases = [self.release]
180+ current_release = self.release
181+ while(cve_lib.release_parent(current_release)):
182+ current_release = cve_lib.release_parent(current_release)
183+ releases.append(current_release)
184+
185+ for release in releases:
186+ sources[release] = load(releases=[release], skip_eol_releases=False)[release]
187+
188+ orig_name = cve_lib.get_orig_rel_name(release)
189+ if '/' in orig_name:
190+ orig_name = orig_name.split('/', maxsplit=1)[1]
191+ source_map_binaries[release] = load(data_type='packages',releases=[orig_name], skip_eol_releases=False)[orig_name] \
192+ if release not in cve_lib.external_releases else {}
193
194 i = 0
195 for cve_path in cves:
196@@ -1143,22 +1161,11 @@ class OvalGeneratorPkg(OvalGenerator):
197 if packages_filter and pkg not in packages_filter:
198 continue
199
200- if self.release in info['pkgs'][pkg] and \
201- info['pkgs'][pkg][self.release][0] != 'DNE' and \
202- pkg in sources[self.release]:
203- pkg_id = Package.get_unique_id(pkg, self.release)
204- if pkg_id not in packages:
205- binaries = self.pkg_cache.get_binarypkgs(pkg, self.release)
206- version = ''
207- if binaries:
208- version = self.pkg_cache.pkgcache[pkg]['Releases'][self.release]['source_version']
209- pkg_obj = Package(pkg, self.release, binaries, version)
210- packages[pkg_id] = pkg_obj
211-
212- pkg_obj = packages[pkg_id]
213- pkg_obj.cves.append(cve_obj)
214- # add_pkg (pkg, status, note)
215- cve_obj.add_pkg(pkg_obj, info['pkgs'][pkg][self.release][0],info['pkgs'][pkg][self.release][1])
216+ for release in releases:
217+ if pkg in sources[release] and release in info['pkgs'][pkg] and \
218+ info['pkgs'][pkg][release][0] != 'DNE':
219+ self._add_new_package(pkg, cve_obj, release, info, packages)
220+ break
221
222 packages = dict(sorted(packages.items()))
223 if self.progress:
224@@ -1186,14 +1193,11 @@ class OvalGeneratorPkg(OvalGenerator):
225 self._populate_pkg(self.packages[pkg], root_element)
226
227 #etree.indent(xml_tree, level=0) -> only available from Python 3.9
228- filename = f"com.ubuntu.{self.release_codename}.pkg.oval.xml"
229 xmlstr = minidom.parseString(etree.tostring(root_element)).toprettyxml(indent=" ")
230- if self.oval_format == 'oci':
231- filename = f'oci.{filename}'
232
233- with open(os.path.join(self.output_dir, filename), 'w') as file:
234+ with open(os.path.join(self.output_dir, self.output_filepath), 'w') as file:
235 file.write(xmlstr)
236- #xml_tree.write(os.path.join(self.output_dir, filename))
237+ #xml_tree.write(os.path.join(self.output_dir, self.output_filepath))
238 return
239
240 class OvalGeneratorCVE:

Subscribers

People subscribed via source and target branches