631 lines
31 KiB
Plaintext
631 lines
31 KiB
Plaintext
|
|
# 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"
|
|
|