added my Recipes
This commit is contained in:
630
meta-st/meta-st-openstlinux/classes/st-image-cve-summary.bbclass
Normal file
630
meta-st/meta-st-openstlinux/classes/st-image-cve-summary.bbclass
Normal file
@@ -0,0 +1,630 @@
|
||||
|
||||
# To have tab on html file generated
|
||||
CVE_IMAGE_CONTENT_WITH_TAB ?= "1"
|
||||
|
||||
# Configure on BSP side this var if you expect the summary to be generated
|
||||
ENABLE_IMAGE_CVE_SUMMARY ??= "0"
|
||||
|
||||
ST_CVE_SUMMARY_DIR ?= "${WORKDIR}/cve-summary/"
|
||||
ST_CVE_SUMMARY_DEPLOYDIR ?= "${DEPLOY_DIR}/images/${MACHINE}"
|
||||
ST_CVE_SUMMARY_NAME ?= "${IMAGE_NAME}-cve_content.html"
|
||||
ST_CVE_SUMMARY_LINK_NAME ?= "${IMAGE_LINK_NAME}-cve_content.html"
|
||||
|
||||
ST_MAIN_COMPONENTS ?= ""
|
||||
|
||||
def cve_create_summary(d):
|
||||
import re
|
||||
import json
|
||||
tab = d.expand("${CVE_IMAGE_CONTENT_WITH_TAB}")
|
||||
|
||||
ref_image_name = d.expand("${IMAGE_LINK_NAME}")
|
||||
deploy_image_dir = d.expand("${DEPLOY_DIR_IMAGE}")
|
||||
temp_deploy_image_dir = d.expand("${IMGDEPLOYDIR}")
|
||||
|
||||
cve_deploy_dir = d.expand("${DEPLOY_DIR}/cve")
|
||||
|
||||
cve_summary_deploydir = d.getVar('ST_CVE_SUMMARY_DIR')
|
||||
cve_summary_name = d.getVar('ST_CVE_SUMMARY_NAME')
|
||||
cve_summary_link = d.getVar('ST_CVE_SUMMARY_LINK_NAME')
|
||||
|
||||
components_list = d.getVar('ST_MAIN_COMPONENTS')
|
||||
|
||||
datetime = d.getVar('DATETIME')
|
||||
|
||||
if tab.startswith("1"):
|
||||
with_tab = 1
|
||||
else:
|
||||
with_tab = None
|
||||
|
||||
def private_open(filename):
|
||||
result = None
|
||||
if os.path.exists(filename):
|
||||
try:
|
||||
with open(filename, "r") as lic:
|
||||
result = lic.readlines()
|
||||
except IOError:
|
||||
bb.warn("IMG LIC SUM: Cannot open file %s" % (filename))
|
||||
result = ""
|
||||
except:
|
||||
bb.warn("IMG LIC SUM: Error with file %s" % (filename))
|
||||
result = ""
|
||||
else:
|
||||
bb.warn("IMG LIC SUM: File does not exist with open file %s" % (filename))
|
||||
|
||||
result = ""
|
||||
return result
|
||||
|
||||
class HTMLSummaryfile():
|
||||
''' format definition '''
|
||||
bold = "font-weight: bold; background-color: #cccccc;"
|
||||
red = "background-color: #ff0000;"
|
||||
center_format = "align: center;"
|
||||
border_format = "border: 1;"
|
||||
wrap_format = ""
|
||||
wrap_red_format = "background-color: #ff0000;"
|
||||
|
||||
blue = "background-color: #0000ff;"
|
||||
green = "background-color: #00ff00;"
|
||||
|
||||
opened_file = None
|
||||
|
||||
def openfile(self, file_name):
|
||||
self.opened_file = open(file_name, 'w')
|
||||
def closefile(self):
|
||||
self.opened_file.close()
|
||||
def startTable(self, style=None, classes=None):
|
||||
if style:
|
||||
if classes:
|
||||
self.opened_file.write("<TABLE STYLE='%s' class='%s'>\n" % (style, classes))
|
||||
else:
|
||||
self.opened_file.write("<TABLE STYLE='%s'>\n" % style)
|
||||
else:
|
||||
if classes:
|
||||
self.opened_file.write("<TABLE BORDER=1 class='%s'>\n" % classes)
|
||||
else:
|
||||
self.opened_file.write("<TABLE border=1>\n")
|
||||
|
||||
def stopTable(self):
|
||||
self.opened_file.write("</TABLE>\n")
|
||||
def startRow(self, style=None):
|
||||
self.opened_file.write("<TR>\n")
|
||||
def stopRow(self, style=None):
|
||||
self.opened_file.write("</TR>\n")
|
||||
def startColumn(self, style=None):
|
||||
if style:
|
||||
self.opened_file.write("<TD STYLE='%s'>\n")
|
||||
else:
|
||||
self.opened_file.write("<TD>\n")
|
||||
def stopColumn(self, style=None):
|
||||
self.opened_file.write("</TD>\n")
|
||||
def addColumnHeaderContent(self, content, style=None):
|
||||
if style:
|
||||
self.opened_file.write("<TH STYLE='%s'>%s</TH>\n" % (style, content))
|
||||
else:
|
||||
self.opened_file.write("<TH><B>%s</B></TH>\n" % content)
|
||||
def addColumnContent(self, content, style=None):
|
||||
if style:
|
||||
self.opened_file.write("<TD STYLE='%s'>%s</TD>\n" % (style, content))
|
||||
else:
|
||||
self.opened_file.write("<TD>%s</TD>\n" % content)
|
||||
def addColumnURLOUTContent(self, content, url, style=None):
|
||||
if style:
|
||||
self.opened_file.write("<TD STYLE='%s'><A HREF='%s' TARGET='_blank'>%s</A></TD>\n" % (style, url, content))
|
||||
else:
|
||||
self.opened_file.write("<TD><A HREF='%s' TARGET='_blank'>%s</A></TD>\n" % (url, content))
|
||||
def addColumnEmptyContent(self, style=None):
|
||||
if style:
|
||||
self.opened_file.write("<TD STYLE='%s'><BR/></TD>\n" % style)
|
||||
else:
|
||||
self.opened_file.write("<TD><BR/></TD>\n")
|
||||
def addNewLine(self):
|
||||
self.opened_file.write("<BR/>\n")
|
||||
def addContent(self, content):
|
||||
self.opened_file.write(content)
|
||||
def addURLContent(self, content, url):
|
||||
self.opened_file.write("<A HREF='%s'>%s</A>\n" %(url, content))
|
||||
def startBlock(self):
|
||||
self.opened_file.write("<UL>\n")
|
||||
def stopBlock(self):
|
||||
self.opened_file.write("</UL>\n")
|
||||
def addTitle(self, title):
|
||||
self.opened_file.write("<H1>{}</H1>\n".format(title))
|
||||
|
||||
def addAnchor(self, anchor):
|
||||
self.opened_file.write("<A name='%s'/>\n" % anchor)
|
||||
def startDiv(self, anchor, title, style=None):
|
||||
self.opened_file.write("<div id='%s' class='tabcontent'>\n" % anchor)
|
||||
self.opened_file.write("<H1>%s</H1>\n" % title)
|
||||
|
||||
def stopDiv(self):
|
||||
self.opened_file.write("</div>\n")
|
||||
|
||||
def beginHtml(self):
|
||||
self.opened_file.write("<HTML>\n")
|
||||
self.opened_file.write('<HEAD>\n')
|
||||
self.opened_file.write(" <STYLE TYPE='text/css'>\n")
|
||||
self.opened_file.write("/* Style the tab buttons */\n")
|
||||
self.opened_file.write(".tablink {\n")
|
||||
self.opened_file.write(" background-color: #555;\n")
|
||||
self.opened_file.write(" color: white;\n")
|
||||
self.opened_file.write(" float: left;\n")
|
||||
self.opened_file.write(" border: none;\n")
|
||||
self.opened_file.write(" outline: none;\n")
|
||||
self.opened_file.write(" cursor: pointer;\n")
|
||||
self.opened_file.write(" padding: 14px 16px;\n")
|
||||
self.opened_file.write(" font-size: 17px;\n")
|
||||
self.opened_file.write(" width: 25%;\n")
|
||||
self.opened_file.write("}\n")
|
||||
self.opened_file.write("\n")
|
||||
self.opened_file.write("/* Change background color of buttons on hover */\n")
|
||||
self.opened_file.write(".tablink:hover {\n")
|
||||
self.opened_file.write(" background-color: #777;\n")
|
||||
self.opened_file.write("}\n")
|
||||
self.opened_file.write("\n")
|
||||
self.opened_file.write("/* Set default styles for tab content */\n")
|
||||
self.opened_file.write(".tabcontent {\n")
|
||||
self.opened_file.write(" color: black;\n")
|
||||
self.opened_file.write(" display: none;\n")
|
||||
self.opened_file.write(" padding: 50px;\n")
|
||||
self.opened_file.write(" text-align: left;\n")
|
||||
self.opened_file.write("}\n")
|
||||
self.opened_file.write("\n")
|
||||
self.opened_file.write("/* Style each tab content individually */\n")
|
||||
self.opened_file.write("#statistic {background-color: white;}\n")
|
||||
self.opened_file.write("#component {background-color: white;}\n")
|
||||
self.opened_file.write("#images {background-color: white;}\n")
|
||||
self.opened_file.write(" </STYLE>\n")
|
||||
self.opened_file.write("</HEAD>\n")
|
||||
def endHtml(self):
|
||||
self.opened_file.write("</HTML>\n")
|
||||
def beginBody(self, tab=None):
|
||||
self.opened_file.write("<BODY>\n")
|
||||
self.opened_file.write("<a name='top'/>\n")
|
||||
|
||||
def addApplicationTab(self):
|
||||
if tab:
|
||||
self.opened_file.write(' <button class="tablink" onclick="openTab(\'statistic\', this)" id="defaultOpen">Main Statistics</button>\n')
|
||||
self.opened_file.write(' <button class="tablink" onclick="openTab(\'component\', this)">Main Components CVE / CVS</button>\n')
|
||||
self.opened_file.write(' <button class="tablink" onclick="openTab(\'images\', this)">Image CVE / CVS</button>\n')
|
||||
self.opened_file.write("\n")
|
||||
def endBody(self, tab=None):
|
||||
if tab:
|
||||
self.opened_file.write('<SCRIPT TYPE="text/javascript">\n')
|
||||
self.opened_file.write('function openTab(Name, elmnt) {\n')
|
||||
self.opened_file.write(' // Hide all elements with class="tabcontent" by default */\n')
|
||||
self.opened_file.write(' var i, tabcontent, tablinks;\n')
|
||||
self.opened_file.write(' tabcontent = document.getElementsByClassName("tabcontent");\n')
|
||||
self.opened_file.write(' for (i = 0; i < tabcontent.length; i++) {\n')
|
||||
self.opened_file.write(' tabcontent[i].style.display = "none";\n')
|
||||
self.opened_file.write(' }\n')
|
||||
self.opened_file.write('\n')
|
||||
self.opened_file.write(' // Remove the background color of all tablinks/buttons\n')
|
||||
self.opened_file.write(' tablinks = document.getElementsByClassName("tablink");\n')
|
||||
self.opened_file.write(' for (i = 0; i < tablinks.length; i++) {\n')
|
||||
self.opened_file.write(' tablinks[i].style.backgroundColor = "";\n')
|
||||
self.opened_file.write(' }\n')
|
||||
self.opened_file.write('\n')
|
||||
self.opened_file.write(' // Show the specific tab content\n')
|
||||
self.opened_file.write(' document.getElementById(Name).style.display = "block";\n')
|
||||
self.opened_file.write('\n')
|
||||
self.opened_file.write(' // Add the specific color to the button used to open the tab content\n')
|
||||
self.opened_file.write(' elmnt.style.backgroundColor = \'white\';\n')
|
||||
self.opened_file.write(' elmnt.style.color = "black";\n')
|
||||
self.opened_file.write('}\n')
|
||||
self.opened_file.write('\n')
|
||||
|
||||
self.opened_file.write('function toggleunpatched(element) {\n')
|
||||
self.opened_file.write(' patched = document.getElementsByClassName("patched");\n')
|
||||
self.opened_file.write(' for (i = 0; i < patched.length; i++) {\n')
|
||||
self.opened_file.write(' if (element.checked) {\n')
|
||||
self.opened_file.write(' patched[i].style.display = "none";\n')
|
||||
self.opened_file.write(' } else {\n')
|
||||
self.opened_file.write(' patched[i].style.display = "block";\n')
|
||||
self.opened_file.write(' }\n')
|
||||
self.opened_file.write(' }\n')
|
||||
self.opened_file.write('}\n')
|
||||
|
||||
self.opened_file.write('function toggleunscorev3(element) {\n')
|
||||
self.opened_file.write(' score = document.getElementsByClassName("scorev3");\n')
|
||||
self.opened_file.write(' for (i = 0; i < score.length; i++) {\n')
|
||||
self.opened_file.write(' if (element.checked) {\n')
|
||||
self.opened_file.write(' score[i].style.display = "none";\n')
|
||||
self.opened_file.write(' } else {\n')
|
||||
self.opened_file.write(' score[i].style.display = "block";\n')
|
||||
self.opened_file.write(' }\n')
|
||||
self.opened_file.write(' }\n')
|
||||
self.opened_file.write(' if element.checked == false) {\n')
|
||||
self.opened_file.write(' check = document.getElementsByName("check_unpatched")\n')
|
||||
self.opened_file.write(' toggleunpatched(check[0])\n')
|
||||
self.opened_file.write(' }\n')
|
||||
self.opened_file.write('}\n')
|
||||
|
||||
self.opened_file.write('function toggleunscorev2(element) {\n')
|
||||
self.opened_file.write(' score2 = document.getElementsByClassName("scorev2");\n')
|
||||
self.opened_file.write(' for (i = 0; i < score2.length; i++) {\n')
|
||||
self.opened_file.write(' if (element.checked) {\n')
|
||||
self.opened_file.write(' score2[i].style.display = "none";\n')
|
||||
self.opened_file.write(' } else {\n')
|
||||
self.opened_file.write(' score2[i].style.display = "block";\n')
|
||||
self.opened_file.write(' }\n')
|
||||
self.opened_file.write(' }\n')
|
||||
self.opened_file.write(' if element.checked == false) {\n')
|
||||
self.opened_file.write(' check = document.getElementsByName("check_unpatched")\n')
|
||||
self.opened_file.write(' toggleunpatched(check[0])\n')
|
||||
self.opened_file.write(' }\n')
|
||||
self.opened_file.write('}\n')
|
||||
|
||||
|
||||
self.opened_file.write('// Get the element with id="defaultOpen" and click on it\n')
|
||||
self.opened_file.write('document.getElementById("defaultOpen").click();\n')
|
||||
self.opened_file.write('</SCRIPT>\n')
|
||||
else:
|
||||
self.opened_file.write('<SCRIPT TYPE="text/javascript">\n')
|
||||
self.opened_file.write(' // display all elements with class="tabcontent" by default */\n')
|
||||
self.opened_file.write(' var i, tabcontent, tablinks;\n')
|
||||
self.opened_file.write(' tabcontent = document.getElementsByClassName("tabcontent");\n')
|
||||
self.opened_file.write(' for (i = 0; i < tabcontent.length; i++) {\n')
|
||||
self.opened_file.write(' tabcontent[i].style.display = "block";\n')
|
||||
self.opened_file.write(' }\n')
|
||||
self.opened_file.write('\n')
|
||||
self.opened_file.write('</SCRIPT>\n')
|
||||
|
||||
self.opened_file.write("</BODY>\n")
|
||||
|
||||
def score_v2_table(score):
|
||||
''' source : https://nvd.nist.gov/vuln-metrics/cvss '''
|
||||
if float(score) < 4.0:
|
||||
return "<SPAN STYLE='color: black; background-color: yellow;'> {} Low </SPAN>".format(score)
|
||||
elif float(score) < 7.0:
|
||||
return "<SPAN STYLE='color: black; background-color: #FFBF00;'> {} Medium </SPAN>".format(score)
|
||||
else:
|
||||
return "<SPAN STYLE='color: black; background-color: red;'> {} Hight </SPAN>".format(score)
|
||||
|
||||
def score_v3_table(score):
|
||||
''' source : https://www.cert-ist.com/public/fr/SO_detail?code=cvss%20v3&format=html '''
|
||||
if float(score) == 0.0:
|
||||
return "<SPAN STYLE='color: black; background-color: darkgrey;'> {} None </SPAN>".format(score)
|
||||
elif float(score) < 4.0:
|
||||
return "<SPAN STYLE='color: black; background-color: yellow;'> {} Low </SPAN>".format(score)
|
||||
elif float(score) < 7.0:
|
||||
return "<SPAN STYLE='color: black; background-color: #FFBF00;'> {} Medium </SPAN>".format(score)
|
||||
elif float(score) < 9.0:
|
||||
return "<SPAN STYLE='color: black; background-color: red;'> {} High </SPAN>".format(score)
|
||||
else:
|
||||
return "<SPAN STYLE='color: white; background-color: black;'> {} Critical </SPAN>".format(score)
|
||||
|
||||
def generate_image_cve_sheet(html):
|
||||
html.startDiv("images", "Image CVE / CVS")
|
||||
html.addAnchor("images")
|
||||
|
||||
# link
|
||||
html.addTitle("List of components on image:")
|
||||
html.startTable(style="width: 80%; border: 1px solid black;")
|
||||
html.startRow()
|
||||
html.addContent("<TD width='20%'>")
|
||||
count=0
|
||||
col=0
|
||||
with open(os.path.join(deploy_image_dir, "{}.json".format(ref_image_name))) as image_file:
|
||||
json_component = json.load(image_file)
|
||||
for i in json_component['package']:
|
||||
issue=i['issue']
|
||||
if len(issue) > 0:
|
||||
html.addContent("<LI><a href='#image_{}'>{}</a></LI>\n".format(i['name'], i['name']))
|
||||
count+=1
|
||||
if count > 15:
|
||||
count = 0
|
||||
if col > 5:
|
||||
col = 0
|
||||
html.addContent("</td></tr><tr><td witdh='20%'>")
|
||||
else:
|
||||
html.addContent("</td><td witdh='10%'>")
|
||||
col+=1
|
||||
html.addContent("</TD>")
|
||||
html.stopRow()
|
||||
html.stopTable()
|
||||
|
||||
html.addNewLine()
|
||||
html.addNewLine()
|
||||
|
||||
html.startTable(style="border: 1px solid black;")
|
||||
|
||||
with open(os.path.join(deploy_image_dir, ref_image_name + ".json")) as image_file:
|
||||
json_component = json.load(image_file)
|
||||
for i in json_component['package']:
|
||||
issue=i['issue']
|
||||
if len(issue) > 0:
|
||||
html.startRow()
|
||||
html.addColumnHeaderContent("Component Name <a href='#top'>[top]</a><a name='image_{}'/>".format(i['name']), style="font-weight: bold; background-color: #cccccc;")
|
||||
html.addColumnHeaderContent("Version", style="font-weight: bold; background-color: #cccccc;")
|
||||
html.addColumnHeaderContent("CVE Ref Name", style="font-weight: bold; background-color: #cccccc;")
|
||||
html.stopRow()
|
||||
html.startRow()
|
||||
html.addColumnContent(i['name'])
|
||||
html.addColumnContent(i['version'])
|
||||
html.addColumnContent(i['products'][0]['product'])
|
||||
html.stopRow()
|
||||
|
||||
html.startRow()
|
||||
html.addColumnHeaderContent("Issues", style="font-weight: bold; background-color: #cccccc;")
|
||||
html.addContent("<TD colspan='2'>")
|
||||
for iss in issue:
|
||||
classe = ''
|
||||
if iss['status'].find("Unpatched") < 0:
|
||||
classe += 'patched '
|
||||
if float(iss['scorev3']) < 7.0 :
|
||||
classe += 'scorev3 '
|
||||
if float(iss['scorev2']) < 7.0 :
|
||||
classe += 'scorev2 '
|
||||
if len(classe) > 0:
|
||||
html.startTable(style='border: 1px solid black; width=100%;', classes=classe)
|
||||
else:
|
||||
html.startTable(style='border: 1px solid black; width=100%;')
|
||||
html.startRow()
|
||||
html.addColumnContent(iss['id'], style="width: 10%;")
|
||||
if iss['status'].find("Unpatched") > -1:
|
||||
html.addColumnContent(iss['status'], style="background-color: red;")
|
||||
else:
|
||||
html.addColumnContent(iss['status'])
|
||||
html.stopRow()
|
||||
html.startRow()
|
||||
html.addColumnContent("")
|
||||
html.addColumnContent(iss['summary'])
|
||||
html.stopRow()
|
||||
html.startRow()
|
||||
html.addColumnContent("")
|
||||
html.addColumnContent("ScoreV2 = {} ScoreV3 = {}".format(score_v2_table(iss['scorev2']), score_v3_table(iss['scorev3'])))
|
||||
html.stopRow()
|
||||
html.startRow()
|
||||
html.addColumnContent("")
|
||||
html.addColumnContent("Link: <A HREF='{}'>NVD</A> or <A HREF='https://www.cve.org/CVERecord?id={}'>CVE.org</A>".format(iss['link'], iss['id']))
|
||||
html.stopRow()
|
||||
html.stopTable()
|
||||
html.addContent("</TD>")
|
||||
html.stopRow()
|
||||
|
||||
html.startRow()
|
||||
html.stopRow()
|
||||
html.startRow(style="bgcolor: gray;")
|
||||
html.stopRow()
|
||||
html.startRow()
|
||||
html.stopRow()
|
||||
|
||||
|
||||
html.stopTable()
|
||||
html.stopDiv()
|
||||
|
||||
def generate_statistics_sheet(html, components):
|
||||
general_MACHINE = d.getVar("MACHINE")
|
||||
# Make sure to remove any DISTRO append to IMAGE_BASENAME for short display
|
||||
general_IMAGE = re.sub(r'-%s$' % d.getVar('DISTRO'), '', d.getVar("IMAGE_BASENAME"))
|
||||
general_DISTRO = d.getVar("DISTRO")
|
||||
general_DISTRO_VERSION = d.getVar("DISTRO_VERSION")
|
||||
general_DISTRO_CODENAME = d.getVar("DISTRO_CODENAME")
|
||||
|
||||
html.startDiv("statistic", "Main Statistics")
|
||||
html.addAnchor("statistic")
|
||||
|
||||
html.addTitle("Number of CVE/CVS:")
|
||||
html.startTable()
|
||||
html.startRow()
|
||||
html.addColumnHeaderContent("Component Name", style="font-weight: bold; background-color: #cccccc;")
|
||||
html.addColumnHeaderContent("Issues", style="font-weight: bold; background-color: #cccccc;")
|
||||
html.addColumnHeaderContent("Issues Patched", style="font-weight: bold; background-color: #cccccc;")
|
||||
html.addColumnHeaderContent("Issues Unpatched", style="font-weight: bold; background-color: #cccccc;")
|
||||
html.stopRow()
|
||||
|
||||
data = []
|
||||
for c in components.split(','):
|
||||
cvs = 0
|
||||
patched = 0
|
||||
unpatched = 0
|
||||
file_name = os.path.join(cve_deploy_dir, "%s_cve.json" % c.lstrip().rstrip())
|
||||
try:
|
||||
with open(os.path.join(cve_deploy_dir, file_name)) as component_file:
|
||||
json_component = json.load(component_file)
|
||||
for i in json_component['package']:
|
||||
issue=i['issue']
|
||||
cvs = len(issue)
|
||||
for err in issue:
|
||||
if err['status'].find("Patched") > -1:
|
||||
patched+= 1
|
||||
elif err['status'].find("Unpatched") > -1:
|
||||
unpatched+= 1
|
||||
data.append([i['name'], cvs, patched, unpatched])
|
||||
except FileNotFoundError:
|
||||
bb.note("file (%s) are not present" % os.path.join(cve_deploy_dir, "%s_cve.json" % c.lstrip().rstrip()))
|
||||
|
||||
for i in data:
|
||||
html.startRow()
|
||||
html.addColumnContent(i[0], style="width: 10%;")
|
||||
html.addColumnContent(i[1], style="width: 10%; text-align: center;")
|
||||
html.addColumnContent(i[2], style="text-align: center;")
|
||||
html.addColumnContent(i[3], style="text-align: center;")
|
||||
html.stopRow()
|
||||
html.stopTable()
|
||||
|
||||
html.addNewLine()
|
||||
html.addNewLine()
|
||||
|
||||
# image count
|
||||
with open( os.path.join(deploy_image_dir, "{}.json".format(ref_image_name))) as image_file:
|
||||
json_component = json.load(image_file)
|
||||
cvs = 0
|
||||
package=0
|
||||
patched = 0
|
||||
unpatched = 0
|
||||
|
||||
for i in json_component['package']:
|
||||
package += 1
|
||||
issue=i['issue']
|
||||
cvs += len(issue)
|
||||
for err in issue:
|
||||
if err['status'].find("Patched") > -1:
|
||||
patched += 1
|
||||
elif err['status'].find("Unpatched") > -1:
|
||||
unpatched += 1
|
||||
|
||||
# package, cvs, patched, unpatched
|
||||
html.addTitle("Number of CVE/CVS for image:")
|
||||
html.startTable()
|
||||
html.startRow()
|
||||
html.addColumnHeaderContent("Image Name", style="font-weight: bold; background-color: #cccccc;")
|
||||
html.addColumnHeaderContent("Packages", style="font-weight: bold; background-color: #cccccc;")
|
||||
html.addColumnHeaderContent("Issues", style="font-weight: bold; background-color: #cccccc;")
|
||||
html.addColumnHeaderContent("Issues Patched", style="font-weight: bold; background-color: #cccccc;")
|
||||
html.addColumnHeaderContent("Issues Unpatched", style="font-weight: bold; background-color: #cccccc;")
|
||||
html.stopRow()
|
||||
|
||||
html.startRow()
|
||||
html.addColumnContent(ref_image_name, style="width: 25%; ")
|
||||
html.addColumnContent(package, style="width: 10%; text-align: center;")
|
||||
html.addColumnContent(cvs, style="text-align: center;")
|
||||
html.addColumnContent(patched, style="text-align: center;")
|
||||
html.addColumnContent(unpatched, style="text-align: center;")
|
||||
html.stopRow()
|
||||
html.stopTable()
|
||||
|
||||
html.stopDiv()
|
||||
|
||||
def generate_components_content_sheet(html, components):
|
||||
html.startDiv("component", "Main Components CVE / CVS")
|
||||
html.addAnchor("component")
|
||||
|
||||
html.addTitle("List of components:")
|
||||
|
||||
# link
|
||||
for c in components.split(","):
|
||||
html.addContent("<LI><a href='#component_{}'>{}</a></LI>\n".format(c, c))
|
||||
|
||||
html.addNewLine()
|
||||
html.addNewLine()
|
||||
for name in components.split(","):
|
||||
html.addContent("<H1>Component: {} <a href='#top'>[top]</a></H1>\n".format(name))
|
||||
html.addContent("<a name='component_{}'/>\n".format(name))
|
||||
html.startTable(style="border: 1px solid black;")
|
||||
html.startRow()
|
||||
html.addColumnHeaderContent("Component Name", style="font-weight: bold; background-color: #cccccc;")
|
||||
html.addColumnContent(name)
|
||||
html.stopRow()
|
||||
try:
|
||||
with open(os.path.join(cve_deploy_dir, "%s_cve.json" % name.lstrip().rstrip())) as component_file:
|
||||
json_component = json.load(component_file)
|
||||
for i in json_component['package']:
|
||||
issue=i['issue']
|
||||
html.startRow()
|
||||
html.addColumnHeaderContent("Version", style="font-weight: bold; background-color: #cccccc;")
|
||||
html.addColumnContent(i['version'])
|
||||
html.stopRow()
|
||||
html.startRow()
|
||||
html.addColumnHeaderContent("CVE Ref Name", style="font-weight: bold; background-color: #cccccc;")
|
||||
html.addColumnContent(i['products'][0]['product'])
|
||||
html.stopRow()
|
||||
html.startRow()
|
||||
html.addColumnHeaderContent("Issues", style="font-weight: bold; background-color: #cccccc;")
|
||||
html.startColumn()
|
||||
for iss in issue:
|
||||
classe = ''
|
||||
if iss['status'].find("Unpatched") < 0:
|
||||
classe += 'patched '
|
||||
if float(iss['scorev3']) < 7.0 :
|
||||
classe += 'scorev3 '
|
||||
if float(iss['scorev2']) < 7.0 :
|
||||
classe += 'scorev2 '
|
||||
if len(classe) > 0:
|
||||
html.startTable(style='border: 1px solid black; width=100%;', classes=classe)
|
||||
else:
|
||||
html.startTable(style='border: 1px solid black; width=100%;')
|
||||
html.startRow()
|
||||
html.addColumnContent(iss['id'], style="width: 10%;")
|
||||
if iss['status'].find("Unpatched") > -1:
|
||||
html.addColumnContent(iss['status'], style="background-color: red;")
|
||||
else:
|
||||
html.addColumnContent(iss['status'])
|
||||
html.stopRow()
|
||||
html.startRow()
|
||||
html.addColumnContent("")
|
||||
html.addColumnContent(iss['summary'])
|
||||
html.stopRow()
|
||||
html.startRow()
|
||||
html.addColumnContent("")
|
||||
html.addColumnContent("ScoreV2 = {}; ScoreV3 = {}".format(score_v2_table(iss['scorev2']), score_v3_table(iss['scorev3'])))
|
||||
html.stopRow()
|
||||
html.startRow()
|
||||
html.addColumnContent("")
|
||||
html.addColumnContent("Link: <A HREF='{}'>NVD</A> or <A HREF='https://www.cve.org/CVERecord?id={}'>CVE.org</A>".format(iss['link'], iss['id']))
|
||||
html.stopRow()
|
||||
# empty line for separation
|
||||
html.startRow(style="bgcolor: gray;")
|
||||
html.stopRow()
|
||||
html.stopTable()
|
||||
html.stopColumn()
|
||||
i = None
|
||||
except FileNotFoundError:
|
||||
bb.note("file (%s) are not present" % os.path.join(cve_deploy_dir, "%s_cve.json" % name.lstrip().rstrip()))
|
||||
|
||||
html.stopTable()
|
||||
html.stopDiv()
|
||||
|
||||
# Create license summary file
|
||||
cve_summary_name_path = os.path.join(cve_summary_deploydir, cve_summary_name)
|
||||
print("generate ", cve_summary_name_path)
|
||||
html = HTMLSummaryfile()
|
||||
html.openfile(cve_summary_name_path)
|
||||
html.beginHtml()
|
||||
html.beginBody(with_tab)
|
||||
|
||||
html.addTitle("Image Name: {}<BR/>Generation Date: {}".format(ref_image_name, datetime))
|
||||
|
||||
html.addContent("<div class='one'>See Only 'Unpatched' CVE <input type='checkbox' valud='submit' class='btn' name='unpatched' onclick='toggleunpatched(this)'></div>")
|
||||
html.addNewLine()
|
||||
html.addContent("<div class='one'>See Only 'ScoreV3 > 7' (only)<input type='checkbox' valud='submit' class='btn' onclick='toggleunscorev3(this)'></div>")
|
||||
html.addNewLine()
|
||||
html.addContent("<div class='one'>See Only 'ScoreV2 > 7' (only)<input type='checkbox' valud='submit' class='btn' onclick='toggleunscorev2(this)'></div>")
|
||||
html.addNewLine()
|
||||
html.addApplicationTab()
|
||||
|
||||
''' generate first page: statistics cve / cvs information'''
|
||||
generate_statistics_sheet(html, components_list)
|
||||
''' generate image content '''
|
||||
generate_components_content_sheet(html, components_list)
|
||||
''' generate license spdx reference '''
|
||||
generate_image_cve_sheet(html)
|
||||
html.endBody(with_tab)
|
||||
html.endHtml()
|
||||
html.closefile()
|
||||
|
||||
# Create link
|
||||
cve_summary_link_path = os.path.join(cve_summary_deploydir, cve_summary_link)
|
||||
if os.path.exists(cve_summary_name_path):
|
||||
bb.note("Creating symlink: %s -> %s" % (cve_summary_link_path, cve_summary_name))
|
||||
if os.path.islink(cve_summary_link_path):
|
||||
os.remove(cve_summary_link_path)
|
||||
os.symlink(cve_summary_name, cve_summary_link_path)
|
||||
else:
|
||||
bb.note("Skipping symlink, source does not exist: %s -> %s" % (cve_summary_link_path, cve_summary_name))
|
||||
|
||||
|
||||
python do_st_write_cve_create_summary() {
|
||||
bb.note("---> ENABLE_IMAGE_CVE_SUMMARY %s" % (d.getVar('ENABLE_IMAGE_CVE_SUMMARY')))
|
||||
if d.getVar('ENABLE_IMAGE_CVE_SUMMARY') == "1":
|
||||
if not d.getVar('CVE_CHECK_MANIFEST') is None:
|
||||
cve_create_summary(d)
|
||||
else:
|
||||
return
|
||||
}
|
||||
addtask st_write_cve_create_summary before do_build after do_image_complete
|
||||
do_st_write_cve_create_summary[dirs] = "${ST_CVE_SUMMARY_DIR} ${IMGDEPLOYDIR}"
|
||||
|
||||
SSTATETASKS += "do_st_write_cve_create_summary"
|
||||
do_st_write_cve_create_summary[cleandirs] = "${ST_CVE_SUMMARY_DIR}"
|
||||
do_st_write_cve_create_summary[sstate-inputdirs] = "${ST_CVE_SUMMARY_DIR}"
|
||||
do_st_write_cve_create_summary[sstate-outputdirs] = "${ST_CVE_SUMMARY_DEPLOYDIR}/"
|
||||
|
||||
python do_st_write_cve_create_summary_setscene () {
|
||||
sstate_setscene(d)
|
||||
}
|
||||
addtask do_st_write_cve_create_summary_setscene
|
||||
|
||||
#excluded from basehash signature calculation
|
||||
cve_create_summary[vardepsexclude] += "DATETIME"
|
||||
|
||||
Reference in New Issue
Block a user