Add feature to check if a CVE has an open launchpad

This change enables the capability to track if a CVE to be fixed already
has an open launchpad in starlingx: https://bugs.launchpad.net/starlingx/

This will help the security team to focus on the CVEs that do not
have a launchpad already open, reducing the overhead of analysis of CVEs
already presented to the development team.

Story:2006971

Change-Id: I494f0221cb52a4bf7ace20d75e067b17c719d749
Signed-off-by: VictorRodriguez <vm.rod25@gmail.com>
This commit is contained in:
VictorRodriguez 2019-11-27 17:39:51 -06:00
parent 2722d6ffbe
commit 063e29fe2e
3 changed files with 137 additions and 7 deletions

View File

@ -12,6 +12,7 @@ Create documentation as pydoc -w cve_policy_filter
import json
import sys
import os
from lp import find_lp_assigned
def print_html_report(cves_report, title):
"""
@ -25,6 +26,7 @@ def print_html_report(cves_report, title):
template = template_env.get_template(template_file)
heads = ["cve_id", "status", "cvss2Score", "av", "ac", "au", "ai"]
output_text = template.render(cves_to_fix=cves_report["cves_to_fix"],\
cves_to_fix_lp=cves_report["cves_to_fix_lp"],\
cves_to_track=cves_report["cves_to_track"],\
cves_w_errors=cves_report["cves_w_errors"],\
cves_to_omit=cves_report["cves_to_omit"],\
@ -40,7 +42,7 @@ def print_report(cves_report, title):
Print the txt STDOUT report
"""
print("\n%s report:" % (title))
print("\nValid CVEs to take action immediately: %d\n" \
print("\nCVEs to fix w/o a launchpad assigned: %d\n" \
% (len(cves_report["cves_to_fix"])))
for cve in cves_report["cves_to_fix"]:
print("\n")
@ -57,6 +59,15 @@ def print_report(cves_report, title):
if cve["sourcelink"]:
print(cve["sourcelink"])
print("\nCVEs to fix w/ a launchpad assigned: %d \n" \
% (len(cves_report["cves_to_fix_lp"])))
for cve in cves_report["cves_to_fix_lp"]:
cve_line = []
for key, value in cve.items():
if key != "summary":
cve_line.append(key + ":" + str(value))
print(cve_line)
print("\nCVEs to track for incoming fix: %d \n" \
% (len(cves_report["cves_to_track"])))
for cve in cves_report["cves_to_track"]:
@ -128,6 +139,7 @@ def main():
cves = []
cves_valid = []
cves_to_fix = []
cves_to_fix_lp = []
cves_to_track = []
cves_w_errors = []
cves_to_omit = []
@ -197,13 +209,17 @@ def main():
and ("N" in cve["au"] or "S" in cve["au"])
and ("P" in cve["ai"] or "C" in cve["ai"])):
if cve["status"] == "fixed":
cves_to_fix.append(cve)
if find_lp_assigned(cve["id"]):
cves_to_fix_lp.append(cve)
else:
cves_to_fix.append(cve)
else:
cves_to_track.append(cve)
else:
cves_to_omit.append(cve)
cves_report["cves_to_fix"] = cves_to_fix
cves_report["cves_to_fix_lp"] = cves_to_fix_lp
cves_report["cves_to_track"] = cves_to_track
cves_report["cves_w_errors"] = cves_w_errors
cves_report["cves_to_omit"] = cves_to_omit

92
cve_support/lp.py Normal file
View File

@ -0,0 +1,92 @@
#
# SPDX-License-Identifier: Apache-2.0
#
# Copyright (C) 2019 Intel Corporation
#
"""
Implement system to detect if CVEs has launchpad assigned
"""
import json
import os
from os import path
from launchpadlib.launchpad import Launchpad
# Filter the open bugs
STATUSES = [
'New',
'Incomplete',
'Confirmed',
'Triaged',
'In Progress',
'Fix Committed',
'Fix Released',
]
CACHEDIR = path.join('/tmp', os.environ['USER'], '.launchpadlib/cache')
CVES_FILE = path.join(CACHEDIR, 'cves_open.json')
DATA = []
def search_upstrem_lps():
"""
Search for launchpads open with CVE or cve in title
"""
launchpad = Launchpad.login_anonymously\
('lplib.cookbook.json_fetcher', 'production',
CACHEDIR, version='devel')
project = launchpad.projects['starlingx']
tasks = project.searchTasks(status=STATUSES)
for task in tasks:
bug = task.bug
if ("cve" in bug.title.lower()):
bug_dic = {}
bug_dic['id'] = bug.id
bug_dic['title'] = bug.title
bug_dic['link'] = bug.self_link
DATA.append(bug_dic)
with open(CVES_FILE, 'w') as outfile:
json.dump(DATA, outfile)
def find_lp_assigned(cve_id):
"""
Check if a launchpad for CVE exist in DATA
DATA must came from file or from upstream launchpad DB
"""
global DATA
if not DATA:
if path.isfile(CVES_FILE):
DATA = json.load(open(CVES_FILE, "r"))
else:
search_upstrem_lps()
for bug in DATA:
if cve_id in bug["title"]:
return bug
return None
def main():
"""
Sanity test
"""
cve_ids = ["CVE-2019-0160",\
"CVE-2019-11810",\
"CVE-2019-11811",\
"CVE-2018-15686",\
"CVE-2019-10126"]
for cve_id in cve_ids:
bug = find_lp_assigned(cve_id)
if bug:
print("\n")
print(bug)
else:
print("\n%s has no LP assigned\n" % (cve_id))
if __name__ == "__main__":
main()

View File

@ -1,9 +1,9 @@
<head></head>
<body>
<h1>Security report from vuls scan from {{title}}</h1>
<h2>Valid CVEs to take action immediately: {{cves_to_fix | length}}</h2>
<h2>CVEs to fix w/o a launchpad assigned: {{cves_to_fix | length}}</h2>
<table>
{% if cves_to_fix|length > 1 %}
{% if cves_to_fix|length >= 1 %}
<tr>
{% for head in heads %}
<th>{{head}}</th>
@ -23,9 +23,31 @@
{% endfor %}
{% endif %}
</table>
<h2>CVEs to fix w/ a launchpad assigend: {{cves_to_fix_lp | length}}</h2>
<table>
{% if cves_to_fix_lp|length >= 1 %}
<tr>
{% for head in heads %}
<th>{{head}}</th>
{% endfor %}
</tr>
{% for cve in cves_to_fix_lp %}
<tr>
<td>{{cve["id"]}}</td>
<td>{{cve["status"]}}</td>
<td>{{cve["cvss2Score"]}}</td>
<td>{{cve["av"]}}</td>
<td>{{cve["ac"]}}</td>
<td>{{cve["au"]}}</td>
<td>{{cve["ai"]}}</td>
</tr>
{% endfor %}
{% endif %}
</table>
<h2> CVEs to track for incoming fix: {{cves_to_track | length}}</h2>
<table>
{% if cves_to_track|length > 1 %}
{% if cves_to_track|length >= 1 %}
<tr>
{% for head in heads %}
<th>{{head}}</th>
@ -47,7 +69,7 @@
</table>
<h2> CVEs to omit: {{cves_to_omit | length}}</h2>
<table>
{% if cves_to_omit|length > 1 %}
{% if cves_to_omit|length >= 1 %}
<tr>
{% for head in heads %}
<th>{{head}}</th>
@ -70,7 +92,7 @@
<h2>ERROR: CVEs that have no cvss2Score or cvss2Vector:{{cves_w_errors | length}}</h2>
<table>
{% if cves_w_errors|length > 1 %}
{% if cves_w_errors|length >= 1 %}
{% for cve in cves_to_track %}
<tr>
<td>{{cve["id"]}}</td>