|
16 | 16 | from vulnerabilities.utils import get_advisory_url |
17 | 17 | from vulnerabilities.utils import get_cwe_id |
18 | 18 | from vulnerabilities.utils import get_reference_id |
| 19 | +from vulnerabilities.utils import ssvc_calculator |
19 | 20 |
|
20 | 21 | logger = logging.getLogger(__name__) |
21 | 22 |
|
@@ -210,117 +211,3 @@ def clean_downloads(self): |
210 | 211 |
|
211 | 212 | def on_failure(self): |
212 | 213 | self.clean_downloads() |
213 | | - |
214 | | - |
215 | | -def ssvc_calculator(ssvc_data): |
216 | | - """ |
217 | | - Return the ssvc vector and the decision value |
218 | | - """ |
219 | | - options = ssvc_data.get("options", []) |
220 | | - timestamp = ssvc_data.get("timestamp") |
221 | | - |
222 | | - # Extract the options into a dictionary |
223 | | - options_dict = {k: v.lower() for option in options for k, v in option.items()} |
224 | | - |
225 | | - # We copied the table value from this link. |
226 | | - # https://www.cisa.gov/sites/default/files/publications/cisa-ssvc-guide%20508c.pdf |
227 | | - |
228 | | - # Determining Mission and Well-Being Impact Value |
229 | | - mission_well_being_table = { |
230 | | - # (Mission Prevalence, Public Well-being Impact) : "Mission & Well-being" |
231 | | - ("minimal", "minimal"): "low", |
232 | | - ("minimal", "material"): "medium", |
233 | | - ("minimal", "irreversible"): "high", |
234 | | - ("support", "minimal"): "medium", |
235 | | - ("support", "material"): "medium", |
236 | | - ("support", "irreversible"): "high", |
237 | | - ("essential", "minimal"): "high", |
238 | | - ("essential", "material"): "high", |
239 | | - ("essential", "irreversible"): "high", |
240 | | - } |
241 | | - |
242 | | - if "Mission Prevalence" not in options_dict: |
243 | | - options_dict["Mission Prevalence"] = "minimal" |
244 | | - |
245 | | - if "Public Well-being Impact" not in options_dict: |
246 | | - options_dict["Public Well-being Impact"] = "material" |
247 | | - |
248 | | - options_dict["Mission & Well-being"] = mission_well_being_table[ |
249 | | - (options_dict["Mission Prevalence"], options_dict["Public Well-being Impact"]) |
250 | | - ] |
251 | | - |
252 | | - decision_key = ( |
253 | | - options_dict.get("Exploitation"), |
254 | | - options_dict.get("Automatable"), |
255 | | - options_dict.get("Technical Impact"), |
256 | | - options_dict.get("Mission & Well-being"), |
257 | | - ) |
258 | | - |
259 | | - decision_points = { |
260 | | - "Exploitation": {"E": {"none": "N", "poc": "P", "active": "A"}}, |
261 | | - "Automatable": {"A": {"no": "N", "yes": "Y"}}, |
262 | | - "Technical Impact": {"T": {"partial": "P", "total": "T"}}, |
263 | | - "Public Well-being Impact": {"B": {"minimal": "M", "material": "A", "irreversible": "I"}}, |
264 | | - "Mission Prevalence": {"P": {"minimal": "M", "support": "S", "essential": "E"}}, |
265 | | - "Mission & Well-being": {"M": {"low": "L", "medium": "M", "high": "H"}}, |
266 | | - } |
267 | | - |
268 | | - # Create the SSVC vector |
269 | | - ssvc_vector = "SSVCv2/" |
270 | | - for key, value_map in options_dict.items(): |
271 | | - options_key = decision_points.get(key) |
272 | | - for lhs, rhs_map in options_key.items(): |
273 | | - ssvc_vector += f"{lhs}:{rhs_map.get(value_map)}/" |
274 | | - |
275 | | - # "Decision": {"D": {"Track": "T", "Track*": "R", "Attend": "A", "Act": "C"}}, |
276 | | - decision_values = {"Track": "T", "Track*": "R", "Attend": "A", "Act": "C"} |
277 | | - |
278 | | - decision_lookup = { |
279 | | - ("none", "no", "partial", "low"): "Track", |
280 | | - ("none", "no", "partial", "medium"): "Track", |
281 | | - ("none", "no", "partial", "high"): "Track", |
282 | | - ("none", "no", "total", "low"): "Track", |
283 | | - ("none", "no", "total", "medium"): "Track", |
284 | | - ("none", "no", "total", "high"): "Track*", |
285 | | - ("none", "yes", "partial", "low"): "Track", |
286 | | - ("none", "yes", "partial", "medium"): "Track", |
287 | | - ("none", "yes", "partial", "high"): "Attend", |
288 | | - ("none", "yes", "total", "low"): "Track", |
289 | | - ("none", "yes", "total", "medium"): "Track", |
290 | | - ("none", "yes", "total", "high"): "Attend", |
291 | | - ("poc", "no", "partial", "low"): "Track", |
292 | | - ("poc", "no", "partial", "medium"): "Track", |
293 | | - ("poc", "no", "partial", "high"): "Track*", |
294 | | - ("poc", "no", "total", "low"): "Track", |
295 | | - ("poc", "no", "total", "medium"): "Track*", |
296 | | - ("poc", "no", "total", "high"): "Attend", |
297 | | - ("poc", "yes", "partial", "low"): "Track", |
298 | | - ("poc", "yes", "partial", "medium"): "Track", |
299 | | - ("poc", "yes", "partial", "high"): "Attend", |
300 | | - ("poc", "yes", "total", "low"): "Track", |
301 | | - ("poc", "yes", "total", "medium"): "Track*", |
302 | | - ("poc", "yes", "total", "high"): "Attend", |
303 | | - ("active", "no", "partial", "low"): "Track", |
304 | | - ("active", "no", "partial", "medium"): "Track", |
305 | | - ("active", "no", "partial", "high"): "Attend", |
306 | | - ("active", "no", "total", "low"): "Track", |
307 | | - ("active", "no", "total", "medium"): "Attend", |
308 | | - ("active", "no", "total", "high"): "Act", |
309 | | - ("active", "yes", "partial", "low"): "Attend", |
310 | | - ("active", "yes", "partial", "medium"): "Attend", |
311 | | - ("active", "yes", "partial", "high"): "Act", |
312 | | - ("active", "yes", "total", "low"): "Attend", |
313 | | - ("active", "yes", "total", "medium"): "Act", |
314 | | - ("active", "yes", "total", "high"): "Act", |
315 | | - } |
316 | | - |
317 | | - decision = decision_lookup.get(decision_key, "") |
318 | | - |
319 | | - if decision: |
320 | | - ssvc_vector += f"D:{decision_values.get(decision)}/" |
321 | | - |
322 | | - if timestamp: |
323 | | - timestamp_formatted = dateparser.parse(timestamp).strftime("%Y-%m-%dT%H:%M:%SZ") |
324 | | - |
325 | | - ssvc_vector += f"{timestamp_formatted}/" |
326 | | - return ssvc_vector, decision |
0 commit comments