\n" % classes)
else:
self.opened_file.write("\n")
def stopTable(self):
self.opened_file.write("
\n")
def startRow(self, style=None):
self.opened_file.write("\n")
def stopRow(self, style=None):
self.opened_file.write(" \n")
def startColumn(self, style=None):
if style:
self.opened_file.write("\n")
else:
self.opened_file.write(" \n")
def stopColumn(self, style=None):
self.opened_file.write(" \n")
def addColumnHeaderContent(self, content, style=None):
if style:
self.opened_file.write("%s \n" % (style, content))
else:
self.opened_file.write("%s \n" % content)
def addColumnContent(self, content, style=None):
if style:
self.opened_file.write("%s \n" % (style, content))
else:
self.opened_file.write("%s \n" % content)
def addColumnURLOUTContent(self, content, url, style=None):
if style:
self.opened_file.write("%s \n" % (style, url, content))
else:
self.opened_file.write("%s \n" % (url, content))
def addColumnEmptyContent(self, style=None):
if style:
self.opened_file.write(" \n" % style)
else:
self.opened_file.write(" \n")
def addNewLine(self):
self.opened_file.write(" \n")
def addContent(self, content):
self.opened_file.write(content)
def addURLContent(self, content, url):
self.opened_file.write("%s \n" %(url, content))
def startBlock(self):
self.opened_file.write("\n")
def stopBlock(self):
self.opened_file.write(" \n")
def addTitle(self, title):
self.opened_file.write("{} \n".format(title))
def addAnchor(self, anchor):
self.opened_file.write(" \n" % anchor)
def startDiv(self, anchor, title, style=None):
self.opened_file.write("\n" % anchor)
self.opened_file.write("
%s \n" % title)
def stopDiv(self):
self.opened_file.write("\n")
def beginHtml(self):
self.opened_file.write("\n")
self.opened_file.write('\n')
self.opened_file.write(" \n")
self.opened_file.write("\n")
def endHtml(self):
self.opened_file.write("\n")
def beginBody(self, tab=None):
self.opened_file.write("\n")
self.opened_file.write(" \n")
def addApplicationTab(self):
if tab:
self.opened_file.write(' Main Statistics \n')
self.opened_file.write(' Main Components CVE / CVS \n')
self.opened_file.write(' Image CVE / CVS \n')
self.opened_file.write("\n")
def endBody(self, tab=None):
if tab:
self.opened_file.write('\n')
else:
self.opened_file.write('\n')
self.opened_file.write("\n")
def score_v2_table(score):
''' source : https://nvd.nist.gov/vuln-metrics/cvss '''
if float(score) < 4.0:
return " {} Low ".format(score)
elif float(score) < 7.0:
return " {} Medium ".format(score)
else:
return " {} Hight ".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 " {} None ".format(score)
elif float(score) < 4.0:
return " {} Low ".format(score)
elif float(score) < 7.0:
return " {} Medium ".format(score)
elif float(score) < 9.0:
return " {} High ".format(score)
else:
return " {} Critical ".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("")
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("{} \n".format(i['name'], i['name']))
count+=1
if count > 15:
count = 0
if col > 5:
col = 0
html.addContent(" ")
else:
html.addContent(" ")
col+=1
html.addContent(" ")
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 [top] ".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("")
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: NVD or CVE.org ".format(iss['link'], iss['id']))
html.stopRow()
html.stopTable()
html.addContent(" ")
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("{} \n".format(c, c))
html.addNewLine()
html.addNewLine()
for name in components.split(","):
html.addContent("Component: {} [top] \n".format(name))
html.addContent(" \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: NVD or CVE.org ".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: {} Generation Date: {}".format(ref_image_name, datetime))
html.addContent("See Only 'Unpatched' CVE
")
html.addNewLine()
html.addContent("See Only 'ScoreV3 > 7' (only)
")
html.addNewLine()
html.addContent("See Only 'ScoreV2 > 7' (only)
")
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"