aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lib/srtgui/reports.py194
-rw-r--r--lib/srtgui/templates/publish.html2
2 files changed, 195 insertions, 1 deletions
diff --git a/lib/srtgui/reports.py b/lib/srtgui/reports.py
index e282a8d0..c207bd84 100644
--- a/lib/srtgui/reports.py
+++ b/lib/srtgui/reports.py
@@ -1919,6 +1919,198 @@ class PackageFiltersReport(Report):
return report_name,os.path.basename(report_name)
+###############################################################################
+#
+# PublishSummaryReport: Publish CVE status summary across products
+#
+
+class PublishSummaryReport(PublishListReport):
+ """Report for the Publish Cve Page"""
+
+ def __init__(self, parent_page, *args, **kwargs):
+ _log_args("REPORT_PUBLISHSUMMARY_INIT(%s)" % parent_page, *args, **kwargs)
+ super(PublishSummaryReport, self).__init__(parent_page, *args, **kwargs)
+
+ def get_context_data(self, *args, **kwargs):
+ _log_args("REPORT_PUBLISHSUMMARY_CONTEXT", *args, **kwargs)
+ context = super(PublishSummaryReport, self).get_context_data(*args, **kwargs)
+
+ # Add a custom extension report type
+ context['report_type_list'] = '\
+ <option value="publish_summary">CVE Summary Report</option> \
+ '
+
+ context['report_custom_list'] = ''
+ # Add scope
+ context['report_custom_list'] += '\
+ <input type="checkbox" id="new" name="new" checked>&nbsp;New CVEs</input> <br>\
+ <input type="checkbox" id="investigate" name="investigate" checked>&nbsp;Investigate CVEs</input> <br>\
+ <input type="checkbox" id="vulnerable" name="vulnerable" checked>&nbsp;Vulnerable CVEs</input> <br>\
+ <input type="checkbox" id="not-vulnerable" name="not-vulnerable" checked>&nbsp;Not Vulnerable CVEs</input> <br>\
+ <input type="checkbox" id="new-reserved" name="new-reserved" >&nbsp;New-Reserved CVEs</input> <br>\
+ <input type="checkbox" id="historical" name="historical" >&nbsp;Historical CVEs</input> <br>\
+ '
+ # Add extra
+ context['report_custom_list'] += '<br>'
+ context['report_custom_list'] += '\
+ <input type="checkbox" id="truncate" name="truncate" checked>&nbsp;Truncate fields (for simple text reports)</input> <BR>\
+ '
+
+ return context
+
+ def get_product_status_matrix(self,product_list,cve):
+ # Preset the default product status labels
+ status_table = {}
+ product_top_order = 99
+ product_top_defect = []
+ # Default all product status to the CVE's status
+ for product in product_list:
+ status_table[product.key] = SRTool.status_text(SRTool.NOT_VULNERABLE)
+ # Set the specific status for the child investigations
+ for cv in cve.cve_to_vulnerability.all():
+ #status_text = cv.vulnerability.get_status_text
+ for investigation in cv.vulnerability.vulnerability_investigation.all():
+# product_key = investigation.product.key
+ release_version_list = []
+ # Gather release versions, find the highest product's respective defect
+ for id in investigation.investigation_to_defect.all():
+ # Find defect(s) for higest ordered product
+ if product_top_order > investigation.product.order:
+ product_top_order = investigation.product.order
+ product_top_defect = []
+ if product_top_order == investigation.product.order:
+ product_top_defect.append(id.defect.name)
+ # Gather the status or release version
+ if id.defect.release_version:
+ release_version_list.append(id.defect.release_version)
+ release_version = '/'.join(release_version_list)
+ # Set investigation status, unless there are release versions
+ status_table[investigation.product.key] = investigation.get_status_text
+ if release_version:
+ status_table[investigation.product.key] = release_version
+ return status_table,product_top_defect
+
+ def exec_report(self, *args, **kwargs):
+ _log_args("REPORT_PUBLISHSUMMARY_EXEC", *args, **kwargs)
+ super(PublishSummaryReport, self).exec_report(*args, **kwargs)
+
+ request_POST = self.request.POST
+ format = request_POST.get('format', '')
+ report_type = request_POST.get('report_type', '')
+ csv_separator = request_POST.get('csv_separator', 'semi')
+ truncate = ('on' == request_POST.get('truncate', 'off'))
+ status_list = []
+ if ('on' == request_POST.get('new', 'off')): status_list.append(Cve.NEW)
+ if ('on' == request_POST.get('investigate', 'off')): status_list.append(Cve.INVESTIGATE)
+ if ('on' == request_POST.get('vulnerable', 'off')): status_list.append(Cve.VULNERABLE)
+ if ('on' == request_POST.get('not-vulnerable', 'off')): status_list.append(Cve.NOT_VULNERABLE)
+ if ('on' == request_POST.get('new-reserved', 'off')): status_list.append(Cve.NEW_RESERVED)
+ if ('on' == request_POST.get('historical', 'off')): status_list.append(Cve.HISTORICAL)
+
+ # Default to the regular report output if not our custom extension
+ if not report_type in ('publish_summary'):
+ return(super(PublishSummaryReport, self).exec_report(*args, **kwargs))
+
+ if 'csv' == format:
+ separator = ';'
+ if csv_separator == 'comma': separator = ','
+ if csv_separator == 'tab': separator = '\t'
+ report_name = '%s/cve-svns-srtool-%s.csv' % (SRT_REPORT_DIR,datetime.today().strftime('%Y_%m_%d'))
+ else:
+ separator = ","
+ report_name = '%s/cve-svns-srtool-%s.txt' % (SRT_REPORT_DIR,datetime.today().strftime('%Y_%m_%d'))
+
+ # Get the desired product list
+ product_list = Product.objects.order_by('-order')
+
+ if 'publish_summary' == report_type:
+ with open(report_name, 'w', newline='') as csvfile:
+ writer = None
+
+ # Assemble the header
+ text_format = '%-18s,%16s,%-8s,%-8s,%-15s,%-15s,%-30s,%-25s,%15s,%15s,%20s,'
+ header = [
+ 'CVE Number',
+ 'Status',
+ 'CVSSv2_Severity',
+ 'CVSSv2_Score',
+ 'CVSSv3_Severity',
+ 'CVSSv3_Score',
+ 'CVE Description',
+ 'YP Comments',
+ 'Created Date',
+ 'Modified Date',
+ 'YP Acknowledged Date',
+ ]
+ # Assemble the product column namess
+ for product in product_list:
+ product_title = product.key
+ header.append(product_title)
+ min_len = max(16,len(product_title)+1)
+ str_format = "%s%ds," % ('%',min_len)
+ text_format += str_format
+# # Add Top Defect
+# header.append('Top Defect')
+# text_format += '%s'
+
+ # Print the header
+ if 'csv' == format:
+ writer = csv.writer(csvfile, delimiter=separator, quotechar='"', quoting=csv.QUOTE_MINIMAL)
+ writer.writerow(header)
+ else:
+ writer = csvfile
+ print(text_format % tuple(header), file=csvfile)
+
+ for i,cve in enumerate(Cve.objects.filter(status__in=status_list).order_by('name_sort')):
+ # Compute the product columns
+ status_table,product_top_defect = self.get_product_status_matrix(product_list,cve)
+ # Assemble the row data
+ if cve.description:
+ if truncate:
+ description = cve.description[:26] + '...'
+ else:
+ description = cve.description
+ else:
+ description = ''
+
+ # Use publish date if acknowledge date not available
+ try:
+ acknowledge_date = cve.acknowledge_date
+ if not acknowledge_date:
+ acknowledge_date = datetime.strptime(cve.publishedDate, '%Y-%m-%d')
+ acknowledge_date = acknowledge_date.strftime('%m/%d/%Y')
+ except:
+ acknowledge_date = ''
+ _log("NO ACK:%s,%s" % (cve.acknowledge_date,cve.publishedDate))
+
+ row = [
+ cve.name,
+ cve.get_status_text,
+ cve.cvssV2_severity,
+ cve.cvssV2_baseScore,
+ cve.cvssV3_baseSeverity,
+ cve.cvssV3_baseScore,
+ description,
+ cve.get_public_comments[:20] if truncate else cve.get_public_comments,
+ cve.srt_created.strftime('%Y/%m/%d') if cve.srt_created else '',
+ cve.srt_updated.strftime('%Y/%m/%d') if cve.srt_updated else '',
+ acknowledge_date,
+ ]
+ # Append the product columns
+ for product in product_list:
+ # Show inactive status as normal status
+ row.append(status_table[product.key].replace('(','').replace(')',''))
+# row.append('/'.join(product_top_defect))
+ # Print the row
+ if 'csv' == format:
+ writer.writerow(row)
+ else:
+ print(text_format % tuple(row), file=writer)
+
+
+ return report_name,os.path.basename(report_name)
+
+
class CpesSrtoolReport(Report):
"""Report for the Publish Cve Page"""
@@ -2177,6 +2369,8 @@ class ReportManager():
return PublishListReport(parent_page, *args, **kwargs)
elif 'publish-list' == parent_page:
return PublishListReport(parent_page, *args, **kwargs)
+ elif 'publish-summary' == parent_page:
+ return PublishSummaryReport(parent_page, *args, **kwargs)
elif 'package-filters' == parent_page:
return PackageFiltersReport(parent_page, *args, **kwargs)
diff --git a/lib/srtgui/templates/publish.html b/lib/srtgui/templates/publish.html
index 826e1953..b22445fc 100644
--- a/lib/srtgui/templates/publish.html
+++ b/lib/srtgui/templates/publish.html
@@ -8,7 +8,7 @@
{% block pagecontent %}
<div class="row">
<div class="col-md-7" style="padding-left: 50px;">
- <h1>Management</h1>
+ <h1>Publish the CVE Database Status</h1>
</div>
</div>
<div class="row">