aboutsummaryrefslogtreecommitdiffstats
path: root/lib/srtgui/views.py
diff options
context:
space:
mode:
Diffstat (limited to 'lib/srtgui/views.py')
-rw-r--r--lib/srtgui/views.py973
1 files changed, 743 insertions, 230 deletions
diff --git a/lib/srtgui/views.py b/lib/srtgui/views.py
index d87dca38..79bf7b17 100644
--- a/lib/srtgui/views.py
+++ b/lib/srtgui/views.py
@@ -37,13 +37,15 @@ from orm.models import Investigation, InvestigationHistory, InvestigationToDefec
from orm.models import SrtSetting, Product
from orm.models import Package
from orm.models import DataSource
-from orm.models import Defect, PublishPending
+from orm.models import Defect, DefectHistory, PublishPending, PublishSet
from orm.models import Notify, NotifyAccess, NotifyCategories
+from orm.models import SRTool, Update
from users.models import SrtUser, UserSafe
from srtgui.reports import ReportManager
from srtgui.api import readCveDetails, writeCveDetails, summaryCveDetails, execute_process
+from srtgui.api import publishCalculate, publishReset, publishMarkNew, publishMarkModified, publishMarkNone
from django.urls import reverse, resolve
from django.core.paginator import EmptyPage, PageNotAnInteger
@@ -59,6 +61,10 @@ logger = logging.getLogger("srt")
# quick development/debugging support
from srtgui.api import _log
+#
+# ================= Helper Routines ============================================
+#
+
def get_name_sort(cve_name):
try:
a = cve_name.split('-')
@@ -67,6 +73,10 @@ def get_name_sort(cve_name):
cve_name_sort = cve_name
return cve_name_sort
+#
+# ================= Page Helper Routines ============================================
+#
+
class MimeTypeFinder(object):
# setting this to False enables additional non-standard mimetypes
# to be included in the guess
@@ -450,10 +460,10 @@ def management(request):
return redirect(landing)
# Keep it simple now, later use Q sets
- defect_open = Defect.objects.filter(status=Defect.OPEN)
- defects_inprogress = Defect.objects.filter(status=Defect.IN_PROGRESS)
- defect_p1 = defect_open.filter(priority=Defect.HIGH).count() + defects_inprogress.filter(priority=Defect.HIGH).count()
- defect_p2 = defect_open.filter(priority=Defect.MEDIUM).count() + defects_inprogress.filter(priority=Defect.MEDIUM).count()
+ defect_open = Defect.objects.filter(status=Defect.DEFECT_STATUS_OPEN)
+ defects_inprogress = Defect.objects.filter(status=Defect.DEFECT_STATUS_IN_PROGRESS)
+ defect_p1 = defect_open.filter(priority=Defect.CRITICAL).count() + defects_inprogress.filter(priority=Defect.CRITICAL).count()
+ defect_p2 = defect_open.filter(priority=Defect.HIGH).count() + defects_inprogress.filter(priority=Defect.HIGH).count()
defect_open = defect_open.count()
defects_inprogress = defects_inprogress.count()
@@ -467,15 +477,15 @@ def management(request):
'vulnerability_total' : Vulnerability.objects.all().count(),
'vulnerability_open' : Vulnerability.objects.filter(outcome=Vulnerability.OPEN).count(),
+ 'vulnerability_critical' : Vulnerability.objects.filter(outcome=Vulnerability.OPEN).filter(priority=Vulnerability.CRITICAL).count(),
'vulnerability_high' : Vulnerability.objects.filter(outcome=Vulnerability.OPEN).filter(priority=Vulnerability.HIGH).count(),
'vulnerability_medium' : Vulnerability.objects.filter(outcome=Vulnerability.OPEN).filter(priority=Vulnerability.MEDIUM).count(),
- 'vulnerability_low' : Vulnerability.objects.filter(outcome=Vulnerability.OPEN).filter(priority=Vulnerability.HIGH).count(),
'investigation_total' : Investigation.objects.all().count(),
'investigation_open' : Investigation.objects.filter(outcome=Investigation.OPEN).count(),
+ 'investigation_critical' : Investigation.objects.filter(outcome=Investigation.OPEN).filter(priority=Investigation.CRITICAL).count(),
'investigation_high' : Investigation.objects.filter(outcome=Investigation.OPEN).filter(priority=Investigation.HIGH).count(),
'investigation_medium' : Investigation.objects.filter(outcome=Investigation.OPEN).filter(priority=Investigation.MEDIUM).count(),
- 'investigation_low' : Investigation.objects.filter(outcome=Investigation.OPEN).filter(priority=Investigation.HIGH).count(),
'defect_total' : Defect.objects.all().count(),
'defect_open' : defect_open,
@@ -487,6 +497,20 @@ def management(request):
}
return render(request, 'management.html', context)
+def maintenance(request):
+ # does this user have permission to see this record?
+ if not UserSafe.is_creator(request.user):
+ return redirect(landing)
+
+ context = {
+ 'history_cve_total' : CveHistory.objects.all().count(),
+ 'history_vulnerability_total' : VulnerabilityHistory.objects.all().count(),
+ 'history_investigation_total' : InvestigationHistory.objects.all().count(),
+ 'defect_investigation_total' : DefectHistory.objects.all().count(),
+ }
+ return render(request, 'maintenance.html', context)
+
+
def cve(request, cve_pk, active_tab="1"):
if request.method == "GET":
template = "cve.html"
@@ -520,23 +544,31 @@ def cve(request, cve_pk, active_tab="1"):
cve_index = ord('1')
is_edit = ('Edit' == active_tab)
- # Prepend summary page?
+ # Fetch source tabs list
cve_sources = CveSource.objects.filter(cve=cve_object.id).order_by('datasource__key')
- if True or (1 < len(cve_sources)):
- tab_states[chr(cve_index)] = ''
- cveDetails,cve_html = summaryCveDetails(cve_object,cve_sources)
- cve_list_table.append([cveDetails,tab_states[chr(cve_index)],'Summary',cve_html])
- cve_index += 1
+ # Always pre-pend a summary page
+ tab_states[chr(cve_index)] = 'active'
+ cveDetails,cve_html = summaryCveDetails(cve_object,cve_sources)
+ cve_list_table.append([cveDetails,tab_states[chr(cve_index)],'Summary',cve_html])
+ cve_index += 1
# Add the source/edit tabs
- for cs in cve_sources:
+ for i in range(len(cve_sources)):
+ if (i < (len(cve_sources)-1)) and (cve_sources[i].datasource.source == cve_sources[i+1].datasource.source):
+ # Insure one source per vendor where the highest key wins (e.g. NIST Modified)
+ continue
+ pass
+
+ cs = cve_sources[i]
if active_tab == cs.datasource.name:
active_tab = chr(cve_index)
if ('Edit' == active_tab) and ('Local' == cs.datasource.name):
- tab_states[chr(cve_index)] = 'active'
+ #tab_states[chr(cve_index)] = 'active'
+ tab_states[chr(cve_index)] = ''
cve_list_table.append([readCveDetails(cve_object,cs.datasource),tab_states[chr(cve_index)],'Edit',{}])
else:
- tab_states[chr(cve_index)] = 'active' if (active_tab == chr(cve_index)) else ''
+ tab_states[chr(cve_index)] = ''
+ #tab_states[chr(cve_index)] = 'active' if (active_tab == chr(cve_index)) else ''
cve_list_table.append([readCveDetails(cve_object,cs.datasource),tab_states[chr(cve_index)],cs.datasource.name,{}])
cve_index += 1
if 0 == len(cve_sources):
@@ -552,11 +584,6 @@ def cve(request, cve_pk, active_tab="1"):
tab_states['1'] = 'active'
cve_list_table[0][1] = 'active'
-
- # cve_summary = copy.copy(cve_object)
- # cve_summary_detail = copy.copy(cve_object_detail)
- # cve_summary.source = 'Summary'
- #
context = {
'object' : cve_object,
'cve_list_table' : cve_list_table,
@@ -583,7 +610,7 @@ def cve(request, cve_pk, active_tab="1"):
# Is this not a save?
if not request.POST.get('cve-edit','').startswith('Save'):
- return redirect(cve, cve_object.id, "Local")
+ return redirect(cve, cve_object.id, "Summary")
# does this user have permission to see this record?
if (not cve_object.public) and (not UserSafe.is_admin(request.user)):
@@ -594,7 +621,7 @@ def cve(request, cve_pk, active_tab="1"):
writeCveDetails(cve_object.name,request)
# show the results
- return redirect(cve, cve_object.id, "Local")
+ return redirect(cve, cve_object.id, "Summary")
def cve_edit(request, cve_pk):
_log("CVE_EDIT1(%s):" % cve_pk)
@@ -677,12 +704,14 @@ def vulnerability(request, vulnerability_pk):
_log("EXPORT_POST:'fileupload' does not exist: %s" % e)
try:
- with open(path + "/" + file.name, 'xb+') as destination:
+ local_file_path = path + "/" + file.name
+ with open(local_file_path, 'xb+') as destination:
for line in file:
destination.write(line)
username = UserSafe.user_name(request.user)
- VulnerabilityUploads.objects.get_or_create(vulnerability_id=vulnerability_object.id, description=description, path=path + "/" + file.name, size=file.size, date=datetime.today().strftime('%Y-%m-%d'), author=username)
+ VulnerabilityUploads.objects.get_or_create(vulnerability_id=vulnerability_object.id, description=description, path=local_file_path, size=file.size, date=datetime.today().strftime('%Y-%m-%d'), author=username)
+ VulnerabilityHistory.objects.create(vulnerability_id=vulnerability_object.id, comment=Update.ATTACH_DOC % file.name, date=datetime.now().strftime(SRTool.DATE_FORMAT), author=username)
except Exception as e:
_log("EXPORT_POST:FILE ALREADY EXISTS: %s" % e)
return redirect(vulnerability,vulnerability_pk)
@@ -722,16 +751,32 @@ def investigation(request, investigation_pk):
except:
return redirect(landing)
+ ### TO-DO: replace with dynamic lookahead instead of static huge list
defects = Defect.objects.all()
+
+ # Calculate the default 'affected_components' list, if any
+ affected_components = ''
+ affected_components_list = []
+ vulnerability = investigation_object.vulnerability
+ vc_list = vulnerability.vulnerability_to_cve.all()
+ for vc in vc_list:
+ if vc.cve.packages:
+ affected_components_list.append(vc.cve.packages)
+ if affected_components_list:
+ affected_components = ' '.join(affected_components_list)
+
+ # Pass Investigation's defect list
investigation_to_defect = investigation_object.investigation_to_defect.all()
context = {
'object' : investigation_object,
'defects' : defects,
'investigation_to_defect' : investigation_to_defect,
+ 'affected_components' : affected_components,
'defect_example' : SrtSetting.objects.get(name='SRTOOL_DEFECT_SAMPLENAME').value,
'notify_categories' : NotifyCategories.objects.all(),
'users' : UserSafe.get_safe_userlist(True),
'components' : Defect.Components,
+ 'found_version' : investigation_object.product.get_defect_tag('found_version'),
}
return render(request, template, context)
elif request.method == "POST":
@@ -757,11 +802,13 @@ def investigation(request, investigation_pk):
_log("EXPORT_POST:'fileupload' does not exist: %s" % e)
try:
- with open(path + "/" + file.name, 'xb+') as destination:
+ local_file_path = path + "/" + file.name
+ with open(local_file_path, 'xb+') as destination:
for line in file:
destination.write(line)
username = UserSafe.user_name(request.user)
- InvestigationUploads.objects.get_or_create(investigation_id=investigation_object.id, description=description, path=path + "/" + file.name, size=file.size, date=datetime.today().strftime('%Y-%m-%d'), author=username)
+ InvestigationUploads.objects.get_or_create(investigation_id=investigation_object.id, description=description, path=local_file_path, size=file.size, date=datetime.today().strftime('%Y-%m-%d'), author=username)
+ InvestigationHistory.objects.create(investigation_id=investigation_object.id, comment=Update.ATTACH_DOC % file.name, date=datetime.now().strftime(SRTool.DATE_FORMAT), author=username)
except Exception as e:
_log("EXPORT_POST:FILE ALREADY EXISTS: %s" % e)
return redirect(investigation,investigation_pk)
@@ -797,6 +844,7 @@ def defect(request, defect_pk):
context = {
'object' : defect_object,
'users' : users,
+ 'SRTOOL_DEFECT_URLBASE' : SrtSetting.objects.get(name='SRTOOL_DEFECT_URLBASE').value
}
return render(request, template, context)
@@ -876,6 +924,7 @@ def users(request):
return render(request, template, context)
def report(request,page_name):
+ _log("REPORT!:%s" % (request))
if request.method == "GET":
context = ReportManager.get_context_data(page_name,request=request)
record_list = request.GET.get('record_list', '')
@@ -883,7 +932,7 @@ def report(request,page_name):
context['record_list'] = record_list
return render(request, 'report.html', context)
elif request.method == "POST":
- _log("EXPORT_POST!:%s|%s" % (request,request.FILES))
+ _log("EXPORT_POST!:%s" % (request))
parent_page = request.POST.get('parent_page', '')
file_name,response_file_name = ReportManager.exec_report(parent_page,request=request)
@@ -926,13 +975,153 @@ def create_vulnerability(request):
context = {}
return render(request, 'create_vulnerability.html', context)
+class Snap():
+ def __init__(self,snap_index=0,snap_mode='None',snap_dir='',snap_date='',snap_time='',snap_day=''):
+ self.index = '%02d' % snap_index
+ self.mode = snap_mode
+ self.dir = snap_dir
+ self.date = snap_date
+ self.time = snap_time
+ self.day = snap_day
+
+class ReportFile():
+ def __init__(self,name='',size=0,date=None):
+ self.name = name
+ self.size = size
+ self.date = date
+
def publish(request):
# does this user have permission to see this record?
if not UserSafe.is_creator(request.user):
return redirect(landing)
+ if request.method == "GET":
+
+ # Prepare available snapshots
+ snapshot_list = []
+ snap_start_index = 0
+ snap_stop_index = 0
+ snap_date_base = SrtSetting.get_setting('publish_snap_date_base','2019-06-08')
+ snap_date_top = SrtSetting.get_setting('publish_snap_date_top','2019-06-16')
+ snap_date_start = SrtSetting.get_setting('publish_snap_date_start','2019-06-08')
+ snap_date_stop = SrtSetting.get_setting('publish_snap_date_stop','2019-06-16')
+ snap_last_calc = SrtSetting.get_setting('publish_snap_last_calc','')
+ backup_returncode,backup_stdout,backup_result = execute_process('bin/common/srtool_backup.py','--list-backups-db')
+ for i,line in enumerate(backup_stdout.decode("utf-8").splitlines()):
+ # Week|backup_2019_19|2019-05-18|12:51:51|Saturday, May 18 2019
+ backup_mode,backup_dir,backup_date,backup_time,backup_day = line.split('|')
+ if 'Now' != backup_mode:
+ snap = Snap(i,backup_mode,backup_dir,backup_date,backup_time,backup_day)
+ snapshot_list.append(snap)
+ if snap_date_base == snap.date:
+ snap_start_index = i
+ if snap_date_start < snap.date:
+ snap_date_start = snap.date
+ if snap_date_stop < snap.date:
+ snap_date_stop = snap.date
+ if snap_date_top == snap.date:
+ snap_stop_index = i
+ if snap_date_stop > snap.date:
+ snap_date_stop = snap.date
+ if not snap_stop_index:
+ snap_stop_index = i
+ if snap_date_stop < snap.date:
+ snap_date_stop = snap.date
+ # Report automation
+ snap_frequency_select = SrtSetting.get_setting('publish_snap_frequency','Off')
+ snapshot_frequency_list = [
+ 'Off',
+ 'Monthly',
+ 'Bi-monthly',
+ 'Weekly',
+ 'Daily',
+ ]
+ # List of available reports
+ generated_report_list = []
+ for entry in os.scandir('data/wr'):
+ if entry.name.startswith('cve-svns-srtool'):
+ generated_report_list.append(ReportFile(entry.name,entry.stat().st_size,datetime.fromtimestamp(entry.stat().st_mtime)))
+# generated_report_list.sort()
+ generated_report_list = sorted(generated_report_list,key=lambda x: x.name)
+
+ # Prepare History data
+ last_calc = SrtSetting.get_setting('publish_last_calc','06/08/2019')
+ date_start = SrtSetting.get_setting('publish_date_start','06/08/2019')
+ date_stop = SrtSetting.get_setting('publish_date_stop','06/21/2019')
+
+ context = {
+ 'date_start' : date_start,
+ 'date_stop' : date_stop,
+ 'last_calc' : last_calc,
+
+ 'snap_date_start' : snap_date_start,
+ 'snap_date_stop' : snap_date_stop,
+ 'snap_date_base' : snap_date_base,
+ 'snap_date_top' : snap_date_top,
+ 'snapshot_list' : snapshot_list,
+ 'snap_start_index' : '%02d' % snap_start_index,
+ 'snap_stop_index' : '%02d' % snap_stop_index,
+ 'snap_last_calc' : snap_last_calc,
+ 'generated_report_list' : generated_report_list,
+
+ 'snapshot_frequency_list' : snapshot_frequency_list,
+ 'snap_frequency_select' : snap_frequency_select,
+ }
+ return render(request, 'publish.html', context)
+ elif request.method == "POST":
+ action = request.POST['action']
+
+ if request.POST["action"] == "download":
+ report_name = request.POST['report_name']
+ file_path = 'data/wr/%s' % report_name
+ if file_path:
+ fsock = open(file_path, "rb")
+ content_type = MimeTypeFinder.get_mimetype(file_path)
+ response = HttpResponse(fsock, content_type = content_type)
+ disposition = 'attachment; filename="{}"'.format(file_path)
+ response['Content-Disposition'] = 'attachment; filename="{}"'.format(file_path)
+ _log("EXPORT_POST_Q{%s} %s || %s " % (response, response['Content-Disposition'], disposition))
+ return response
+ else:
+ return render(request, "unavailable_artifact.html", context={})
+
+ # Dates (make as no timezone)
+ msg = ''
+ try:
+ msg = 'Start:%s' % request.POST.get('date_start', '')
+ date_start = datetime.strptime(request.POST.get('date_start', ''), '%m/%d/%Y')
+ msg = 'Stop:%s' % request.POST.get('date_stop', '')
+ date_stop = datetime.strptime(request.POST.get('date_stop', ''), '%m/%d/%Y')
+ if date_stop < date_start:
+# return 'Error:stop date is before start date'
+ _log('Error:stop date is before start date')
+ pass
+ except Exception as e:
+# return 'Error:bad format for dates (must be mm/dd/yyyy) (%s)(%s)' % (msg,e),''
+ _log('Error:bad format for dates (must be mm/dd/yyyy) (%s)(%s)' % (msg,e))
+ pass
+ SrtSetting.set_setting('publish_date_start',date_start.strftime('%m/%d/%Y'))
+ SrtSetting.set_setting('publish_date_stop',date_stop.strftime('%m/%d/%Y'))
+ if 'recalculate' == action:
+ # Calculate
+ publishCalculate(date_start,date_stop)
+ return redirect('publish')
+ if 'view' == action:
+ # Go to publish list page
+ return redirect('publish-list')
+ if 'add-cve' == action:
+ # Go to publish list page
+ return redirect('publish-cve')
+ if 'add-defect' == action:
+ # Go to publish list page
+ return redirect('publish-defect')
+ if 'reset' == action:
+ publishReset(date_start,date_stop)
+ publishCalculate(date_start,date_stop)
+ return redirect('publish')
+ if 'export' == action:
+ return redirect('/wr/report/publish')
+ return redirect('publish')
- context = {}
- return render(request, 'publish.html', context)
def manage_report(request):
# does this user have permission to see this record?
@@ -952,31 +1141,66 @@ def guided_tour(request):
def quicklink(request):
return redirect("/srtgui/select-publish")
-def _create_defect(investigation,defect_reason,components):
- _log("SRT_DEFECT=%s|%s|%s|" % (investigation.name,defect_reason,components))
+# Return defect_name,isCreated
+def _create_defect(investigation,reason,defect_reason,domain_components,affected_components,username):
+ _log("SRT_DEFECT=%s|%s|%s|%s|" % (investigation.name,defect_reason,domain_components,affected_components))
+
+ # Check to see if defect creation is allowed for this product
+ if 'no' == investigation.product.get_defect_tag('auto_create','yes'):
+ _log("SRT_DEFECT_SKIPPED:NO_auto_create:%s" % (investigation.product.defect_tags))
+ return '(%s skipped)' % investigation.product.key,False
+
+ # Check to see if a defect already is created for this investigation
+ try:
+ for id in InvestigationToDefect.objects.filter(investigation=investigation):
+ # First defect wins
+ _log("SRT_DEFECT_EXISTING:%s" % (id.defect.name))
+ return id.defect.name, False
+ except:
+ pass
vulnerability = investigation.vulnerability
vc_list = vulnerability.vulnerability_to_cve.all()
- # gather name(s) and link(s) of parent CVE(s)
+ # Gather name(s) and link(s) of parent CVE(s)
cve_list = [vc.cve.name for vc in vc_list]
cves = ','.join(cve_list)
+
+ # Offer a default defect description
description = ['%s\n' % vc.cve.description for vc in vc_list]
+
### TODO: normal NIST link might not always work
- link_list = ['https://nvd.nist.gov/vuln/detail/%s' % vc.cve.name for vc in vc_list]
- links = ','.join(cve_list)
+ link_list = []
+ for vc in vc_list:
+ link_list.append('https://nvd.nist.gov/vuln/detail/%s' % vc.cve.name)
+
+ # Fix links to make if Jira friendly
+ # CREATE(Triage): {Link=https://nvd.nist.gov/vuln/detail/CVE-2019-8934 User=admin}
+# links = "%s {%sLink=%s User=%s}" % (Update.CREATE_STR % Update.SOURCE_TRIAGE,"Reason='%s' " % reason if reason else '',' '.join(link_list),username)
+ # CREATE(Triage):(User=admin) [CVE-2019-8934|https://nvd.nist.gov/vuln/detail/CVE-2019-8934]
+ links = "%s%s(User=%s)" % (Update.CREATE_STR % Update.SOURCE_TRIAGE,"(Reason='%s')" % reason if reason else '',username)
+ for link in link_list:
+ links += ' [%s|%s]' % (os.path.basename(link),link)
# Assign the defect the same priority as the Investigation
priority = investigation.get_priority_text
+ _log("_create_defect:%s:%s:%s" % (investigation.name,priority,links))
- # Component string (e.g. 'kernel', 'userspace', ...)
- if not components:
- components = 'unknown'
- # Offer a defect summary
+ # Offer a default defect summary
+ if not defect_reason:
+ defect_reason = affected_components
if defect_reason:
summary = "Security Advisory - %s - %s" % (defect_reason,cves)
else:
summary = "Security Advisory %s" % (cves)
+
+ # Add the affect components
+ if affected_components:
+ affected_components.replace(',',' ').replace(';',' ').replace(' ',' ')
+ components = "%s {COMPONENTS:%s}" % (domain_components,affected_components)
+ else:
+ components = domain_components
+
defect_tool = SrtSetting.objects.get(name='SRTOOL_DEFECT_TOOL').value
result_returncode,result_stdout,result_stderr = execute_process(
defect_tool, '--new',
@@ -1019,6 +1243,11 @@ def _create_defect(investigation,defect_reason,components):
d = Defect.objects.create(name=d_name)
d.summary = summary
d.priority = investigation.priority
+ d.status = Defect.DEFECT_STATUS_OPEN
+ d.resolution = Defect.DEFECT_UNRESOLVED
+ d.srt_priority = investigation.priority
+ d.srt_status = Defect.VULNERABLE
+ d.srt_outcome = Defect.OPEN
d.product = investigation.product
d.url = d_url
d.save()
@@ -1026,7 +1255,24 @@ def _create_defect(investigation,defect_reason,components):
# Create Investigation to Defect
id = InvestigationToDefect.objects.create(investigation=investigation,defect=d,product=investigation.product)
id.save()
- return d.name
+ return d.name,True
+
+def _auto_map_cve_priority(cve,force=True):
+ if not force and (SRTool.UNDEFINED != cve.priority):
+ return(cve.priority)
+ severity = cve.cvssV3_baseSeverity.strip()
+ if not severity:
+ severity = cve.cvssV2_severity.strip()
+ if not severity:
+ severity = 'MEDIUM'
+ if 'CRITICAL' == severity:
+ return(SRTool.CRITICAL)
+ elif 'HIGH' == severity:
+ return(SRTool.HIGH)
+ elif 'MEDIUM' == severity:
+ return(SRTool.MEDIUM)
+ else:
+ return(SRTool.LOW)
def xhr_triage_commit(request):
_log("xhr_triage_commit(%s)" % request.POST)
@@ -1035,7 +1281,8 @@ def xhr_triage_commit(request):
try:
username = UserSafe.user_name(request.user)
action = request.POST['action']
- today = datetime.today().strftime("%Y-%m-%d")
+ srtool_today_time = datetime.today()
+ srtool_today = datetime.today().strftime("%Y-%m-%d")
if 'submit-notvulnerable' == action:
reason = request.POST['reason']
cves = request.POST['cves']
@@ -1044,85 +1291,83 @@ def xhr_triage_commit(request):
created_list = ''
for cve_name in cves.split(','):
cve = Cve.objects.get(name=cve_name)
+ history_update = []
+ history_update.append(Update.STATUS % (SRTool.status_text(cve.status),SRTool.status_text(Cve.NOT_VULNERABLE)))
+ cve.priority = _auto_map_cve_priority(cve,False)
cve.status = Cve.NOT_VULNERABLE
if cve.comments:
cve.comments += ', ' + reason
else:
cve.comments = reason
+ cve.acknowledge_date = srtool_today_time
cve.save()
created_list += ' %s' % cve_name
# add audit comment
cc = CveHistory.objects.create(cve=cve)
- cc.date = today
- cc.comment = "ACTION: marked not vulnerable, reason='%s'" % (reason)
+ cc.date = srtool_today
+ cc.comment = "%s%s {%s}" % (Update.UPDATE_STR % Update.SOURCE_USER,';'.join(history_update),"Set by triage, reason='%s'" % reason)
cc.author = username
cc.save()
if created_list:
created_list = "NotVulnerable:" + created_list
- if 'submit-investigate' == action:
- cves = request.POST['cves']
- created_list = ''
- for cve_name in cves.split(','):
- cve = Cve.objects.get(name=cve_name)
- cve.status = Cve.INVESTIGATE
- cve.save()
- created_list += ' %s' % cve_name
- # add audit comment
- cc = CveHistory.objects.create(cve=cve)
- cc.date = today
- cc.comment = "ACTION: marked investigate"
- cc.author = username
- cc.save()
- if created_list:
- created_list = "Investigate:" + created_list
-
if 'submit-other' == action:
cves = request.POST['cves']
status = int(request.POST['status'])
created_list = ''
for cve_name in cves.split(','):
cve = Cve.objects.get(name=cve_name)
+ history_update = []
+ history_update.append(Update.STATUS % (SRTool.status_text(cve.status),SRTool.status_text(status)))
+ cve.priority = _auto_map_cve_priority(cve,False)
cve.status = status
+ cve.acknowledge_date = srtool_today_time
cve.save()
created_list += ' %s' % cve_name
# add audit comment
cc = CveHistory.objects.create(cve=cve)
- cc.date = today
- cc.comment = "ACTION: set status to %s" % cve.get_status_text
+ cc.date = srtool_today
+ cc.comment = "%s%s {%s}" % (Update.UPDATE_STR % Update.SOURCE_USER,';'.join(history_update),"Set by triage")
cc.author = username
cc.save()
if created_list:
created_list = "Status=%s:%s" % (cve.get_status_text,created_list)
- if 'submit-isvulnerable' == action:
+ if action in ('submit-isvulnerable','submit-investigate'):
+ if 'submit-isvulnerable' == action:
+ notify_message = 'Triage:Vulnerable:'
+ new_status = SRTool.VULNERABLE
+ elif 'submit-investigate' == action:
+ notify_message = 'Triage:Investigate:'
+ new_status = SRTool.INVESTIGATE
reason = request.POST['reason'].strip()
defect_reason = request.POST['defect_reason'].strip()
cves = request.POST['cves']
products = request.POST['products']
components = request.POST['components']
- priority = request.POST['priority']
+ affected_components = request.POST['affected_components'].strip()
+ priority = int(request.POST['priority'])
make_defects = ('yes' == request.POST['mk_d'])
mark_publish = ('yes' == request.POST['pub'])
group_vulnerability = int(request.POST['vul_group'])
group_vulnerability_name = request.POST['vul_name'].strip()
notifications = ('yes' == request.POST['notify'])
+ acknowledge_date = request.POST['acknowledge_date']
add_for = request.POST['for']
_log("xhr_triage_commit:IS:%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|" % (reason,defect_reason,cves,products,components,make_defects,mark_publish,add_for,priority,group_vulnerability,group_vulnerability_name))
# Set up
- investigation_names = {}
created_list = ''
- notify_message = 'Triage:Vulnerable:'
+
# Map vulnerability grouping
- v = None
+ vulnerability = None
if 2 == group_vulnerability:
# Existing V all C
first_vulnerability = False
group_vulnerabilities = True
try:
- v = Vulnerability.objects.get(name=group_vulnerability_name)
- created_list += ' %s(found)' % v.name
- notify_message += ' Found:%s' % v.name
+ vulnerability = Vulnerability.objects.get(name=group_vulnerability_name)
+ created_list += ' %s(found)' % vulnerability.name
+ notify_message += ' Found:%s' % vulnerability.name
except Exception as e:
_log("xhr_triage_commit:No such Vulnerability name found (%s,%s)" % (group_vulnerability_name,e))
return HttpResponse(json.dumps({"error":"No such Vulnerability name found (%s)" % (group_vulnerability_name)}), content_type = "application/json")
@@ -1134,91 +1379,159 @@ def xhr_triage_commit(request):
# One V per C
first_vulnerability = True
group_vulnerabilities = False
+
# Process the CVE list
for cve_name in cves.split(','):
# update CVE
cve = Cve.objects.get(name=cve_name)
- cve.status = Cve.VULNERABLE
- cve.priority = priority
+ # Auto priority?
+ cve_priority = _auto_map_cve_priority(cve) if 99 == priority else priority
if cve.comments:
- cve.comments += ', ' + reason
+ cve_comments = '%s, %s' % (cve.comments,reason)
else:
- cve.comments = reason
+ cve_comments = reason
+ # Acknowledge date selection
+ try:
+ if ('publish' == acknowledge_date) and cve.publishedDate:
+ cve_acknowledge_date = datetime.strptime(cve.publishedDate, '%Y-%m-%d')
+ elif ('update' == acknowledge_date) and cve.lastModifiedDate:
+ cve_acknowledge_date = datetime.strptime(cve.lastModifiedDate, '%Y-%m-%d')
+ elif ('no_change' == acknowledge_date):
+ cve_acknowledge_date = cve.acknowledge_date
+ else:
+ cve_acknowledge_date = srtool_today_time
+ except:
+ cve_acknowledge_date = srtool_today_time
+ # Update history changes
+ history_update = []
+ if cve.status != new_status:
+ history_update.append(Update.STATUS % (SRTool.status_text(cve.status),SRTool.status_text(new_status)))
+ if cve.priority != cve_priority:
+ history_update.append(Update.PRIORITY % (SRTool.priority_text(cve.priority),SRTool.priority_text(cve_priority)))
+ if cve.acknowledge_date != cve_acknowledge_date:
+ history_update.append(Update.ACKNOWLEDGE_DATE % (cve.acknowledge_date.strftime("%Y/%m/%d") if cve.acknowledge_date else '',cve_acknowledge_date.strftime("%Y/%m/%d")))
+ # Update record
+ cve.status = new_status
+ cve.priority = cve_priority
+ cve.comments = cve_comments
+ cve.acknowledge_date = cve_acknowledge_date
+ cve.packages = affected_components
cve.save()
notify_message += " %s" % cve_name
- # create vulnerability
+ # Add history comment
+ if history_update:
+ cc = CveHistory.objects.create(cve=cve)
+ cc.date = srtool_today
+ cc.comment = "%s%s {%s}" % (Update.UPDATE_STR % Update.SOURCE_USER,';'.join(history_update), "Triage:reason='%s'" % reason)
+ cc.author = username
+ cc.save()
+
+ # Find or create vulnerability
if first_vulnerability or not group_vulnerabilities:
first_vulnerability = False
- v_name = Vulnerability.new_vulnerability_name()
- v = Vulnerability.objects.create(name=v_name)
- v.public = True
- v.status = Vulnerability.VULNERABLE
- v.priority = priority
- v.comments = reason
- v.save()
- notify_message += " %s" % v_name
- created_list += ' %s' % v.name
- _log("Create First Vulnerability:%s" % v.name)
- # add audit comment
- cc = CveHistory.objects.create(cve=cve)
- cc.date = today
- cc.comment = "ACTION: created vulnerability '%s', reason='%s'" % (v.name,reason)
- cc.author = username
- cc.save()
+
+ # Check to see if a vulnerability already is created for this cve
+ vulnerability = None
+ try:
+ for cv in CveToVulnerablility.objects.filter(cve=cve):
+ # First vulnerability wins
+ vulnerability = cv.vulnerability
+ created_list += ' (%s)' % vulnerability.name
+ break
+ except:
+ pass
+
+ if not vulnerability:
+ v_name = Vulnerability.new_vulnerability_name()
+ vulnerability = Vulnerability.objects.create(name=v_name)
+ vulnerability.public = True
+ vulnerability.priority = cve_priority
+ vulnerability.status = new_status
+ vulnerability.outcome = Vulnerability.OPEN
+ vulnerability.comments = reason
+ vulnerability.save()
+ notify_message += " %s" % v_name
+ created_list += ' %s' % vulnerability.name
+ _log("Create First Vulnerability:%s" % vulnerability.name)
+
+ # add audit comment
+ vh = VulnerabilityHistory.objects.create(vulnerability=vulnerability)
+ vh.date = srtool_today
+ vh.comment = "%s {%s}" % (Update.CREATE_STR % Update.SOURCE_TRIAGE,'Created from triage')
+ vh.author = username
+ vh.save()
# map vulnerability to CVE
- cv = CveToVulnerablility.objects.create(vulnerability=v,cve=cve)
- cv.save()
- # add audit comment
- vc = VulnerabilityHistory.objects.create(vulnerability=v)
- vc.date = today
- vc.comment = "ACTION: created vulnerability for '%s', reason='%s'" % (cve.name,reason)
- vc.author = username
- vc.save()
+ cv,created = CveToVulnerablility.objects.get_or_create(vulnerability=vulnerability,cve=cve)
+ if created:
+ cv.save()
if products:
for product_id in products.split(','):
# fetch product
- p = Product.objects.get(pk=product_id)
+ product = Product.objects.get(pk=product_id)
# create (or group) investigation
- investigation_key = "%s-%s" % (v_name,product_id)
- i_name = ''
- if investigation_key in investigation_names:
- i_name = investigation_names[investigation_key]
- if not i_name or not group_vulnerabilities:
+
+ # Check to see if a investigation for this product already is created for this vulnerability
+ investigation = None
+ try:
+ for vi in VulnerabilityToInvestigation.objects.filter(vulnerability=vulnerability,investigation__product=product):
+ # First Investigation for this product wins
+ investigation = vi.investigation
+ created_list += ' (%s)' % investigation.name
+ break
+ except:
+ pass
+
+ if not investigation:
i_name = Investigation.new_investigation_name()
- i = Investigation.objects.create(name=i_name)
- i.vulnerability = v
- i.product = p
- i.priority = priority
- i.save()
- notify_message += " %s" % i_name
- created_list += ' %s' % i.name
- investigation_names[investigation_key] = i_name
+ investigation = Investigation.objects.create(name=i_name)
+ investigation.vulnerability = vulnerability
+ investigation.product = product
+ investigation.priority = cve_priority
+ investigation.outcome = Investigation.OPEN
+ # Check to see if product is active
+ _log("BOO1:")
+ if 'no' == product.get_product_tag('active','yes'):
+ _log("BOO2:%s,%s" % (investigation.status,SRTool.status_to_inactive(new_status)))
+ investigation.status = SRTool.status_to_inactive(new_status)
+ else:
+ _log("BOO3:")
+ investigation.status = new_status
+ _log("BOO4:%s" % investigation.status )
+
+ investigation.save()
+
+ notify_message += " %s" % investigation.name
+ created_list += ' %s' % investigation.name
# map vulnerability to investigation/product
- vi = VulnerabilityToInvestigation.objects.create(vulnerability=v,investigation = i)
+ vi = VulnerabilityToInvestigation.objects.create(vulnerability=vulnerability,investigation=investigation)
vi.save()
- else:
- i = Investigation.objects.get(name=i_name)
- # add audit comment
- ic = InvestigationHistory.objects.create(investigation=i)
- ic.date = today
- ic.comment = "ACTION: created investigation for '%s', reason='%s'" % (cve.name,reason)
- ic.author = username
- ic.save()
+
+ # add audit comment
+ ih = InvestigationHistory.objects.create(investigation=investigation)
+ ih.date = srtool_today
+ ih.comment = "%s {%s}" % (Update.CREATE_STR % Update.SOURCE_TRIAGE,'Created from triage')
+ ih.author = username
+ ih.save()
+
# create defects
if make_defects:
- defect_name = _create_defect(i,defect_reason,components)
- notify_message += " %s" % defect_name
- created_list += ' %s' % defect_name
- _log("NEW_DEFECT:%s|%s|%s|" % (defect_name,components,priority))
+ defect_name,created = _create_defect(investigation,reason,defect_reason,components,affected_components,username)
+ if created:
+ notify_message += ' %s' % defect_name
+ created_list += ' %s' % defect_name
+ else:
+ notify_message += ' (%s)' % defect_name
+ created_list += ' (%s)' % defect_name
+ _log("NEW_DEFECT:%s|%s|%s|" % (defect_name,components,cve_priority))
# Finish up
if notifications:
# Create the notify record
_log("xhr_notifications3")
notify = Notify()
notify.category = 'TRIAGE'
- notify.priority = priority
+ notify.priority = cve_priority
notify.description = notify_message
notify.url = ''
notify.author = username
@@ -1280,35 +1593,64 @@ def xhr_cve_commit(request):
try:
cve = Cve.objects.get(id=request.POST['cve_id'])
action = request.POST['action']
- history_comment = ''
+ history_update = []
new_name = ''
if 'submit-quickedit' == action:
- note = request.POST['note']
priority = int(request.POST['priority'])
status = int(request.POST['status'])
- private_note = request.POST['private_note']
- publish_state = request.POST['publish_state']
- publish_date = request.POST['publish_date']
- if (priority != cve.priority):
+ note = request.POST['note'].strip()
+ private_note = request.POST['private_note'].strip()
+ tags = request.POST['tags'].strip()
+ publish_state = int(request.POST['publish_state'])
+ publish_date = request.POST['publish_date'].strip()
+ acknowledge_date = request.POST['acknowledge_date'].strip()
+ affected_components = request.POST['affected_components'].strip()
+ # Convert simple date back to datetime
+ try:
+ if not acknowledge_date:
+ acknowledge_date = None
+ else:
+ acknowledge_date = datetime.strptime(acknowledge_date, '%Y-%m-%d')
+ except Exception as e:
+ acknowledge_date = cve.acknowledge_date
+ if (cve.priority != priority):
+ history_update.append(Update.PRIORITY % (SRTool.priority_text(cve.priority),SRTool.priority_text(priority)))
cve.priority = priority
- history_comment += "Priority, "
- if (status != cve.status):
+ if (cve.status != status):
+ history_update.append(Update.STATUS % (SRTool.status_text(cve.status),SRTool.status_text(status)))
cve.status = status
- history_comment += "Status, "
- if (note != cve.comments):
+ if (cve.comments != note):
+ history_update.append(Update.NOTE)
cve.comments = note
- history_comment += "Note, "
- if (private_note != cve.comments_private):
+ if (cve.comments_private != private_note):
+ history_update.append(Update.PRIVATE_NOTE)
cve.comments_private = private_note
- history_comment += "Private Note, "
- if (publish_state != cve.publish_state):
+ if ( cve.tags !=tags):
+ history_update.append(Update.TAG)
+ cve.tags = tags
+ if (cve.publish_state != publish_state):
+ history_update.append(Update.PUBLISH_STATE % (SRTool.publish_text(cve.publish_state),SRTool.publish_text(publish_state)))
cve.publish_state = publish_state
- history_comment += "Publish State, "
- if (publish_date != cve.publish_date):
+ if (cve.publish_date != publish_date):
+ history_update.append(Update.PUBLISH_DATE % (SRTool.date_ymd_text(cve.publish_date),SRTool.date_ymd_text(publish_date)))
cve.publish_date = publish_date
- history_comment += "Publish Date, "
+ if (cve.packages != affected_components):
+ history_update.append(Update.AFFECTED_COMPONENT % (cve.packages,affected_components))
+ cve.packages = affected_components
+ # Allow for either acknowledge_date to be empty/None
+ if (cve.acknowledge_date and not acknowledge_date):
+ history_update.append(Update.ACKNOWLEDGE_DATE % (SRTool.date_ymd_text(cve.acknowledge_date),''))
+ cve.acknowledge_date = None
+ elif (not cve.acknowledge_date and acknowledge_date):
+ cve.acknowledge_date = acknowledge_date
+ history_update.append(Update.ACKNOWLEDGE_DATE % (cve.acknowledge_date,SRTool.date_ymd_text(acknowledge_date)))
+ elif (cve.acknowledge_date != acknowledge_date):
+ history_update.append(Update.ACKNOWLEDGE_DATE % (SRTool.date_ymd_text(cve.acknowledge_date),SRTool.date_ymd_text(acknowledge_date)))
+ cve.acknowledge_date = acknowledge_date
+
cve.save()
if 'submit-notification' == action:
+ # Note: no history update
_submit_notification(request)
if 'submit-newname' == action:
old_name = request.POST['old_name']
@@ -1319,6 +1661,7 @@ def xhr_cve_commit(request):
return HttpResponse(json.dumps({"error":"name '%s' is already used\n" % new_name}), content_type = "application/json")
except:
_log("NewName3:%s -> %s" % (old_name,new_name))
+ history_update.append(Update.NEW_NAME % (old_name,new_name))
# Apply this unique name to CVE
cve.name = new_name
cve.name_sort = get_name_sort(new_name)
@@ -1337,6 +1680,7 @@ def xhr_cve_commit(request):
priority = cve.priority,
)
vulnerability.save()
+ history_update.append(Update.ATTACH_INV % (vname))
cve2vul = CveToVulnerablility.objects.create(cve = cve,vulnerability = vulnerability)
cve2vul.save()
_log("SUBMIT-CREATE-VULNERABILITY:%s,%s,%s" % (cve.id,vulnerability.id,cve2vul.id))
@@ -1348,9 +1692,16 @@ def xhr_cve_commit(request):
except Exception as e:
_log("xhr_triage_commit:No such Vulnerability name found (%s,%s)" % (vname,e))
return HttpResponse(json.dumps({"error":"No such Vulnerability name found (%s)" % (vname)}), content_type = "application/json")
+ history_update.append(Update.ATTACH_INV % (vname))
cve2vul = CveToVulnerablility.objects.create(cve = cve,vulnerability = vulnerability)
cve2vul.save()
_log("SUBMIT-CREATE-VULNERABILITY:%s,%s,%s" % (cve.id,vulnerability.id,cve2vul.id))
+ if 'submit-delete-cve' == action:
+ _log("SUBMIT-DELETE-CVE(%s)" % cve.name)
+ #history_update.append(Update.ATTACH_INV % (vname))
+ cve.delete()
+ _log("SUBMIT-DELETED-CVE(%s)!" % cve.name)
+ new_name = 'url:/srtgui/cves'
return_data = {
"error": "ok",
@@ -1358,10 +1709,9 @@ def xhr_cve_commit(request):
}
username = UserSafe.user_name(request.user)
- if (history_comment != ''):
- history_comment = history_comment[:-2]
- history_comment += " edited"
- CveHistory.objects.create(cve_id=cve.id, comment=history_comment, date=datetime.now().strftime('%Y-%m-%d'), author=username)
+ if history_update:
+ update_comment = "%s%s" % (Update.UPDATE_STR % Update.SOURCE_USER,';'.join(history_update))
+ CveHistory.objects.create(cve_id=cve.id, comment=update_comment, date=datetime.now().strftime('%Y-%m-%d'), author=username)
_log("xhr_cve_commit:SUCCESS")
return HttpResponse(json.dumps( return_data ), content_type = "application/json")
@@ -1416,34 +1766,38 @@ def xhr_vulnerability_commit(request):
action = request.POST['action']
v_id = request.POST['vulnerability_id']
username = UserSafe.user_name(request.user)
- history_comment = ''
try:
+ history_update = []
if 'submit-quickedit' == action:
- note = request.POST['note']
- private_note = request.POST['private_note']
+ note = request.POST['note'].strip()
+ private_note = request.POST['private_note'].strip()
+ tags = request.POST['tags'].strip()
+ priority = int(request.POST['priority'])
+ status = int(request.POST['status'])
+ outcome = int(request.POST['outcome'])
v = Vulnerability.objects.get(id=v_id)
+ if (v.priority != priority):
+ history_update.append(Update.PRIORITY % (SRTool.priority_text(v.priority),SRTool.priority_text(priority)))
+ v.priority = priority
+ if (v.status != status):
+ history_update.append(Update.STATUS % (SRTool.status_text(v.status),SRTool.status_text(status)))
+ v.status = status
+ if (v.outcome != outcome):
+ history_update.append(Update.OUTCOME % (SRTool.status_text(v.outcome),SRTool.status_text(outcome)))
+ v.outcome = outcome
if (v.comments != note):
+ history_update.append(Update.NOTE)
v.comments = note
- history_comment += "Note, "
if (v.comments_private != private_note):
+ history_update.append(Update.PRIVATE_NOTE)
v.comments_private = private_note
- history_comment += "Private Note, "
- if (v.status != request.POST['status']):
- v.status = request.POST['status']
- history_comment += "Status, "
- if (v.outcome != request.POST['outcome']):
- v.outcome = request.POST['outcome']
- history_comment += "Outcome, "
- if (v.priority != request.POST['priority']):
- v.priority = request.POST['priority']
- history_comment += "Priority, "
- if (history_comment != ''):
- history_comment = history_comment[:-2]
- history_comment += " edited"
+ if (tags != v.tags):
+ history_update.append(Update.TAG)
+ v.tags = tags
v.save()
if 'submit-addproduct' == action:
products = request.POST['products']
- product_names = ''
+ investigation_names = []
vulnerability_obj = Vulnerability.objects.get(id=v_id)
for product_id in products.split(','):
product_obj = Product.objects.get(pk=product_id)
@@ -1460,72 +1814,70 @@ def xhr_vulnerability_commit(request):
)
vul2inv = VulnerabilityToInvestigation.objects.create(vulnerability=vulnerability_obj,investigation=investigation_obj)
vul2inv.save()
- product_names += "%s " % product_obj.long_name
- product_names = product_names[:-2]
- history_comment = product_names + " added to affected products"
+ investigation_names.append(iname)
+ history_update.append(Update.ATTACH_INV % ','.join(investigation_names))
if 'submit-trashinvestigation' == action:
inv_id = request.POST['record_id']
investigation_obj = Investigation.objects.get(pk=inv_id)
vul2inv = VulnerabilityToInvestigation.objects.filter(investigation=investigation_obj)
vul2inv.delete()
- history_comment = investigation_obj.name + " investigation(s) removed"
+ history_update.append(Update.DETACH_INV % (investigation_obj.name))
investigation_obj.delete()
if 'submit-newcomment' == action:
comment = request.POST['comment']
VulnerabilityComments.objects.create(vulnerability_id=v_id, comment=comment, date=datetime.today().strftime('%Y-%m-%d'), author=username)
- history_comment = "New comment submitted"
+ #NOTE: No History for this
if 'submit-trashcomment' == action:
record_id = request.POST['record_id']
comment = VulnerabilityComments.objects.get(id=record_id)
- history_comment = "Comment from " + comment.author + " deleted"
comment.delete()
+ #NOTE: No History for this
if 'submit-trashattachment' == action:
record_id = request.POST['record_id']
upload = VulnerabilityUploads.objects.get(id=record_id)
- history_comment = "Upload '" + upload.description + "' from " + upload.author + " deleted"
try:
os.remove(upload.path)
except OSError:
pass
+ history_update.append(Update.DETACH_DOC % (upload.path))
upload.delete()
if 'submit-addusernotify' == action:
users = request.POST['users']
- usernames = ''
+ usernames = []
for user_id in users.split(','):
- usernames += SrtUser.objects.get(pk=user_id).name + ', '
+ usernames.append(SrtUser.objects.get(pk=user_id).name)
VulnerabilityNotification.objects.get_or_create(vulnerability_id=v_id, user_id=user_id)
- usernames = usernames[:-2]
- history_comment = usernames + " added to notifications"
+ history_update.append(Update.ATTACH_USER_NOTIFY % ','.join(usernames))
if 'submit-trashusernotification' == action:
record_id = request.POST['record_id']
notification_record = VulnerabilityNotification.objects.get(id=record_id)
removed_user = SrtUser.objects.get(pk=notification_record.user_id).name
- history_comment = removed_user + " removed from notifications"
notification_record.delete()
+ history_update.append(Update.DETACH_USER_NOTIFY % removed_user)
if 'submit-adduseraccess' == action:
users = request.POST['users']
- usernames = ''
+ usernames = []
for user_id in users.split(','):
- usernames += SrtUser.objects.get(pk=user_id).name + ', '
+ usernames.append(SrtUser.objects.get(pk=user_id).name)
VulnerabilityAccess.objects.get_or_create(vulnerability_id=v_id, user_id=user_id)
- usernames = usernames[:-2]
- history_comment = usernames + " granted access"
+ history_update.append(Update.ATTACH_ACCESS % ','.join(usernames))
if 'submit-trashuseraccess' == action:
record_id = request.POST['record_id']
access_record = VulnerabilityAccess.objects.get(id=record_id)
- removed_user = username
- history_comment = removed_user + "'s access removed"
access_record.delete()
+ history_update.append(Update.DETACH_ACCESS % username)
if 'submit-notification' == action:
_submit_notification(request)
+ #NOTE: No History for this
if 'submit-trashvulnerability' == action:
record_id = request.POST['record_id']
vulnerability_obj = Vulnerability.objects.get(pk=record_id)
- history_comment = "Vulnerability '%s' is deleted" % vulnerability_obj.name
+# history_update.append(Update.DETACH_VUL % vulnerability_obj.name)
vulnerability_obj.delete()
- if (history_comment != ''):
- VulnerabilityHistory.objects.create(vulnerability_id=v_id, comment=history_comment, date=datetime.now().strftime('%Y-%m-%d'), author=username)
+ if history_update:
+ update_comment = "%s%s" % (Update.UPDATE_STR % Update.SOURCE_USER,';'.join(history_update))
+ VulnerabilityHistory.objects.create(vulnerability_id=v_id, comment=update_comment, date=datetime.now().strftime('%Y-%m-%d'), author=username)
return_data = {
"error": "ok",
}
@@ -1644,43 +1996,48 @@ def xhr_investigation_commit(request):
action = request.POST['action']
invst_id = request.POST['investigation_id']
username = UserSafe.user_name(request.user)
- history_comment = "Nothing happened."
try:
+ history_update = []
if 'submit-quickedit' == action:
- note = request.POST['note']
- private_note = request.POST['private_note']
+ priority = int(request.POST['priority'])
+ status = int(request.POST['status'])
+ outcome = int(request.POST['outcome'])
+ note = request.POST['note'].strip()
+ private_note = request.POST['private_note'].strip()
+ tags = request.POST['tags'].strip()
invst = Investigation.objects.get(id=invst_id)
+ if (invst.priority != priority):
+ history_update.append(Update.PRIORITY % (SRTool.priority_text(invst.priority),SRTool.priority_text(priority)))
+ invst.priority = priority
+ if (invst.status != request.POST['status']):
+ history_update.append(Update.STATUS % (SRTool.status_text(invst.status),SRTool.status_text(status)))
+ invst.status = request.POST['status']
+ if (invst.outcome != outcome):
+ history_update.append(Update.OUTCOME % (SRTool.status_text(invst.outcome),SRTool.status_text(outcome)))
+ invst.outcome = outcome
if (invst.comments != note):
invst.comments = note
- history_comment += "Note, "
+ history_update.append(Update.NOTE)
if (invst.comments_private != private_note):
invst.comments_private = private_note
- history_comment += "Private Note, "
- if (invst.status != request.POST['status']):
- invst.status = request.POST['status']
- history_comment += "Status, "
- if (invst.outcome != request.POST['outcome']):
- invst.outcome = request.POST['outcome']
- history_comment += "Outcome, "
- if (invst.priority != request.POST['priority']):
- invst.priority = request.POST['priority']
- history_comment += "Priority, "
- if (history_comment != ''):
- history_comment = history_comment[:-2]
- history_comment += " edited"
+ history_update.append(Update.PRIVATE_NOTE)
+ if (invst.tags != tags):
+ invst.tags = tags
+ history_update.append(Update.TAG)
invst.save()
if 'submit-attachdefectlist' == action:
defects = request.POST['defects']
product_id = Investigation.objects.get(id=invst_id).product_id
- defect_names = ""
+ defect_names = []
for defect_id in defects.split(','):
- defect_names += Defect.objects.get(pk=defect_id).name + ", "
+ defect_names.append(Defect.objects.get(pk=defect_id).name)
InvestigationToDefect.objects.get_or_create(investigation_id=invst_id, defect_id=defect_id)
- defect_names = defect_names[:-2]
- history_comment = defect_names + " added to defects"
+ history_update.append(Update.ATTACH_DEV % ','.join(defect_names))
if 'submit-attachdefect' == action:
query = request.POST['query'].upper()
product_id = Investigation.objects.get(id=invst_id).product_id
+ # Courtesy removal of URL (or other) prefix
+ query = re.sub(r".*/", "", query)
#check if defect already in SRTool data
try:
defect = Defect.objects.get(name=query)
@@ -1697,79 +2054,86 @@ def xhr_investigation_commit(request):
defect = Defect.objects.get(name=query)
except subprocess.CalledProcessError as e:
_log("ERROR:submit-attachdefect:%d:STDOUT='%s':" % (e.returncode, e.output))
- return HttpResponse(json.dumps({"error":str(e) + "\n"}), content_type = "application/json")
+ error_message = "Could not find defect with the name '%s'\n\n(detail:%s)\n" % (query,str(e))
+ return HttpResponse(json.dumps({"error":error_message}), content_type = "application/json")
if defect:
InvestigationToDefect.objects.get_or_create(investigation_id=invst_id, defect_id=defect.id, product_id=product_id)
- history_comment = "Attached " + defect.name
+ # Enforce minimum status on open defects
+ if Defect.DEFECT_UNRESOLVED == defect.resolution:
+ invst = Investigation.objects.get(id=invst_id)
+ if defect.srt_status < invst.status:
+ defect.srt_status = invst.status
+ defect.save()
+ history_update.append(Update.ATTACH_DEV % defect.name)
if 'submit-createdefect' == action:
investigation = Investigation.objects.get(id=invst_id)
defect_reason = request.POST['defect_reason']
components = request.POST['components']
priority = request.POST['priority']
- defect_name = _create_defect(investigation,defect_reason,components)
- history_comment = "New defect '%s' created" % defect_name
+ affected_components = request.POST['affected_components'].strip()
+ defect_name,created = _create_defect(investigation,'',defect_reason,components,affected_components,username)
+ history_update.append(Update.ATTACH_DEV % defect_name)
if 'submit-detachdefect' == action:
defect_name = request.POST['defect']
product_id = Investigation.objects.get(id=invst_id).product_id
defect_id = Defect.objects.get(name=defect_name).id
InvestigationToDefect.objects.get(investigation_id=invst_id, defect_id=defect_id).delete()
- history_comment = defect_name + " detached from investigation"
+ history_update.append(Update.DETACH_DEV % defect_name)
if 'submit-newcomment' == action:
comment = request.POST['comment']
InvestigationComments.objects.create(investigation_id=invst_id, comment=comment, date=datetime.today().strftime('%Y-%m-%d'), author=username)
- history_comment = "New comment submitted"
+ #NOTE: No History for this
if 'submit-trashcomment' == action:
record_id = request.POST['record_id']
comment = InvestigationComments.objects.get(id=record_id)
- history_comment = "Comment from " + comment.author + " deleted"
comment.delete()
+ #NOTE: No History for this
if 'submit-trashattachment' == action:
record_id = request.POST['record_id']
upload = InvestigationUploads.objects.get(id=record_id)
- history_comment = "Upload '" + upload.description + "' from " + upload.author + " deleted"
try:
os.remove(upload.path)
except OSError:
pass
+ history_update.append(Update.DETACH_DOC % (upload.path))
upload.delete()
if 'submit-addusernotify' == action:
users = request.POST['users']
- usernames = ""
+ usernames = []
for user_id in users.split(','):
- usernames += SrtUser.objects.get(pk=user_id).name + ", "
+ usernames.append(SrtUser.objects.get(pk=user_id).name)
InvestigationNotification.objects.get_or_create(investigation_id=invst_id, user_id=user_id)
- usernames = usernames[:-2]
- history_comment = usernames + " added to notifications"
+ history_update.append(Update.ATTACH_USER_NOTIFY % ','.join(usernames))
if 'submit-trashusernotification' == action:
record_id = request.POST['record_id']
notification_record = InvestigationNotification.objects.get(id=record_id)
removed_user = SrtUser.objects.get(pk=notification_record.user_id).name
- history_comment = removed_user + " removed from notifications"
+ history_update.append(Update.DETACH_USER_NOTIFY % removed_user)
notification_record.delete()
if 'submit-adduseraccess' == action:
users = request.POST['users']
- usernames = ""
+ usernames = []
for user_id in users.split(','):
- usernames += SrtUser.objects.get(pk=user_id).name + ", "
+ usernames.append(SrtUser.objects.get(pk=user_id).name)
InvestigationAccess.objects.get_or_create(investigation_id=invst_id, user_id=user_id)
- history_comment = usernames + " granted access"
+ history_update.append(Update.ATTACH_ACCESS % ','.join(usernames))
if 'submit-trashuseraccess' == action:
record_id = request.POST['record_id']
access_record = InvestigationAccess.objects.get(id=record_id)
- removed_user = username
- history_comment = removed_user + "'s access removed"
+ history_update.append(Update.DETACH_ACCESS % username)
access_record.delete()
if 'submit-notification' == action:
_submit_notification(request)
- history_comment = ''
+ #NOTE: No History for this
if 'submit-trashinvestigation' == action:
record_id = request.POST['record_id']
investigation_obj = Investigation.objects.get(pk=record_id)
- history_comment = "Investigation '%s' is deleted" % investigation_obj.name
+# history_update.append(Update.DETACH_INV % investigation_obj.name)
investigation_obj.delete()
- if history_comment:
- InvestigationHistory.objects.create(investigation_id=invst_id, comment=history_comment, date=datetime.now().strftime('%Y-%m-%d'), author=username)
+ if history_update:
+ update_comment = "%s%s" % (Update.UPDATE_STR % Update.SOURCE_USER,';'.join(history_update))
+ InvestigationHistory.objects.create(investigation_id=invst_id, comment=update_comment, date=datetime.now().strftime('%Y-%m-%d'), author=username)
return_data = {
"error": "ok",
}
@@ -1779,6 +2143,146 @@ def xhr_investigation_commit(request):
_log("xhr_investigation_commit:no(%s)" % e)
return HttpResponse(json.dumps({"error":str(e) + "\n"}), content_type = "application/json")
+def xhr_publish(request):
+ _log("xhr_publish(%s)" % request.POST)
+
+ def remove_mark(mark,line):
+ pos1 = line.find(mark)
+ if -1 == pos1:
+ return line
+ pos2 = line.find(')',pos1)
+ if -1 == pos2:
+ return line.replace(mark,'')
+ line = line[0:pos1] + line[pos2+1:]
+ return line
+
+ if not 'action' in request.POST:
+ return HttpResponse(json.dumps({"error":"missing action\n"}), content_type = "application/json")
+ try:
+ username = UserSafe.user_name(request.user)
+ action = request.POST['action']
+
+ if 'export-snapshot' == action:
+ snap_date_base = request.POST['snap_date_base']
+ snap_date_top = request.POST['snap_date_top']
+ snap_date_start = request.POST['snap_date_start']
+ snap_date_stop = request.POST['snap_date_stop']
+ _log("xhr_publish:export-snapshot:%s,%s,%s,%s" % (snap_date_base,snap_date_top,snap_date_start,snap_date_stop))
+
+ SrtSetting.set_setting('publish_snap_date_base',snap_date_base)
+ SrtSetting.set_setting('publish_snap_date_top',snap_date_top)
+ SrtSetting.set_setting('publish_snap_date_start',snap_date_start)
+ SrtSetting.set_setting('publish_snap_date_stop',snap_date_stop)
+
+ backup_returncode,backup_stdout,backup_result = execute_process('bin/common/srtool_backup.py','--list-backups-db')
+ base_dir = ''
+ top_dir = ''
+ for i,line in enumerate(backup_stdout.decode("utf-8").splitlines()):
+ # Week|backup_2019_19|2019-05-18|12:51:51|Saturday, May 18 2019
+ backup_mode,backup_dir,backup_date,backup_time,backup_day = line.split('|')
+ if (not base_dir) and (snap_date_base == backup_date):
+ base_dir = 'backups/%s' % backup_dir
+ if (not top_dir) and (snap_date_top == backup_date) and ('Now' != backup_mode):
+ top_dir = 'backups/%s' % backup_dir
+
+ _log('Publish:./bin/wr/srtool_publish.py --srt2update ' + base_dir)
+ report_returncode,report_stdout,report_error = execute_process('./bin/wr/srtool_publish.py','--srt2update',base_dir)
+ if 0 != report_returncode:
+ return_data = {"error": "Error: base dir prep:%s:%s" % (report_error,report_stdout),}
+ return HttpResponse(json.dumps( return_data ), content_type = "application/json")
+ _log('Publish:./bin/wr/srtool_publish.py --srt2update ' + top_dir)
+ report_returncode,report_stdout,report_error = execute_process('./bin/wr/srtool_publish.py','--srt2update',top_dir)
+ if 0 != report_returncode:
+ return_data = {"error": "Error: top dir prep:%s:%s" % (report_error,report_stdout),}
+ return HttpResponse(json.dumps( return_data ), content_type = "application/json")
+ _log('Publish:./bin/wr/srtool_publish.py --validate-update-svns --previous '+base_dir+' --current '+top_dir+' --start '+snap_date_start+' --stop '+snap_date_stop)
+ report_returncode,report_stdout,report_error = execute_process('./bin/wr/srtool_publish.py',
+ '--validate-update-svns','--previous',base_dir,'--current',top_dir,
+ '--start',snap_date_start,'--stop',snap_date_stop)
+ if 0 != report_returncode:
+ return_data = {"error": "Error: publish report:%s:%s" % (report_error,report_stdout),}
+ return HttpResponse(json.dumps( return_data ), content_type = "application/json")
+
+ publish_snap_last_calc = 'Base:%s, Top:%s, Start:%s, Stop:%s, On:%s' % (
+ snap_date_base,snap_date_top,snap_date_start,snap_date_stop,
+ datetime.today().strftime("%Y-%m-%d %H:%M:%S")
+ )
+ SrtSetting.set_setting('publish_snap_last_calc',publish_snap_last_calc)
+
+ _log('Publish:Done!')
+ elif 'submit-trashreport' == action:
+ report_name = request.POST['report_name']
+ os.remove('data/wr/%s' % report_name)
+ else:
+ srtool_today_time = datetime.today()
+ srtool_today = datetime.today().strftime("%Y-%m-%d")
+ reason_map = {}
+ if 'defects' in request.POST:
+ cve_table = []
+ for defect_name in request.POST['defects'].split(','):
+ try:
+ defect = Defect.objects.get(name = defect_name)
+ cve_names = defect.get_cve_names
+ for cve_name in cve_names.split(','):
+ cve_table.append(cve_name)
+ reason_map[cve_name] = defect_name
+ except Exception as e:
+ _log("ERROR:xhr_publish:defectlist:%s" % e)
+ cve_list = ','.join(cve_table)
+ else:
+ cve_list = request.POST['cves']
+ for cve_name in cve_list.split(','):
+ reason_map[cve_name] = ''
+ _log("xhr_publish_defect2cves3:%s:%d" % (cve_list,len(cve_list)))
+
+ date_start = datetime.strptime(SrtSetting.get_setting('publish_date_start','02/15/2019'), '%m/%d/%Y')
+ date_stop = datetime.strptime(SrtSetting.get_setting('publish_date_stop','03/15/2019'), '%m/%d/%Y')
+ # set date_stop to 11:59pm for end of 'incusive' day
+ date_stop = date_stop.replace(hour=11, minute=59)
+ if 'mark-new' == action:
+ for cve_name in cve_list.split(','):
+ _log("xhr_publish_defect2cvesNEW:%s" % (cve_name))
+ cve = Cve.objects.get(name=cve_name)
+ publish_object,created = PublishSet.objects.get_or_create(cve=cve)
+ publish_object.state = PublishSet.PUBLISH_SET_NEW_USER
+ publish_object.reason = remove_mark('Mark_New',publish_object.reason)
+ publish_object.reason = remove_mark('Mark_Updated',publish_object.reason)
+ publish_object.reason += ' Mark_New(%s)' % reason_map[cve_name]
+ publish_object.reason = publish_object.reason.replace(' ',' ').strip()
+ publish_object.save()
+ publishMarkNew(cve_list,reason_map,date_start,date_stop)
+ if 'mark-modified' == action:
+ for cve_name in cve_list.split(','):
+ _log("xhr_publish_defect2cvesMOD:%s" % (cve_name))
+ cve = Cve.objects.get(name=cve_name)
+ publish_object,created = PublishSet.objects.get_or_create(cve=cve)
+ publish_object.state = PublishSet.PUBLISH_SET_MODIFIED_USER
+ publish_object.reason = remove_mark('Mark_New',publish_object.reason)
+ publish_object.reason = remove_mark('Mark_Updated',publish_object.reason)
+ publish_object.reason += ' Mark_Updated(%s)' % reason_map[cve_name]
+ publish_object.reason = publish_object.reason.replace(' ',' ').strip()
+ publish_object.save()
+ publishMarkModified(cve_list,reason_map,date_start,date_stop)
+ if 'unmark' == action:
+ for cve_name in cve_list.split(','):
+ cve = Cve.objects.get(name=cve_name)
+ publish_object,created = PublishSet.objects.get_or_create(cve=cve)
+ publish_object.state = PublishSet.PUBLISH_SET_NONE
+ publish_object.reason = remove_mark('Mark_New',publish_object.reason)
+ publish_object.reason = remove_mark('Mark_Updated',publish_object.reason)
+ publish_object.reason = publish_object.reason.replace(' ',' ').strip()
+ publish_object.save()
+ publishMarkNone(cve_list,date_start,date_stop)
+
+ return_data = {
+ "error": "ok",
+ }
+
+ return HttpResponse(json.dumps( return_data ), content_type = "application/json")
+ except Exception as e:
+ _log("xhr_publish:no(%s)(%s)" % (e,traceback.print_stack()))
+ return HttpResponse(json.dumps({"error":str(e) + "\n"}), content_type = "application/json")
+
def cve_alternates(request, cve_pk):
try:
@@ -1795,6 +2299,15 @@ def cve_alternates(request, cve_pk):
cve_source_object,created = CveSource.objects.get_or_create(cve=cve_object,datasource=ds)
_log("Alternate CVE source %s for %s (created=%s)" % (ds.key,cve_object.name,created))
+ # Force update the CVE summary data from sources
+ result_returncode,result_stdout,result_stderr = execute_process(
+ './bin/nist/srtool_nist.py',
+ '--update-cve-list',
+ cve_object.name,
+ '--force'
+ )
+ _log("CVE_ALT_REFRESH=%s|%s|%s" % (result_returncode,result_stdout,result_stderr))
+
return redirect(cve, cve_pk)