Merge ~andrey-fedoseev/launchpad:more-vulnerability-dates-new into launchpad:master
- Git
- lp:~andrey-fedoseev/launchpad
- more-vulnerability-dates-new
- Merge into master
Proposed by
Andrey Fedoseev
Status: | Merged |
---|---|
Approved by: | Andrey Fedoseev |
Approved revision: | 4c357c5f6df0e6177d38c3b195a61514aba720bf |
Merge reported by: | Otto Co-Pilot |
Merged at revision: | not available |
Proposed branch: | ~andrey-fedoseev/launchpad:more-vulnerability-dates-new |
Merge into: | launchpad:master |
Diff against target: |
396 lines (+121/-67) 7 files modified
lib/contrib/cve_lib.py (+0/-17) lib/lp/bugs/interfaces/vulnerability.py (+26/-0) lib/lp/bugs/model/vulnerability.py (+14/-0) lib/lp/bugs/scripts/tests/test_uct.py (+46/-21) lib/lp/bugs/scripts/uct/models.py (+12/-16) lib/lp/bugs/scripts/uct/uctexport.py (+3/-3) lib/lp/bugs/scripts/uct/uctimport.py (+20/-10) |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Colin Watson (community) | Approve | ||
Review via email: mp+429006@code.launchpad.net |
Commit message
Add `Vulnerability.
Description of the change
Update the UCT import/export scripts accordingly
To post a comment you must log in.
Revision history for this message
Colin Watson (cjwatson) : | # |
review:
Approve
Revision history for this message
Colin Watson (cjwatson) : | # |
Revision history for this message
Andrey Fedoseev (andrey-fedoseev) : | # |
Revision history for this message
Colin Watson (cjwatson) : | # |
Revision history for this message
Andrey Fedoseev (andrey-fedoseev) wrote : | # |
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | diff --git a/lib/contrib/cve_lib.py b/lib/contrib/cve_lib.py |
2 | index da211fd..c7e6210 100644 |
3 | --- a/lib/contrib/cve_lib.py |
4 | +++ b/lib/contrib/cve_lib.py |
5 | @@ -1472,23 +1472,6 @@ def load_cve(cve, strict=False, srcmap=None): |
6 | if "Priority" not in data: |
7 | data.setdefault("Priority", "untriaged") |
8 | srcmap.setdefault("Priority", (cve, 1)) |
9 | - # Perform override fields |
10 | - if "PublicDateAtUSN" in data: |
11 | - data["PublicDate"] = data["PublicDateAtUSN"] |
12 | - srcmap["PublicDate"] = srcmap["PublicDateAtUSN"] |
13 | - if ( |
14 | - "CRD" in data |
15 | - and data["CRD"].strip() != "" |
16 | - and data["PublicDate"] != data["CRD"] |
17 | - ): |
18 | - if cve.startswith("embargoed"): |
19 | - print( |
20 | - "%s: %d: adjusting PublicDate to use CRD: %s" |
21 | - % (cve, linenum, data["CRD"]), |
22 | - file=sys.stderr, |
23 | - ) |
24 | - data["PublicDate"] = data["CRD"] |
25 | - srcmap["PublicDate"] = srcmap["CRD"] |
26 | |
27 | # entries need an upstream entry if any entries are from the internal |
28 | # list of subprojects |
29 | diff --git a/lib/lp/bugs/interfaces/vulnerability.py b/lib/lp/bugs/interfaces/vulnerability.py |
30 | index 9d8292a..474309f 100644 |
31 | --- a/lib/lp/bugs/interfaces/vulnerability.py |
32 | +++ b/lib/lp/bugs/interfaces/vulnerability.py |
33 | @@ -282,6 +282,27 @@ class IVulnerabilityEditableAttributes(Interface): |
34 | as_of="devel", |
35 | ) |
36 | |
37 | + date_notice_issued = exported( |
38 | + Datetime( |
39 | + title=_( |
40 | + "Date when a security notice was issued for this " |
41 | + "vulnerability." |
42 | + ), |
43 | + required=False, |
44 | + readonly=False, |
45 | + ), |
46 | + as_of="devel", |
47 | + ) |
48 | + |
49 | + date_coordinated_release = exported( |
50 | + Datetime( |
51 | + title=_("Coordinated Release Date."), |
52 | + required=False, |
53 | + readonly=False, |
54 | + ), |
55 | + as_of="devel", |
56 | + ) |
57 | + |
58 | |
59 | class IVulnerabilityEdit(Interface): |
60 | """`IVulnerability` attributes that require launchpad.Edit.""" |
61 | @@ -315,6 +336,8 @@ class IVulnerabilitySet(Interface): |
62 | mitigation=None, |
63 | importance_explanation=None, |
64 | date_made_public=None, |
65 | + date_notice_issued=None, |
66 | + date_coordinated_release=None, |
67 | ): |
68 | """Return a new vulnerability. |
69 | |
70 | @@ -330,6 +353,9 @@ class IVulnerabilitySet(Interface): |
71 | :param importance_explanation: Used to explain why our importance |
72 | differs from somebody else's CVSS score. |
73 | :param date_made_public: The date this vulnerability was made public. |
74 | + :param date_coordinated_release: Date when a security notice was issued |
75 | + for this vulnerability. |
76 | + :param date_notice_issued: Coordinated Release Date. |
77 | """ |
78 | |
79 | def findByIds(vulnerability_ids, visible_by_user=None): |
80 | diff --git a/lib/lp/bugs/model/vulnerability.py b/lib/lp/bugs/model/vulnerability.py |
81 | index d8d00a7..075fba8 100644 |
82 | --- a/lib/lp/bugs/model/vulnerability.py |
83 | +++ b/lib/lp/bugs/model/vulnerability.py |
84 | @@ -98,6 +98,12 @@ class Vulnerability(StormBase, BugLinkTargetMixin, InformationTypeMixin): |
85 | date_made_public = DateTime( |
86 | name="date_made_public", tzinfo=pytz.UTC, allow_none=True |
87 | ) |
88 | + date_notice_issued = DateTime( |
89 | + name="date_notice_issued", tzinfo=pytz.UTC, allow_none=True |
90 | + ) |
91 | + date_coordinated_release = DateTime( |
92 | + name="date_coordinated_release", tzinfo=pytz.UTC, allow_none=True |
93 | + ) |
94 | |
95 | creator_id = Int(name="creator", allow_none=False) |
96 | creator = Reference(creator_id, "Person.id") |
97 | @@ -115,6 +121,8 @@ class Vulnerability(StormBase, BugLinkTargetMixin, InformationTypeMixin): |
98 | mitigation=None, |
99 | importance_explanation=None, |
100 | date_made_public=None, |
101 | + date_notice_issued=None, |
102 | + date_coordinated_release=None, |
103 | ): |
104 | super().__init__() |
105 | self.distribution = distribution |
106 | @@ -132,6 +140,8 @@ class Vulnerability(StormBase, BugLinkTargetMixin, InformationTypeMixin): |
107 | self.mitigation = mitigation |
108 | self.importance_explanation = importance_explanation |
109 | self.date_made_public = date_made_public |
110 | + self.date_notice_issued = date_notice_issued |
111 | + self.date_coordinated_release = date_coordinated_release |
112 | self.date_created = UTC_NOW |
113 | |
114 | @property |
115 | @@ -323,6 +333,8 @@ class VulnerabilitySet: |
116 | mitigation=None, |
117 | importance_explanation=None, |
118 | date_made_public=None, |
119 | + date_notice_issued=None, |
120 | + date_coordinated_release=None, |
121 | ): |
122 | """See `IVulnerabilitySet`.""" |
123 | store = IStore(Vulnerability) |
124 | @@ -338,6 +350,8 @@ class VulnerabilitySet: |
125 | information_type=information_type, |
126 | importance_explanation=importance_explanation, |
127 | date_made_public=date_made_public, |
128 | + date_notice_issued=date_notice_issued, |
129 | + date_coordinated_release=date_coordinated_release, |
130 | ) |
131 | store.add(vulnerability) |
132 | vulnerability._reconcileAccess() |
133 | diff --git a/lib/lp/bugs/scripts/tests/test_uct.py b/lib/lp/bugs/scripts/tests/test_uct.py |
134 | index 00f995d..71b1abb 100644 |
135 | --- a/lib/lp/bugs/scripts/tests/test_uct.py |
136 | +++ b/lib/lp/bugs/scripts/tests/test_uct.py |
137 | @@ -162,7 +162,7 @@ class TestUCTRecord(TestCase): |
138 | self.assertEqual(load_from.read_text(), saved_to_path.read_text()) |
139 | |
140 | |
141 | -class TextCVE(TestCaseWithFactory): |
142 | +class TestCVE(TestCaseWithFactory): |
143 | |
144 | layer = ZopelessDatabaseLayer |
145 | maxDiff = None |
146 | @@ -296,14 +296,14 @@ class TextCVE(TestCaseWithFactory): |
147 | |
148 | self.cve = CVE( |
149 | sequence="CVE-2022-23222", |
150 | - crd=datetime.datetime( |
151 | - 2020, 1, 14, 8, 15, tzinfo=datetime.timezone.utc |
152 | + date_made_public=datetime.datetime( |
153 | + 2022, 1, 14, 8, 15, tzinfo=datetime.timezone.utc |
154 | ), |
155 | - public_date_at_USN=datetime.datetime( |
156 | + date_notice_issued=datetime.datetime( |
157 | 2021, 1, 14, 8, 15, tzinfo=datetime.timezone.utc |
158 | ), |
159 | - public_date=datetime.datetime( |
160 | - 2022, 1, 14, 8, 15, tzinfo=datetime.timezone.utc |
161 | + date_coordinated_release=datetime.datetime( |
162 | + 2020, 1, 14, 8, 15, tzinfo=datetime.timezone.utc |
163 | ), |
164 | distro_packages=[ |
165 | CVE.DistroPackage( |
166 | @@ -480,14 +480,17 @@ class TestUCTImporterExporter(TestCaseWithFactory): |
167 | ) |
168 | |
169 | self.lp_cve = self.factory.makeCVE("2022-23222") |
170 | - self.now = datetime.datetime.now(datetime.timezone.utc).replace( |
171 | - microsecond=0 |
172 | - ) |
173 | self.cve = CVE( |
174 | sequence="CVE-2022-23222", |
175 | - crd=None, |
176 | - public_date=self.now, |
177 | - public_date_at_USN=None, |
178 | + date_made_public=datetime.datetime( |
179 | + 2022, 1, 14, 8, 15, tzinfo=datetime.timezone.utc |
180 | + ), |
181 | + date_notice_issued=datetime.datetime( |
182 | + 2021, 1, 14, 8, 15, tzinfo=datetime.timezone.utc |
183 | + ), |
184 | + date_coordinated_release=datetime.datetime( |
185 | + 2020, 1, 14, 8, 15, tzinfo=datetime.timezone.utc |
186 | + ), |
187 | distro_packages=[ |
188 | CVE.DistroPackage( |
189 | package=self.ubuntu_package, |
190 | @@ -683,6 +686,13 @@ class TestUCTImporterExporter(TestCaseWithFactory): |
191 | self.assertEqual( |
192 | cve.date_made_public, vulnerability.date_made_public |
193 | ) |
194 | + self.assertEqual( |
195 | + cve.date_notice_issued, vulnerability.date_notice_issued |
196 | + ) |
197 | + self.assertEqual( |
198 | + cve.date_coordinated_release, |
199 | + vulnerability.date_coordinated_release, |
200 | + ) |
201 | self.assertEqual([bug], vulnerability.bugs) |
202 | |
203 | def checkLaunchpadCve(self, lp_cve: CveModel, cve: CVE): |
204 | @@ -693,10 +703,12 @@ class TestUCTImporterExporter(TestCaseWithFactory): |
205 | |
206 | def checkCVE(self, expected: CVE, actual: CVE): |
207 | self.assertEqual(expected.sequence, actual.sequence) |
208 | - self.assertEqual(expected.crd, actual.crd) |
209 | - self.assertEqual(expected.public_date, actual.public_date) |
210 | + self.assertEqual(expected.date_made_public, actual.date_made_public) |
211 | + self.assertEqual( |
212 | + expected.date_notice_issued, actual.date_notice_issued |
213 | + ) |
214 | self.assertEqual( |
215 | - expected.public_date_at_USN, actual.public_date_at_USN |
216 | + expected.date_coordinated_release, actual.date_coordinated_release |
217 | ) |
218 | self.assertListEqual(expected.distro_packages, actual.distro_packages) |
219 | self.assertListEqual(expected.series_packages, actual.series_packages) |
220 | @@ -970,14 +982,27 @@ class TestUCTImporterExporter(TestCaseWithFactory): |
221 | importer.import_cve(self.cve) |
222 | self.assertIsNone(importer._find_existing_bug(self.cve, self.lp_cve)) |
223 | |
224 | - def test_naive_date_made_public(self): |
225 | + def test_naive_dates(self): |
226 | cve = self.cve |
227 | - cve.public_date = cve.public_date.replace(tzinfo=None) |
228 | - bug = self.importer.create_bug(cve, self.lp_cve) |
229 | - self.assertEqual( |
230 | - UTC, |
231 | - bug.vulnerabilities[0].date_made_public.tzinfo, |
232 | + cve.date_made_public = cve.date_made_public.replace(tzinfo=None) |
233 | + cve.date_notice_issued = cve.date_notice_issued.replace(tzinfo=None) |
234 | + cve.date_coordinated_release = cve.date_coordinated_release.replace( |
235 | + tzinfo=None |
236 | ) |
237 | + bug = self.importer.create_bug(cve, self.lp_cve) |
238 | + for date in ( |
239 | + bug.vulnerabilities[0].date_made_public, |
240 | + bug.vulnerabilities[0].date_notice_issued, |
241 | + bug.vulnerabilities[0].date_coordinated_release, |
242 | + ): |
243 | + self.assertEqual(UTC, date.tzinfo) |
244 | + self.importer.update_bug(bug, cve, self.lp_cve) |
245 | + for date in ( |
246 | + bug.vulnerabilities[0].date_made_public, |
247 | + bug.vulnerabilities[0].date_notice_issued, |
248 | + bug.vulnerabilities[0].date_coordinated_release, |
249 | + ): |
250 | + self.assertEqual(UTC, date.tzinfo) |
251 | |
252 | def test_make_cve_from_bug(self): |
253 | self.importer.import_cve(self.cve) |
254 | diff --git a/lib/lp/bugs/scripts/uct/models.py b/lib/lp/bugs/scripts/uct/models.py |
255 | index 440f79d..4234fdd 100644 |
256 | --- a/lib/lp/bugs/scripts/uct/models.py |
257 | +++ b/lib/lp/bugs/scripts/uct/models.py |
258 | @@ -483,9 +483,9 @@ class CVE: |
259 | def __init__( |
260 | self, |
261 | sequence: str, |
262 | - crd: Optional[datetime], |
263 | - public_date: Optional[datetime], |
264 | - public_date_at_USN: Optional[datetime], |
265 | + date_made_public: Optional[datetime], |
266 | + date_notice_issued: Optional[datetime], |
267 | + date_coordinated_release: Optional[datetime], |
268 | distro_packages: List[DistroPackage], |
269 | series_packages: List[SeriesPackage], |
270 | upstream_packages: List[UpstreamPackage], |
271 | @@ -502,9 +502,9 @@ class CVE: |
272 | cvss: List[CVSS], |
273 | ): |
274 | self.sequence = sequence |
275 | - self.crd = crd |
276 | - self.public_date = public_date |
277 | - self.public_date_at_USN = public_date_at_USN |
278 | + self.date_made_public = date_made_public |
279 | + self.date_notice_issued = date_notice_issued |
280 | + self.date_coordinated_release = date_coordinated_release |
281 | self.distro_packages = distro_packages |
282 | self.series_packages = series_packages |
283 | self.upstream_packages = upstream_packages |
284 | @@ -614,9 +614,9 @@ class CVE: |
285 | |
286 | return cls( |
287 | sequence=uct_record.candidate, |
288 | - crd=uct_record.crd, |
289 | - public_date=uct_record.public_date, |
290 | - public_date_at_USN=uct_record.public_date_at_USN, |
291 | + date_made_public=uct_record.public_date, |
292 | + date_notice_issued=uct_record.public_date_at_USN, |
293 | + date_coordinated_release=uct_record.crd, |
294 | distro_packages=distro_packages, |
295 | series_packages=series_packages, |
296 | upstream_packages=upstream_packages, |
297 | @@ -728,9 +728,9 @@ class CVE: |
298 | bugs=self.bug_urls, |
299 | cvss=self.cvss, |
300 | candidate=self.sequence, |
301 | - crd=self.crd, |
302 | - public_date=self.public_date, |
303 | - public_date_at_USN=self.public_date_at_USN, |
304 | + crd=self.date_coordinated_release, |
305 | + public_date=self.date_made_public, |
306 | + public_date_at_USN=self.date_notice_issued, |
307 | description=self.description, |
308 | discovered_by=self.discovered_by, |
309 | mitigation=self.mitigation, |
310 | @@ -741,10 +741,6 @@ class CVE: |
311 | packages=list(packages_by_name.values()), |
312 | ) |
313 | |
314 | - @property |
315 | - def date_made_public(self): |
316 | - return self.crd or self.public_date_at_USN or self.public_date |
317 | - |
318 | @cachedproperty |
319 | def affected_distributions(self) -> Set[Distribution]: |
320 | return {p.package.distribution for p in self.distro_packages} |
321 | diff --git a/lib/lp/bugs/scripts/uct/uctexport.py b/lib/lp/bugs/scripts/uct/uctexport.py |
322 | index 65e274c..f14d994 100644 |
323 | --- a/lib/lp/bugs/scripts/uct/uctexport.py |
324 | +++ b/lib/lp/bugs/scripts/uct/uctexport.py |
325 | @@ -174,9 +174,9 @@ class UCTExporter: |
326 | |
327 | return CVE( |
328 | sequence="CVE-{}".format(lp_cve.sequence), |
329 | - crd=None, # TODO: fix this |
330 | - public_date=vulnerability.date_made_public, |
331 | - public_date_at_USN=None, # TODO: fix this |
332 | + date_made_public=vulnerability.date_made_public, |
333 | + date_notice_issued=vulnerability.date_notice_issued, |
334 | + date_coordinated_release=vulnerability.date_coordinated_release, |
335 | distro_packages=distro_packages, |
336 | series_packages=series_packages, |
337 | upstream_packages=upstream_packages, |
338 | diff --git a/lib/lp/bugs/scripts/uct/uctimport.py b/lib/lp/bugs/scripts/uct/uctimport.py |
339 | index 5f94703..87d6b0d 100644 |
340 | --- a/lib/lp/bugs/scripts/uct/uctimport.py |
341 | +++ b/lib/lp/bugs/scripts/uct/uctimport.py |
342 | @@ -296,21 +296,15 @@ class UCTImporter: |
343 | :param distribution: a `Distribution` affected by the vulnerability |
344 | :return: a Vulnerability |
345 | """ |
346 | - date_made_public = cve.date_made_public |
347 | - if date_made_public.tzinfo is None: |
348 | - date_made_public = date_made_public.replace(tzinfo=timezone.utc) |
349 | vulnerability = getUtility(IVulnerabilitySet).new( |
350 | distribution=distribution, |
351 | - creator=bug.owner, |
352 | - cve=lp_cve, |
353 | status=cve.status, |
354 | - description=cve.ubuntu_description, |
355 | - notes=cve.notes, |
356 | - mitigation=cve.mitigation, |
357 | importance=cve.importance, |
358 | + creator=bug.owner, |
359 | information_type=InformationType.PUBLICSECURITY, |
360 | - date_made_public=date_made_public, |
361 | + cve=lp_cve, |
362 | ) # type: Vulnerability |
363 | + self._update_vulnerability(vulnerability, cve) |
364 | |
365 | vulnerability.linkBug(bug, bug.owner) |
366 | |
367 | @@ -333,12 +327,28 @@ class UCTImporter: |
368 | :param vulnerability: `Vulnerability` model to be updated |
369 | :param cve: `CVE` with information from UCT |
370 | """ |
371 | + date_made_public = cve.date_made_public |
372 | + if date_made_public.tzinfo is None: |
373 | + date_made_public = date_made_public.replace(tzinfo=timezone.utc) |
374 | + date_notice_issued = cve.date_notice_issued |
375 | + if date_notice_issued.tzinfo is None: |
376 | + date_notice_issued = date_notice_issued.replace( |
377 | + tzinfo=timezone.utc |
378 | + ) |
379 | + date_coordinated_release = cve.date_coordinated_release |
380 | + if date_coordinated_release.tzinfo is None: |
381 | + date_coordinated_release = date_coordinated_release.replace( |
382 | + tzinfo=timezone.utc |
383 | + ) |
384 | + |
385 | vulnerability.status = cve.status |
386 | vulnerability.description = cve.ubuntu_description |
387 | vulnerability.notes = cve.notes |
388 | vulnerability.mitigation = cve.mitigation |
389 | vulnerability.importance = cve.importance |
390 | - vulnerability.date_made_public = cve.date_made_public |
391 | + vulnerability.date_made_public = date_made_public |
392 | + vulnerability.date_notice_issued = date_notice_issued |
393 | + vulnerability.date_coordinated_release = date_coordinated_release |
394 | |
395 | def _assign_bug_tasks( |
396 | self, bug: BugModel, assignee: Optional[Person] |
Colin,
Using different date values in tests helped to find an issue with `cve_lib`: it used to override PublicDate with PublicDateAtUSN or CRD when reading data from files.
I disabled this behaviour in our copy of `cve_lib` to preserve all original date values during import.