Merge ~lgp171188/launchpad:revert-cve-model-changes into launchpad:master

Proposed by Guruprasad
Status: Merged
Approved by: Guruprasad
Approved revision: e2aa76d6d69bde6129a71d5c50e6146304e8dc18
Merge reported by: Otto Co-Pilot
Merged at revision: not available
Proposed branch: ~lgp171188/launchpad:revert-cve-model-changes
Merge into: launchpad:master
Diff against target: 374 lines (+8/-256)
4 files modified
lib/lp/bugs/interfaces/cve.py (+1/-38)
lib/lp/bugs/model/cve.py (+4/-38)
lib/lp/bugs/tests/test_cve.py (+1/-168)
lib/lp/testing/factory.py (+2/-12)
Reviewer Review Type Date Requested Status
Guruprasad Approve
Review via email: mp+416676@code.launchpad.net

Commit message

Revert "Add new fields and methods to ICve and Cve"

This reverts commit 2d216ac658b2bd01c02d98bfcf1649d3fc767e48
as the corresponding DB changes haven't been merged to
the master branch yet.

To post a comment you must log in.
Revision history for this message
Guruprasad (lgp171188) wrote :

Self-approving since this is a trivial revert.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
diff --git a/lib/lp/bugs/interfaces/cve.py b/lib/lp/bugs/interfaces/cve.py
index 3a860da..2ba5a53 100644
--- a/lib/lp/bugs/interfaces/cve.py
+++ b/lib/lp/bugs/interfaces/cve.py
@@ -30,15 +30,12 @@ from zope.interface import (
30from zope.schema import (30from zope.schema import (
31 Choice,31 Choice,
32 Datetime,32 Datetime,
33 Dict,
34 Int,33 Int,
35 Text,
36 TextLine,34 TextLine,
37 )35 )
3836
39from lp import _37from lp import _
40from lp.app.validators.validation import valid_cve_sequence38from lp.app.validators.validation import valid_cve_sequence
41from lp.services.fields import PersonChoice
4239
4340
44class CveStatus(DBEnumeratedType):41class CveStatus(DBEnumeratedType):
@@ -124,45 +121,12 @@ class ICve(Interface):
124 description=_("A title for the CVE")))121 description=_("A title for the CVE")))
125 references = Attribute("The set of CVE References for this CVE.")122 references = Attribute("The set of CVE References for this CVE.")
126123
127 date_made_public = exported(
128 Datetime(title=_('Date Made Public'), required=False, readonly=True),
129 as_of='devel'
130 )
131
132 discoverer = exported(
133 PersonChoice(
134 title=_('Discoverer'),
135 required=False,
136 readonly=True,
137 vocabulary='ValidPerson'
138 ),
139 as_of='devel'
140 )
141
142 cvss = exported(
143 Dict(
144 title=_('CVSS'),
145 description=_(
146 'The CVSS vector strings from various authorities '
147 'that publish it.'
148 ),
149 key_type=Text(title=_('The authority that published the score.')),
150 value_type=Text(title=_('The CVSS vector string.')),
151 required=False,
152 readonly=True,
153 ),
154 as_of='devel'
155 )
156
157 def createReference(source, content, url=None):124 def createReference(source, content, url=None):
158 """Create a new CveReference for this CVE."""125 """Create a new CveReference for this CVE."""
159126
160 def removeReference(ref):127 def removeReference(ref):
161 """Remove a CveReference."""128 """Remove a CveReference."""
162129
163 def setCVSSVectorForAuthority(authority, vector_string):
164 """Set the CVSS vector string from an authority."""
165
166130
167@exported_as_webservice_collection(ICve)131@exported_as_webservice_collection(ICve)
168class ICveSet(Interface):132class ICveSet(Interface):
@@ -176,8 +140,7 @@ class ICveSet(Interface):
176 def __iter__():140 def __iter__():
177 """Iterate through all the Cve records."""141 """Iterate through all the Cve records."""
178142
179 def new(sequence, description, cvestate=CveStatus.CANDIDATE,143 def new(sequence, description, cvestate=CveStatus.CANDIDATE):
180 date_made_public=None, discoverer=None, cvss=None):
181 """Create a new ICve."""144 """Create a new ICve."""
182145
183 @collection_default_content()146 @collection_default_content()
diff --git a/lib/lp/bugs/model/cve.py b/lib/lp/bugs/model/cve.py
index f49ce00..27a40b5 100644
--- a/lib/lp/bugs/model/cve.py
+++ b/lib/lp/bugs/model/cve.py
@@ -9,12 +9,10 @@ __all__ = [
9import operator9import operator
1010
11import pytz11import pytz
12from storm.databases.postgres import JSON
13from storm.locals import (12from storm.locals import (
14 DateTime,13 DateTime,
15 Desc,14 Desc,
16 Int,15 Int,
17 Reference,
18 ReferenceSet,16 ReferenceSet,
19 Store,17 Store,
20 Unicode,18 Unicode,
@@ -62,29 +60,11 @@ class Cve(StormBase, BugLinkTargetMixin):
62 references = ReferenceSet(60 references = ReferenceSet(
63 id, 'CveReference.cve_id', order_by='CveReference.id')61 id, 'CveReference.cve_id', order_by='CveReference.id')
6462
65 date_made_public = DateTime(tzinfo=pytz.UTC, allow_none=True)63 def __init__(self, sequence, status, description):
66 discoverer_id = Int(name='discoverer', allow_none=True)
67 discoverer = Reference(discoverer_id, 'Person.id')
68 _cvss = JSON(name='cvss', allow_none=True)
69
70 @property
71 def cvss(self):
72 return self._cvss or {}
73
74 @cvss.setter
75 def cvss(self, value):
76 assert value is None or isinstance(value, dict)
77 self._cvss = value
78
79 def __init__(self, sequence, status, description,
80 date_made_public=None, discoverer=None, cvss=None):
81 super().__init__()64 super().__init__()
82 self.sequence = sequence65 self.sequence = sequence
83 self.status = status66 self.status = status
84 self.description = description67 self.description = description
85 self.date_made_public = date_made_public
86 self.discoverer = discoverer
87 self._cvss = cvss
8868
89 @property69 @property
90 def url(self):70 def url(self):
@@ -131,12 +111,6 @@ class Cve(StormBase, BugLinkTargetMixin):
131 getUtility(IXRefSet).delete(111 getUtility(IXRefSet).delete(
132 {('cve', self.sequence): [('bug', str(bug.id))]})112 {('cve', self.sequence): [('bug', str(bug.id))]})
133113
134 def setCVSSVectorForAuthority(self, authority, vector_string):
135 """See ICveReference."""
136 if self._cvss is None:
137 self._cvss = {}
138 self._cvss[authority] = vector_string
139
140114
141@implementer(ICveSet)115@implementer(ICveSet)
142class CveSet:116class CveSet:
@@ -162,18 +136,10 @@ class CveSet:
162 """See ICveSet."""136 """See ICveSet."""
163 return iter(IStore(Cve).find(Cve))137 return iter(IStore(Cve).find(Cve))
164138
165 def new(self, sequence, description, status=CveStatus.CANDIDATE,139 def new(self, sequence, description, status=CveStatus.CANDIDATE):
166 date_made_public=None, discoverer=None, cvss=None):
167 """See ICveSet."""140 """See ICveSet."""
168 cve = Cve(141 cve = Cve(sequence=sequence, status=status,
169 sequence=sequence,142 description=description)
170 status=status,
171 description=description,
172 date_made_public=date_made_public,
173 discoverer=discoverer,
174 cvss=cvss
175 )
176
177 IStore(Cve).add(cve)143 IStore(Cve).add(cve)
178 return cve144 return cve
179145
diff --git a/lib/lp/bugs/tests/test_cve.py b/lib/lp/bugs/tests/test_cve.py
index 6882b34..90bffc7 100644
--- a/lib/lp/bugs/tests/test_cve.py
+++ b/lib/lp/bugs/tests/test_cve.py
@@ -3,19 +3,10 @@
33
4"""CVE related tests."""4"""CVE related tests."""
55
6from datetime import datetime
7
8import pytz
9from testtools.matchers import MatchesStructure
10from testtools.testcase import ExpectedException
11from zope.component import getUtility6from zope.component import getUtility
12from zope.security.proxy import removeSecurityProxy
137
14from lp.bugs.interfaces.bugtasksearch import BugTaskSearchParams8from lp.bugs.interfaces.bugtasksearch import BugTaskSearchParams
15from lp.bugs.interfaces.cve import (9from lp.bugs.interfaces.cve import ICveSet
16 CveStatus,
17 ICveSet,
18 )
19from lp.testing import (10from lp.testing import (
20 login_person,11 login_person,
21 person_logged_in,12 person_logged_in,
@@ -142,161 +133,3 @@ class TestBugLinks(TestCaseWithFactory):
142 self.assertContentEqual([bug1], cve2.bugs)133 self.assertContentEqual([bug1], cve2.bugs)
143 self.assertContentEqual([cve2], bug1.cves)134 self.assertContentEqual([cve2], bug1.cves)
144 self.assertContentEqual([], bug2.cves)135 self.assertContentEqual([], bug2.cves)
145
146
147class TestCve(TestCaseWithFactory):
148 """Tests for Cve fields and methods."""
149
150 layer = DatabaseFunctionalLayer
151
152 def test_cveset_new_method_optional_parameters(self):
153 cve = getUtility(ICveSet).new(
154 sequence='2099-1234',
155 description='A critical vulnerability',
156 status=CveStatus.CANDIDATE
157 )
158 self.assertThat(cve, MatchesStructure.byEquality(
159 sequence='2099-1234',
160 status=CveStatus.CANDIDATE,
161 description='A critical vulnerability',
162 date_made_public=None,
163 discoverer=None,
164 cvss={}
165 ))
166
167 def test_cveset_new_method_parameters(self):
168 person = self.factory.makePerson()
169 today = datetime.now(tz=pytz.UTC)
170 cvss = {
171 'nvd': 'CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H'
172 }
173 cve = getUtility(ICveSet).new(
174 sequence='2099-1234',
175 description='A critical vulnerability',
176 status=CveStatus.CANDIDATE,
177 date_made_public=today,
178 discoverer=person,
179 cvss=cvss
180 )
181 self.assertThat(cve, MatchesStructure.byEquality(
182 sequence='2099-1234',
183 status=CveStatus.CANDIDATE,
184 description='A critical vulnerability',
185 date_made_public=today,
186 discoverer=person,
187 cvss=cvss
188 ))
189
190 def test_cve_date_made_public_invalid_values(self):
191 invalid_values = ['', 'abcd', {'a': 1},
192 [1, 'a', '2', 'b'], '2022-01-01']
193 cve = self.factory.makeCVE(
194 sequence='2099-1234',
195 description='A critical vulnerability',
196 cvestate=CveStatus.CANDIDATE,
197 )
198 for invalid_value in invalid_values:
199 with ExpectedException(TypeError, 'Expected datetime,.*'):
200 removeSecurityProxy(cve).date_made_public = invalid_value
201
202 def test_cve_discoverer_id_invalid_values(self):
203 invalid_values = ['', 'abcd', '2022-01-01', datetime.now()]
204
205 cve = self.factory.makeCVE(
206 sequence='2099-1234',
207 description='A critical vulnerability',
208 cvestate=CveStatus.CANDIDATE,
209 )
210 for invalid_value in invalid_values:
211 with ExpectedException(TypeError, 'Expected int,.*'):
212 removeSecurityProxy(cve).discoverer_id = invalid_value
213
214 def test_cve_cvss_invalid_values(self):
215 invalid_values = ['', 'abcd', '2022-01-01', datetime.now()]
216 cve = self.factory.makeCVE(
217 sequence='2099-1234',
218 description='A critical vulnerability',
219 cvestate=CveStatus.CANDIDATE,
220 )
221 for invalid_value in invalid_values:
222 with ExpectedException(AssertionError):
223 removeSecurityProxy(cve).cvss = invalid_value
224
225 def test_cvss_value_returned_when_null(self):
226 cve = self.factory.makeCVE(
227 sequence='2099-1234',
228 description='A critical vulnerability',
229 cvestate=CveStatus.CANDIDATE,
230 )
231 cve = removeSecurityProxy(cve)
232 self.assertIsNone(cve._cvss)
233 self.assertEqual({}, cve.cvss)
234
235 def test_setCVSSVectorForAuthority_initially_unset(self):
236 cve = self.factory.makeCVE(
237 sequence='2099-1234',
238 description='A critical vulnerability',
239 cvestate=CveStatus.CANDIDATE,
240 )
241 unproxied_cve = removeSecurityProxy(cve)
242 self.assertIsNone(unproxied_cve._cvss)
243 self.assertEqual({}, unproxied_cve.cvss)
244
245 cve.setCVSSVectorForAuthority(
246 authority="nvd",
247 vector_string="CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H"
248 )
249
250 self.assertEqual(
251 {"nvd": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H"},
252 unproxied_cve.cvss
253 )
254
255 def test_setCVSSVectorForAuthority_overwrite_existing_key_value(self):
256 cve = self.factory.makeCVE(
257 sequence='2099-1234',
258 description='A critical vulnerability',
259 cvestate=CveStatus.CANDIDATE,
260 cvss={"nvd": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H"}
261 )
262 unproxied_cve = removeSecurityProxy(cve)
263 self.assertEqual(
264 {"nvd": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H"},
265 unproxied_cve.cvss
266 )
267
268 cve.setCVSSVectorForAuthority(
269 authority="nvd",
270 vector_string="CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N"
271 )
272
273 self.assertEqual(
274 {"nvd": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N"},
275 unproxied_cve.cvss
276 )
277
278 def test_setCVSSVectorForAuthority_add_new_when_initial_value_set(self):
279 cve = self.factory.makeCVE(
280 sequence='2099-1234',
281 description='A critical vulnerability',
282 cvestate=CveStatus.CANDIDATE,
283 cvss={"nvd": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H"}
284 )
285 unproxied_cve = removeSecurityProxy(cve)
286 self.assertEqual(
287 {"nvd": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H"},
288 unproxied_cve.cvss
289 )
290
291 cve.setCVSSVectorForAuthority(
292 authority="nist",
293 vector_string="CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N"
294 )
295
296 self.assertEqual(
297 {
298 "nvd": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H",
299 "nist": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N"
300 },
301 unproxied_cve.cvss
302 )
diff --git a/lib/lp/testing/factory.py b/lib/lp/testing/factory.py
index 9e37780..041cb89 100644
--- a/lib/lp/testing/factory.py
+++ b/lib/lp/testing/factory.py
@@ -4582,21 +4582,11 @@ class BareLaunchpadObjectFactory(ObjectFactory):
4582 return secret, token4582 return secret, token
45834583
4584 def makeCVE(self, sequence, description=None,4584 def makeCVE(self, sequence, description=None,
4585 cvestate=CveStatus.CANDIDATE,4585 cvestate=CveStatus.CANDIDATE):
4586 date_made_public=None, discoverer=None,
4587 cvss=None):
4588 """Create a new CVE record."""4586 """Create a new CVE record."""
4589 if description is None:4587 if description is None:
4590 description = self.getUniqueUnicode()4588 description = self.getUniqueUnicode()
45914589 return getUtility(ICveSet).new(sequence, description, cvestate)
4592 return getUtility(ICveSet).new(
4593 sequence,
4594 description,
4595 cvestate,
4596 date_made_public,
4597 discoverer,
4598 cvss
4599 )
46004590
4601 def makePublisherConfig(self, distribution=None, root_dir=None,4591 def makePublisherConfig(self, distribution=None, root_dir=None,
4602 base_url=None, copy_base_url=None):4592 base_url=None, copy_base_url=None):

Subscribers

People subscribed via source and target branches

to status/vote changes: