Merge ~litios/ubuntu-cve-tracker:aliases-v2 into ubuntu-cve-tracker:master

Proposed by David Fernandez Gonzalez
Status: Merged
Merged at revision: 6429624c17b76980ce95094140c2527fda8b1def
Proposed branch: ~litios/ubuntu-cve-tracker:aliases-v2
Merge into: ubuntu-cve-tracker:master
Diff against target: 264 lines (+116/-39)
5 files modified
scripts/active_edit (+12/-4)
scripts/check-cves (+18/-1)
scripts/check-syntax (+24/-24)
scripts/check-syntax-fixup (+29/-4)
scripts/source_map.py (+33/-6)
Reviewer Review Type Date Requested Status
Alex Murray Approve
Review via email: mp+437199@code.launchpad.net

Description of the change

This MR is to use aliases the other way around as it is right now:
* supported.txt will contain the name of the package in the subproject
* aliases.yaml will contain the aliases for the package name in Ubuntu

Example:

$ cat subprojects/soss/conda-focal/supported.txt| grep cryptography
cryptography
$ cat subprojects/soss/conda-focal/aliases.yaml
---
cryptography: [python-cryptography]

When doing triage, we want to make the process as easy as possible; therefore, the tool will expect that the user always provides the Ubuntu name of the package. It will warn the user if using the subproject name instead of the Ubuntu one (if it exists), as this will break any other aliases in other subprojects.

In case the package doesn't exist in Ubuntu, the tool will warn the user that it exists in a subproject and the person doing triage can provide the subproject name(s) so the CVE gets created.

Example output with check-cves and check-syntax: https://pastebin.canonical.com/p/PyzT5tvjmP/

To post a comment you must log in.
Revision history for this message
David Fernandez Gonzalez (litios) wrote :

It seems like the preview diff is broken, all the changes to CVEs are already merged in master.

Revision history for this message
Alex Murray (alexmurray) wrote :

A few questions inline.

review: Needs Fixing
Revision history for this message
David Fernandez Gonzalez (litios) wrote :

Thanks for the input Alex!

I was relying too much on the user to do the manual work of figuring out the right alias when triaging.

I added some new commits to make it more transparent.

About the multi-versioned packages Steve mentioned, the last commit should also fix the issue.

Revision history for this message
David Fernandez Gonzalez (litios) wrote (last edit ):

I added a final commit to deal with aliases in SOSS.

SOSS package names have the format PACKAGE|VERSION, and that's what the contents of supported.txt are.

Right now, the format of aliases.yaml would be something like this to match it:

"cryptography|1.0.0": ["python-cryptography"],
"cryptography|2.0.0": ["python-cryptography"],
...

but really, whatever is after the | doesn't seem useful for aliases, as the package is always the same. So the proposed format from @ccdm94 was:

"cryptography": ["python-cryptography"],

and that should cover all of the "cryptography|VERSION" listed in `supported.txt`.

Testing: https://pastebin.canonical.com/p/fXYYYN9jmV/

Revision history for this message
Alex Murray (alexmurray) wrote :

LGTM - but one minor query about whether we even need check-syntax-fixup anymore and hence could these changes to it be removed and the file deleted instead?

review: Approve
Revision history for this message
Alex Murray (alexmurray) wrote :

Actually as pointed out by mdeslaur, check-syntax-fixup is still useful for a bunch of use-cases so please ignore those comments.

Revision history for this message
David Fernandez Gonzalez (litios) wrote :

Thanks Alex!

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/scripts/active_edit b/scripts/active_edit
2index 9d0df27..ec36cfe 100755
3--- a/scripts/active_edit
4+++ b/scripts/active_edit
5@@ -43,6 +43,8 @@ for release in cve_lib.all_releases:
6 source_releases.append(release)
7 source = source_map.load(releases=source_releases, skip_eol_releases=False)
8
9+added_rel_pkg = []
10+
11 def pkg_in_rel(pkg,rel):
12 if rel in ['upstream']:
13 return True
14@@ -88,10 +90,12 @@ def _add_pkg(p, fp, fixed, parent, embargoed):
15 if len(fixed[p]) > 2:
16 fixed_in_release_version = fixed[p][2]
17 for rel in ['upstream'] + list(source.keys()):
18+ aliases = source_map.get_aliases_of_ubuntu_package(source, p, rel)
19+
20 # determine default state but override this if pkg_db has a
21 # better one
22 state = "needs-triage"
23- if not pkg_in_rel(p, rel):
24+ if not pkg_in_rel(p, rel) and not aliases:
25 # package doesn't exist in this release - see if it wants a
26 # DNE entry
27 if release_wants_dne(rel):
28@@ -128,9 +132,13 @@ def _add_pkg(p, fp, fixed, parent, embargoed):
29 print('%s_%s: %s' % (rel, p, state), file=fp)
30 # TODO: figure out how to store subproject details for embargoed CVEs
31 elif not embargoed:
32- # add this to subprojects for rel
33- with open(os.path.join(cve_lib.get_external_subproject_cve_dir(rel), cve), "a") as f:
34- print('%s_%s: %s' % (rel, p, state), file=f)
35+ pkgs_to_add = aliases if aliases else [p]
36+ for pkg in pkgs_to_add:
37+ rel_pkgname = rel + '/' + pkg
38+ if not rel_pkgname in added_rel_pkg:
39+ with open(os.path.join(cve_lib.get_external_subproject_cve_dir(rel), cve), "a") as f:
40+ print('%s_%s: %s' % (rel, pkg, state), file=f)
41+ added_rel_pkg.append(rel_pkgname)
42
43 def add_pkg(p, fp, fixed, parent, embargoed):
44 # skip packages which don't actually exist in any release
45diff --git a/scripts/check-cves b/scripts/check-cves
46index 6eb9f58..2bc15d2 100755
47--- a/scripts/check-cves
48+++ b/scripts/check-cves
49@@ -884,9 +884,26 @@ class CVEHandler(xml.sax.handler.ContentHandler):
50 external_subprojects = {}
51 for subproject in cve_lib.external_releases:
52 if subproject in source:
53+ aliases = source_map.get_all_aliases(source, subproject)
54 for hint in software_hints_from_cve_description:
55- if hint in source[subproject] and hint not in common_words:
56+ if hint in common_words:
57+ continue
58+
59+ if hint in source[subproject]:
60+ if 'aliases' in source[subproject][hint]:
61+ external_subprojects.setdefault(subproject, set()).add(','.join(source[subproject][hint]['aliases']))
62+ else:
63+ external_subprojects.setdefault(subproject, set()).add(hint)
64+ elif hint in aliases:
65 external_subprojects.setdefault(subproject, set()).add(hint)
66+ else:
67+ pkgs = source_map.get_packages_from_generic_name(source, hint, subproject)
68+ for pkg in pkgs:
69+ if 'aliases' in source[subproject][pkg]:
70+ external_subprojects.setdefault(subproject, set()).add(','.join(source[subproject][pkg]['aliases']))
71+ else:
72+ external_subprojects.setdefault(subproject, set()).add(pkg)
73+
74 return external_subprojects
75
76 def display_cve(self, cve, file=sys.stdout, line_prefix=None, wrap_desc=False):
77diff --git a/scripts/check-syntax b/scripts/check-syntax
78index def63e3..4fb0cf8 100755
79--- a/scripts/check-syntax
80+++ b/scripts/check-syntax
81@@ -429,35 +429,35 @@ for cve in args:
82
83 # Check aliases
84 for rel in all_required_releases:
85- if rel in source and pkg in source[rel] and \
86- 'aliases' in source[rel][pkg]:
87- aliases_releases.add(rel)
88-
89- # This package-release uses aliases,
90- # it shouldn't be listed
91- if rel in listed_releases and pkg \
92- not in source[rel][pkg]['aliases']:
93- filename = srcmap["pkgs"][pkg][nearby_rel][0]
94- linenum = srcmap["pkgs"][pkg][nearby_rel][1]
95- print(
96- "%s: %d: package '%s' not in '%s'"
97- % (filename, linenum, pkg, rel),
98- file=sys.stderr,
99- )
100-
101- failed = 0
102- for alias in source[rel][pkg]['aliases']:
103- if alias not in data["pkgs"].keys():
104+ if rel in source:
105+ aliases = source_map.get_aliases_of_ubuntu_package(source, pkg, rel)
106+ if aliases:
107+ if rel in listed_releases and pkg \
108+ not in aliases:
109 filename = srcmap["pkgs"][pkg][nearby_rel][0]
110 linenum = srcmap["pkgs"][pkg][nearby_rel][1]
111 print(
112- "%s: %d: %s missing release '%s'"
113- # put the error on a line near where this entry should go
114- % (filename, linenum, alias, rel),
115+ "%s: %d: package '%s' not in '%s'"
116+ % (filename, linenum, pkg, rel),
117 file=sys.stderr,
118 )
119- cve_okay = False
120- failed += 1
121+
122+ aliases_releases.add(rel)
123+
124+ # This package-release uses aliases,
125+ # it shouldn't be listed
126+
127+ for alias in aliases:
128+ if alias not in data["pkgs"].keys():
129+ filename = srcmap["pkgs"][pkg][nearby_rel][0]
130+ linenum = srcmap["pkgs"][pkg][nearby_rel][1]
131+ print(
132+ "%s: %d: %s missing release '%s'"
133+ # put the error on a line near where this entry should go
134+ % (filename, linenum, alias, rel),
135+ file=sys.stderr,
136+ )
137+ cve_okay = False
138
139 missing_releases = all_required_releases - listed_releases - aliases_releases
140 nearby_rel = list(listed_releases - missing_releases)[0]
141diff --git a/scripts/check-syntax-fixup b/scripts/check-syntax-fixup
142index c7c77c2..697368c 100755
143--- a/scripts/check-syntax-fixup
144+++ b/scripts/check-syntax-fixup
145@@ -59,11 +59,31 @@ def delete_from_file(filename: str, linenum: int, dryrun=False, verbose=False):
146 else:
147 print("%s: %d: would delete this line" % (os.path.relpath(filename), linenum))
148
149+
150+def identify_subproject_line_number(filename: str, pkg: str, rel: str):
151+ # file may not already exist
152+ contents = []
153+ try:
154+ with open(filename, "r") as f:
155+ contents = f.readlines()
156+ except FileNotFoundError:
157+ pass
158+
159+ for linenum,line in enumerate(contents):
160+ line_rel, line_pkg = line.split(":")[0].split('_')
161+ if pkg == line_pkg and rel == line_rel:
162+ return linenum + 1
163+
164+ return -1
165+
166 def get_pkg_rel_from_msg(msg):
167 parts = msg.split(" ")
168 if 'DOES exist' in msg or 'not in' in msg:
169 pkg = parts[1].replace("'", "")
170 rel = parts[-1].replace("'", "")
171+ elif 'unknown package' in msg:
172+ pkg = parts[2].replace("'", "")
173+ rel = parts[-1].replace("'", "")
174 else:
175 pkg = parts[0]
176 rel = parts[-1].replace("'", "")
177@@ -153,8 +173,11 @@ for line in args.infile:
178 cve = os.path.join(
179 cve_lib.get_external_subproject_cve_dir(rel), os.path.basename(cve)
180 )
181- # linenum is only relevant to the original cve file
182- linenum = 1
183+ linenum = identify_subproject_line_number(cve, pkg, rel)
184+ if linenum == -1:
185+ if 'DOES exist' in msg:
186+ continue
187+ linenum = 1 # We are inserting
188
189 # Remove the 'DNE' line before adding the new one
190 if 'DOES exist' in msg:
191@@ -171,8 +194,10 @@ for line in args.infile:
192 cve = os.path.join(
193 cve_lib.get_external_subproject_cve_dir(rel), os.path.basename(cve)
194 )
195- # linenum is only relevant to the original cve file
196- linenum = 1
197+ linenum = identify_subproject_line_number(cve, pkg, rel)
198+ if linenum == -1:
199+ print(line, file=sys.stderr)
200+ continue
201
202 # delete this line since
203 delete_from_file(cve, linenum, args.dry_run, args.verbose)
204diff --git a/scripts/source_map.py b/scripts/source_map.py
205index 311c1f6..616c5ec 100755
206--- a/scripts/source_map.py
207+++ b/scripts/source_map.py
208@@ -423,6 +423,29 @@ def get_built_using_header():
209 header += "\n" + "-" * 78
210 return header
211
212+def get_all_aliases(sources, rel):
213+ aliases = []
214+ for pkg in sources[rel]:
215+ if 'aliases' in sources[rel][pkg]:
216+ for alias in sources[rel][pkg]['aliases']:
217+ aliases.append(alias)
218+ return aliases
219+
220+def get_aliases_of_ubuntu_package(sources, pkg_name, rel_name):
221+ aliases = []
222+ for rel in sources:
223+ for pkg in sources[rel]:
224+ if rel == rel_name and 'aliases' in sources[rel][pkg]:
225+ if pkg_name in sources[rel][pkg]['aliases']:
226+ aliases.append(pkg)
227+ return aliases
228+
229+def get_packages_from_generic_name(sources, generic_name, rel):
230+ pkgs = []
231+ for pkg in sources[rel]:
232+ if 'generic_name' in sources[rel][pkg] and sources[rel][pkg]['generic_name'] == generic_name:
233+ pkgs.append(pkg)
234+ return pkgs
235
236 def load_subprojects_lists(releases=None):
237 map = dict()
238@@ -471,17 +494,21 @@ def load_subprojects_lists(releases=None):
239 map[rel][pkg]['pocket'] = ''
240 map[rel][pkg]['section'] = 'main'
241
242+ if '|' in pkg:
243+ main_package_name = pkg.split('|')[0]
244+ map[rel][pkg]['generic_name'] = main_package_name
245+
246 if 'aliases' in details:
247 with open(details['aliases'], 'r') as file:
248 aliases = yaml.safe_load(file)
249
250 for pkg in aliases:
251- if pkg in map[rel]:
252- map[rel][pkg]['aliases'] = aliases[pkg]
253- #else:
254- # print("WARN: pkg %s found in aliases but not in supported list for %s. Skipping" % (pkg, rel))
255- else:
256- pass
257+ for src_pkg in map[rel]:
258+ if pkg == src_pkg or \
259+ ('generic_name' in map[rel][src_pkg] and pkg == map[rel][src_pkg]['generic_name']):
260+ map[rel][src_pkg]['aliases'] = aliases[pkg]
261+ #else:
262+ # print("WARN: pkg %s found in aliases but not in supported list for %s. Skipping" % (pkg, rel))
263
264 return map
265

Subscribers

People subscribed via source and target branches