aboutsummaryrefslogtreecommitdiffstats
path: root/lib/orm/models.py
diff options
context:
space:
mode:
Diffstat (limited to 'lib/orm/models.py')
-rw-r--r--lib/orm/models.py677
1 files changed, 562 insertions, 115 deletions
diff --git a/lib/orm/models.py b/lib/orm/models.py
index 0f6cfb17..0dd73ba4 100644
--- a/lib/orm/models.py
+++ b/lib/orm/models.py
@@ -114,6 +114,266 @@ def GitURLField(**kwargs):
# Core Classes
+# Helper class to common mappings
+class SRTool():
+
+ # Global date format
+ DATE_FORMAT = '%Y-%m-%d'
+ DATETIME_FORMAT = '%Y-%m-%d %H:%M:%S'
+
+ # SRTool Priority
+ UNDEFINED = 0
+ LOW = 1
+ MEDIUM = 2
+ HIGH = 3
+ CRITICAL = 4
+ PRIORITY_ERROR = 99
+ SRT_PRIORITY = (
+ (UNDEFINED, 'Undefined'),
+ (LOW, 'Low'),
+ (MEDIUM, 'Medium'),
+ (HIGH, 'High'),
+ (CRITICAL, 'Critical'),
+ )
+ @staticmethod
+ def priority_text(index):
+ if (0 > index) or (index >= len(SRTool.SRT_PRIORITY)):
+ return 'PRIORITY_ERROR'
+ return SRTool.SRT_PRIORITY[index][1]
+ @staticmethod
+ def priority_index(value):
+ for item in SRTool.SRT_PRIORITY:
+ if value == item[1]:
+ return item[0]
+ return SRTool.PRIORITY_ERROR
+
+ # SRTool Severity (same integer values as prority)
+ SRT_SEVERITY = (
+ (UNDEFINED, 'UNDEFINED'),
+ (LOW, 'LOW'),
+ (MEDIUM, 'MEDIUM'),
+ (HIGH, 'HIGH'),
+ (CRITICAL, 'CRITICAL'),
+ )
+ @staticmethod
+ def severity_text(index):
+ if (0 > index) or (index >= len(SRTool.SRT_SEVERITY)):
+ return 'SEVERITY_ERROR'
+ return SRTool.SRT_SEVERITY[index][1]
+ @staticmethod
+ def severity_index(value):
+ for item in SRTool.SRT_SEVERITY:
+ if value == item[1]:
+ return item[0]
+ return SRTool.PRIORITY_ERROR
+
+ # SRTool Status
+ HISTORICAL = 0
+ NEW = 1
+ NEW_RESERVED = 2
+ INVESTIGATE = 3
+ VULNERABLE = 4
+ NOT_VULNERABLE = 5
+ NEW_INACTIVE = 6
+ INVESTIGATE_INACTIVE = 7
+ VULNERABLE_INACTIVE = 8
+ NOT_VULNERABLE_INACTIVE = 9
+ STATUS_ERROR = 99
+ SRT_STATUS = (
+ (HISTORICAL, 'Historical'),
+ (NEW, 'New'),
+ (NEW_RESERVED, 'New-Reserved'),
+ (INVESTIGATE, 'Investigate'),
+ (VULNERABLE, 'Vulnerable'),
+ (NOT_VULNERABLE, 'Not Vulnerable'),
+ (NEW_INACTIVE, '(New)'),
+ (INVESTIGATE_INACTIVE, '(Investigate)'),
+ (VULNERABLE_INACTIVE, '(Vulnerable)'),
+ (NOT_VULNERABLE_INACTIVE, '(Not Vulnerable)'),
+ )
+ @staticmethod
+ def status_text(index):
+ if (0 > index) or (index >= len(SRTool.SRT_STATUS)):
+ return 'STATUS_ERROR'
+ return SRTool.SRT_STATUS[index][1]
+ @staticmethod
+ def status_index(value):
+ for item in SRTool.SRT_STATUS:
+ if value == item[1]:
+ return item[0]
+ return SRTool.STATUS_ERROR
+ @staticmethod
+ def status_to_inactive(value):
+ if SRTool.NEW == value:
+ return SRTool.NEW_INACTIVE
+ elif SRTool.INVESTIGATE == value:
+ return SRTool.INVESTIGATE_INACTIVE
+ elif SRTool.VULNERABLE == value:
+ return SRTool.VULNERABLE_INACTIVE
+ elif SRTool.NOT_VULNERABLE == value:
+ return SRTool.NOT_VULNERABLE_INACTIVE
+ else:
+ return value
+ @staticmethod
+ def status_to_active(value):
+ if SRTool.NEW_INACTIVE == value:
+ return SRTool.NEW
+ elif SRTool.INVESTIGATE_INACTIVE == value:
+ return SRTool.INVESTIGATE
+ elif SRTool.VULNERABLE_INACTIVE == value:
+ return SRTool.VULNERABLE
+ elif SRTool.NOT_VULNERABLE_INACTIVE == value:
+ return SRTool.NOT_VULNERABLE
+ else:
+ return value
+
+ OPEN = 0
+ CLOSED = 1
+ FIXED = 2
+ NOT_FIX = 3
+ OUTCOME_ERROR = 4
+ SRT_OUTCOME = (
+ (OPEN, 'Open'),
+ (CLOSED, 'Closed (Not Vulnerable)'),
+ (FIXED, 'Closed (Fixed)'),
+ (NOT_FIX, "Closed (Won't Fix)"),
+ )
+ @staticmethod
+ def outcome_text(index):
+ if (0 > index) or (index >= len(SRTool.SRT_OUTCOME)):
+ return "OUTCOME_ERROR"
+ return SRTool.SRT_OUTCOME[index][1]
+ @staticmethod
+ def outcome_index(value):
+ for item in SRTool.SRT_OUTCOME:
+ if value == item[1]:
+ return item[0]
+ return SRTool.OUTCOME_ERROR
+
+ # Publish state
+ PUBLISH_UNPUBLISHED = 0
+ PUBLISH_NOPUBLISH = 1
+ PUBLISH_PUBLISHED = 2
+ PUBLISH_REQUEST = 3
+ PUBLISH_UPDATE = 4
+ PUBLISH_SUBMITTED = 5
+ PUBLISH_ERROR = 99
+ SRT_PUBLISH_STATE = (
+ (PUBLISH_UNPUBLISHED, 'Unpublished'),
+ (PUBLISH_NOPUBLISH, 'Not to be Published'),
+ (PUBLISH_PUBLISHED, 'Published'),
+ (PUBLISH_REQUEST, 'Publish Request (New)'),
+ (PUBLISH_UPDATE, 'Publish Request (Update)'),
+ (PUBLISH_SUBMITTED, 'Publish Submitted'),
+ )
+ @staticmethod
+ def publish_text(index):
+ if (0 > index) or (index >= len(SRTool.SRT_PUBLISH_STATE)):
+ return SRTool.SRT_PUBLISH_STATE[SRTool.PUBLISH_ERROR][1]
+ return 'PUBLISH_ERROR'
+ @staticmethod
+ def publish_index(value):
+ for item in SRTool.SRT_PUBLISH_STATE:
+ if value == item[1]:
+ return item[0]
+ return SRTool.PUBLISH_ERROR
+
+ # Normalize displayed dates
+ @staticmethod
+ def date_ymd_text(value):
+ if isinstance(value,datetime):
+ return(value.strftime("%Y-%m-%d"))
+ return(value)
+
+ # Extract dictionary tag values
+ @staticmethod
+ def get_dict_tag(tag,dict_str,default=None):
+ dict = json.loads(dict_str)
+ if tag in dict:
+ return dict[tag]
+ return default
+
+
+# Helper class to format and track updates
+# Enforce strict formatting and content to enable reporting, change filtering, pretty printing
+class Update():
+ # General history prefix format (type,source,semicolon-joined changes):
+ # UPDATE(User):Priority(%s,%s);Tag();Status(%s,%s) {helpful text}
+ # CREATE(Defect): {Created from defect ABCD-1234}
+ # Update report check strings: 'UPDATE(','Priority(','Status('
+
+ # General update label
+ UPDATE_STR = "UPDATE(%s):"
+ CREATE_STR = "CREATE(%s):"
+ UPDATE_PREFIX_STR = "UPDATE("
+ CREATE_PREFIX_STR = "CREATE("
+
+ # Update sources
+ SOURCE_USER = "User"
+ SOURCE_TRIAGE = "Triage"
+ SOURCE_CVE = "CVE"
+ SOURCE_DEFECT = "Defect"
+
+ # Update labels (no string overlaps allowed)
+ NEW_NAME = "New_Name(%s,%s)"
+ PRIORITY = "Priority(%s,%s)"
+ STATUS = "Status(%s,%s)"
+ SEVERITY_V3 = "Severity_V3(%s,%s)"
+ SEVERITY_V2 = "Severity_V2(%s,%s)"
+ OUTCOME = "Outcome(%s,%s)"
+ RELEASE = "Release(%s,%s)"
+ DESCRIPTION = "Description()"
+ LASTMODIFIEDDATE = "LastModifiedDate(%s,%s)"
+ NOTE = "User_Note()"
+ PRIVATE_NOTE = "Private_Note()"
+ TAG = "Tag()"
+ PUBLISH_STATE = "Publish_State(%s,%s)"
+ PUBLISH_DATE = "Publish_Date(%s,%s)"
+ AFFECTED_COMPONENT = "Affected_Component(%s,%s)"
+ ACKNOWLEDGE_DATE = "AcknowledgeDate(%s,%s)"
+ ATTACH_CVE = "Attach_CVE(%s)"
+ DETACH_CVE = "Detach_CVE(%s)"
+ ATTACH_VUL = "Attach_Vulnerability(%s)"
+ DETACH_VUL = "Detach_Vulnerability(%s)"
+ ATTACH_INV = "Attach_Investigration(%s)"
+ DETACH_INV = "Detach_Investigration(%s)"
+ ATTACH_DEV = "Attach_Defect(%s)"
+ DETACH_DEV = "Detach_Defect(%s)"
+ ATTACH_DOC = "Attach_Document(%s)"
+ DETACH_DOC = "Detach_Document(%s)"
+ ATTACH_USER_NOTIFY = "Attach_User_Notify(%s)"
+ DETACH_USER_NOTIFY = "Detach_User_Notify(%s)"
+ ATTACH_ACCESS = "Attach_Access(%s)"
+ DETACH_ACCESS = "Detach_Access(%s)"
+ ATTACH_PRODUCT = "Attach_Product(%s)"
+ DETACH_PRODUCT = "Detach_Product(%s)"
+ MARK_NEW = "Mark_New(%s)"
+ MARK_UPDATED = "Mark_Updated(%s)"
+ MARK_PREFIX = "Mark_"
+ MARK_NEW_PREFIX = "Mark_New"
+ MARK_UPDATED_PREFIX = "Mark_Updated"
+ MARK_UNMARK = "Mark_Unmark()"
+
+ # Update Report list
+ UPDATE_CHECK_LIST = (
+ PRIORITY,
+ STATUS,
+ SEVERITY_V3,
+ SEVERITY_V2,
+ RELEASE,
+ MARK_NEW,
+ MARK_UPDATED,
+ )
+
+ #Any matching string for the period indicates reportable change
+ @staticmethod
+ def get_check_list():
+ check_list = []
+ for check in UPDATE_CHECK_LIST:
+ simple_check = re.sub(r'(.*', '(', check)
+ check_list.append(simple_check)
+ return(check_list)
+
class SrtSetting(models.Model):
name = models.CharField(max_length=63)
helptext = models.TextField()
@@ -128,6 +388,11 @@ class SrtSetting(models.Model):
return(SrtSetting.objects.get(name=key).value)
except:
return(default)
+ @staticmethod
+ def set_setting(key,value):
+ obj,created = SrtSetting.objects.get_or_create(name=key)
+ obj.value = value
+ obj.save()
class HelpText(models.Model):
@@ -163,6 +428,10 @@ class DataSource(models.Model):
DATE_FORMAT = '%Y-%m-%d'
DATETIME_FORMAT = '%Y-%m-%d %H:%M:%S'
+ # Metadata
+ LOOKUP_MISSING = 'LOOKUP-MISSING'
+ PREVIEW_SOURCE = 'PREVIEW-SOURCE'
+
key = models.CharField(max_length=20)
data = models.CharField(max_length=20)
source = models.CharField(max_length=20)
@@ -194,20 +463,22 @@ class CweTable(models.Model):
class Cve(models.Model):
search_allowed_fields = ['name', 'description', 'publishedDate',
- 'lastModifiedDate', 'comments', 'comments_private']
+ 'lastModifiedDate', 'comments', 'comments_private', 'tags', 'packages']
# SRTool Priority
UNDEFINED = 0
- MINOR = 1
- LOW = 2
- MEDIUM = 3
- HIGH = 4
+ LOW = 1
+ MEDIUM = 2
+ HIGH = 3
+ CRITICAL = 4
+ PRIORITY_ERROR = 5
PRIORITY = (
(UNDEFINED, 'Undefined'),
- (MINOR, 'Minor'),
(LOW, 'Low'),
(MEDIUM, 'Medium'),
(HIGH, 'High'),
+ (CRITICAL, 'Critical'),
+ (PRIORITY_ERROR, 'PRIORITY_ERROR'),
)
# WR Status
@@ -256,6 +527,7 @@ class Cve(models.Model):
status = models.IntegerField(choices=STATUS, default=NEW)
comments = models.TextField(blank=True)
comments_private = models.TextField(blank=True)
+ tags = models.TextField(blank=True, default='', null=True)
cve_data_type = models.CharField(max_length=100, blank=True)
cve_data_format = models.CharField(max_length=50, blank=True)
@@ -264,6 +536,7 @@ class Cve(models.Model):
public = models.BooleanField(default=True)
publish_state = models.IntegerField(choices=PUBLISH_STATE, default=PUBLISH_UNPUBLISHED)
publish_date = models.CharField(max_length=50, blank=True)
+ acknowledge_date = models.DateTimeField(null=True)
description = models.TextField(blank=True)
publishedDate = models.CharField(max_length=50, blank=True)
@@ -281,25 +554,41 @@ class Cve(models.Model):
packages = models.TextField(blank=True)
score_date = models.DateField(null=True, blank=True)
- srt_updated = models.DateTimeField(auto_now=True)
+ srt_updated = models.DateTimeField(auto_now=True, null=True)
+ srt_created = models.DateTimeField(auto_now_add=True, null=True)
@property
def get_priority_text(self):
- return Cve.PRIORITY[int(self.priority)][1]
+ return SRTool.priority_text(self.priority)
+ @property
+ def get_status_text(self):
+ return SRTool.status_text(self.status)
@property
def get_publish_text(self):
return Cve.PUBLISH_STATE[int(self.publish_state)][1]
@property
- def get_status_text(self):
- return Cve.STATUS[int(self.status)][1]
- @property
def is_local(self):
try:
CveLocal.objects.get(name=self.name)
return True
except:
return False
-
+ @property
+ def get_publishset_state(self):
+ try:
+ obj = PublishSet.objects.get(cve=self)
+ return obj.state_text
+ except:
+ return PublishSet.PUBLISH_SET_STATE[PublishSet.PUBLISH_SET_NONE][1]
+ @property
+ def get_public_comments(self):
+ the_comments = self.comments.strip()
+ the_packages = self.packages.strip()
+ if not the_comments or not the_packages:
+ return '%s%s' % (the_comments,the_packages)
+ if the_comments == the_packages:
+ return the_comments
+ return '%s' % (the_comments)
class CveDetail():
# CPE item list
@@ -317,6 +606,7 @@ class CveDetail():
description = ''
publishedDate = ''
+ acknowledge_date = ''
lastModifiedDate = ''
url_title = ''
url = ''
@@ -431,11 +721,12 @@ class CveLocal(models.Model):
# Map of all sources for the given CVE
class CveSource(models.Model):
- cve = models.ForeignKey(Cve,related_name="cve_parent",on_delete=models.CASCADE,)
+ cve = models.ForeignKey(Cve,related_name="cve_parent",blank=True, null=True,on_delete=models.CASCADE,)
datasource = models.ForeignKey(DataSource,related_name="cve_datasource", blank=True, null=True,on_delete=models.CASCADE,)
class CveHistory(models.Model):
- cve = models.ForeignKey(Cve,related_name="cve_history",on_delete=models.CASCADE,)
+ search_allowed_fields = ['cve__name', 'comment', 'date', 'author']
+ cve = models.ForeignKey(Cve,related_name="cve_history",default=None, null=True, on_delete=models.CASCADE,)
comment = models.TextField(blank=True)
date = models.DateField(null=True, blank=True)
author = models.TextField(blank=True)
@@ -485,12 +776,12 @@ class Package(models.Model):
@staticmethod
def update_computed_counts(package_name=None):
# A 'None' indicates all packages
- _log("update_computed_counts0:%s" % package_name)
+# _log("update_computed_counts0:%s" % package_name)
if package_name:
package_list = Package.objects.filter(name=package_name)
else:
package_list = Package.objects.all()
- _log("update_computed_counts:p:%s" % len(package_list))
+# _log("update_computed_counts:p:%s" % len(package_list))
for package in package_list:
try:
state = "p"
@@ -498,7 +789,7 @@ class Package(models.Model):
package.vulnerability_count = 0
package.investigation_count = 0
package.defect_count = 0
- _log("update_computed_counts2:c:%s" % len(package.package2cve.all()))
+# _log("update_computed_counts2:c:%s" % len(package.package2cve.all()))
for pc in package.package2cve.all():
cve = pc.cve
package.cve_count += 1
@@ -559,7 +850,7 @@ class CveToCwe(models.Model):
class CveReference(models.Model):
cve = models.ForeignKey(Cve,related_name="references",on_delete=models.CASCADE,)
- hyperlink = models.CharField(max_length=100)
+ hyperlink = models.CharField(max_length=100, null=True)
resource = models.CharField(max_length=100, null=True)
type = models.CharField(max_length=100, null=True)
source = models.CharField(max_length=100, null=True)
@@ -586,26 +877,20 @@ class Product(models.Model):
def long_name(self):
long_name = '%s %s %s' % (self.name,self.version,self.profile)
return long_name.strip()
- def get_defect_tag(self,tag):
- dict = json.loads(self.defect_tags)
- try:
- return dict[tag]
- except:
- _log("ERROR:get_defect_tag:%s[%s]" % (dict,tag))
- return ''
- def get_product_tag(self,tag):
- dict = json.loads(self.product_tags)
- try:
- return dict[tag]
- except:
- _log("ERROR:get_product_tags:%s[%s]" % (dict,tag))
- return ''
+ def get_defect_tag(self,tag,default=None):
+ return SRTool.get_dict_tag(tag,self.defect_tags,default)
+ def get_product_tag(self,tag,default=None):
+ return SRTool.get_dict_tag(tag,self.product_tags,default)
+ def get_defect_str(self):
+ return self.defect_tags.replace('"','')
+ def get_product_str(self):
+ return self.product_tags.replace('"','')
# VULNERABILITY
# Company-level Vulnerablility Record
class Vulnerability(models.Model):
- search_allowed_fields = ['name', 'comments', 'comments_private']
+ search_allowed_fields = ['name', 'comments', 'comments_private', 'tags']
HISTORICAL = 0
NEW = 1
@@ -632,18 +917,21 @@ class Vulnerability(models.Model):
(FIXED, 'Closed (Fixed)'),
(NOT_FIX, "Closed (Won't Fix)"),
)
- # SRTool Severity, matched with Cve/Defect Priority with placeholder for 'minor'
+
+ # SRTool Priority
UNDEFINED = 0
- MINOR = 1
- LOW = 2
- MEDIUM = 3
- HIGH = 4
+ LOW = 1
+ MEDIUM = 2
+ HIGH = 3
+ CRITICAL = 4
+ PRIORITY_ERROR = 5
PRIORITY = (
(UNDEFINED, 'Undefined'),
- (MINOR, 'Minor'),
(LOW, 'Low'),
(MEDIUM, 'Medium'),
(HIGH, 'High'),
+ (CRITICAL, 'Critical'),
+ (PRIORITY_ERROR, 'PRIORITY_ERROR'),
)
name = models.CharField(max_length=50)
@@ -653,21 +941,26 @@ class Vulnerability(models.Model):
public = models.BooleanField(default=True)
comments = models.TextField(blank=True, default='')
comments_private = models.TextField(blank=True, default='')
+ tags = models.TextField(blank=True, default='')
status = models.IntegerField(choices=STATUS, default=INVESTIGATE)
outcome = models.IntegerField(choices=OUTCOME, default=OPEN)
priority = models.IntegerField(choices=PRIORITY, default=LOW)
+ srt_updated = models.DateTimeField(auto_now=True, null=True)
+ srt_created = models.DateTimeField(auto_now_add=True, null=True)
+
+ @property
+ def get_priority_text(self):
+ return SRTool.priority_text(self.priority)
@property
def get_status_text(self):
- return Vulnerability.STATUS[int(self.status)][1]
+ return SRTool.status_text(self.status)
@property
def get_outcome_text(self):
+ return SRTool.outcome_text(self.outcome)
return Vulnerability.OUTCOME[int(self.outcome)][1]
@property
- def get_priority_text(self):
- return Vulnerability.PRIORITY[int(self.priority)][1]
- @property
def get_long_name(self):
if self.cve_primary_name:
return "%s (%s)" % (self.name,self.cve_primary_name)
@@ -698,6 +991,9 @@ class Vulnerability(models.Model):
print("Error in new_vulnerability_name")
raise
return "VUL-%05d" % index
+ @property
+ def investigation_list(self):
+ return VulnerabilityToInvestigation.objects.filter(vulnerability_id=self.id).order_by('investigation__product__order')
class VulnerabilityComments(models.Model):
vulnerability = models.ForeignKey(Vulnerability,related_name="vulnerability_comments",on_delete=models.CASCADE,)
@@ -706,6 +1002,7 @@ class VulnerabilityComments(models.Model):
author = models.TextField(blank=True)
class VulnerabilityHistory(models.Model):
+ search_allowed_fields = ['vulnerability__name', 'comment', 'date', 'author']
vulnerability = models.ForeignKey(Vulnerability,related_name="vulnerability_history",on_delete=models.CASCADE,)
comment = models.TextField(blank=True)
date = models.DateField(null=True, blank=True)
@@ -733,58 +1030,62 @@ class Defect(models.Model):
#Issue Type,Key,Summary,Priority,Status,Resolution,Publish To OLS,Fix Version
#Bug,LIN10-2031,Security Advisory - libvorbis - CVE-2017-14633,P3,Closed,Fixed,Reviewed - Publish,10.17.41.3
- NONE = 0
- MINOR = 1
- LOW = 2
- MEDIUM = 3
- HIGH = 4
- Priority = (
- (NONE, 'None'),
- (MINOR, 'P4'),
- (LOW, 'P3'),
- (MEDIUM, 'P2'),
- (HIGH, 'P1'),
+ # Defect/SRTool Priority
+ DEFECT_UNDEFINED = 0
+ DEFECT_LOW = 1
+ DEFECT_MEDIUM = 2
+ DEFECT_HIGH = 3
+ DEFECT_CRITICAL = 4
+ DEFECT_PRIORITY_ERROR = 5
+ DEFECT_PRIORITY = (
+ (DEFECT_UNDEFINED, 'Undefined'),
+ (DEFECT_LOW, 'Low'),
+ (DEFECT_MEDIUM, 'Medium'),
+ (DEFECT_HIGH, 'High'),
+ (DEFECT_CRITICAL, 'Critical'),
+ (DEFECT_PRIORITY_ERROR, 'PRIORITY_ERROR'),
)
- OPEN = 0
- IN_PROGRESS = 1
- ON_HOLD = 2
- CHECKED_IN = 3
- RESOLVED = 4
- CLOSED = 5
- Status = (
- (OPEN, 'Open'),
- (IN_PROGRESS, 'In progress'),
- (ON_HOLD, 'On Hold'),
- (CHECKED_IN, 'Checked In'),
- (RESOLVED, 'Resolved'),
- (CLOSED, 'Closed'),
+ DEFECT_STATUS_OPEN = 0
+ DEFECT_STATUS_IN_PROGRESS = 1
+ DEFECT_STATUS_ON_HOLD = 2
+ DEFECT_STATUS_CHECKED_IN = 3
+ DEFECT_STATUS_RESOLVED = 4
+ DEFECT_STATUS_CLOSED = 5
+ DEFECT_STATUS = (
+ (DEFECT_STATUS_OPEN, 'Open'),
+ (DEFECT_STATUS_IN_PROGRESS, 'In progress'),
+ (DEFECT_STATUS_ON_HOLD, 'On Hold'),
+ (DEFECT_STATUS_CHECKED_IN, 'Checked In'),
+ (DEFECT_STATUS_RESOLVED, 'Resolved'),
+ (DEFECT_STATUS_CLOSED, 'Closed'),
)
- UNRESOLVED = 0
- RESOLVED = 1
- FIXED = 2
- WILL_NOT_FIX = 3
- WITHDRAWN = 4
- REJECTED = 5
- DUPLICATE = 6
- NOT_APPLICABLE = 7
- REPLACED_BY_REQUIREMENT = 8
- CANNOT_REPRODUCE = 9
- DONE = 10
- Resolution = (
- (UNRESOLVED, 'Unresolved'),
- (RESOLVED, 'Resolved'),
- (FIXED, 'Fixed'),
- (WILL_NOT_FIX, 'Won\'t Fix'),
- (WITHDRAWN, 'Withdrawn'),
- (REJECTED, 'Rejected'),
- (DUPLICATE, 'Duplicate'),
- (NOT_APPLICABLE, 'Not Applicable'),
- (REPLACED_BY_REQUIREMENT, 'Replaced By Requirement'),
- (CANNOT_REPRODUCE, 'Cannot Reproduce'),
- (DONE, 'Done'),
+ DEFECT_UNRESOLVED = 0
+ DEFECT_RESOLVED = 1
+ DEFECT_FIXED = 2
+ DEFECT_WILL_NOT_FIX = 3
+ DEFECT_WITHDRAWN = 4
+ DEFECT_REJECTED = 5
+ DEFECT_DUPLICATE = 6
+ DEFECT_NOT_APPLICABLE = 7
+ DEFECT_REPLACED_BY_REQUIREMENT = 8
+ DEFECT_CANNOT_REPRODUCE = 9
+ DEFECT_DONE = 10
+ DEFECT_RESOLUTION = (
+ (DEFECT_UNRESOLVED, 'Unresolved'),
+ (DEFECT_RESOLVED, 'Resolved'),
+ (DEFECT_FIXED, 'Fixed'),
+ (DEFECT_WILL_NOT_FIX, 'Won\'t Fix'),
+ (DEFECT_WITHDRAWN, 'Withdrawn'),
+ (DEFECT_REJECTED, 'Rejected'),
+ (DEFECT_DUPLICATE, 'Duplicate'),
+ (DEFECT_NOT_APPLICABLE, 'Not Applicable'),
+ (DEFECT_REPLACED_BY_REQUIREMENT, 'Replaced By Requirement'),
+ (DEFECT_CANNOT_REPRODUCE, 'Cannot Reproduce'),
+ (DEFECT_DONE, 'Done'),
)
+
Components = (
'BSP',
'Kernel',
@@ -796,12 +1097,62 @@ class Defect(models.Model):
'Test',
)
+ HISTORICAL = 0
+ NEW = 1
+ NEW_RESERVED = 2
+ INVESTIGATE = 3
+ VULNERABLE = 4
+ NOT_VULNERABLE = 5
+ SRT_STATUS = (
+ (HISTORICAL, 'Historical'),
+ (NEW, 'New'),
+ (NEW_RESERVED, 'New-Reserved'),
+ (INVESTIGATE, 'Investigate'),
+ (VULNERABLE, 'Vulnerable'),
+ (NOT_VULNERABLE, 'Not Vulnerable'),
+ )
+
+ OPEN = 0
+ CLOSED = 1
+ FIXED = 2
+ NOT_FIX = 3
+ SRT_OUTCOME = (
+ (OPEN, 'Open'),
+ (CLOSED, 'Closed (Not Vulnerable)'),
+ (FIXED, 'Closed (Fixed)'),
+ (NOT_FIX, "Closed (Won't Fix)"),
+ )
+
+ # SRTool Priority
+ UNDEFINED = 0
+ LOW = 1
+ MEDIUM = 2
+ HIGH = 3
+ CRITICAL = 4
+ PRIORITY_ERROR = 5
+ SRT_PRIORITY = (
+ (UNDEFINED, 'Undefined'),
+ (LOW, 'Low'),
+ (MEDIUM, 'Medium'),
+ (HIGH, 'High'),
+ (CRITICAL, 'Critical'),
+ (PRIORITY_ERROR, 'PRIORITY_ERROR'),
+ )
+
name = models.CharField(max_length=50)
summary = models.TextField(blank=True)
url = models.TextField(blank=True)
- priority = models.IntegerField(choices=Priority, default=MINOR)
- status = models.IntegerField(choices=Status, default=OPEN)
- resolution = models.IntegerField(choices=Resolution, default=UNRESOLVED)
+ duplicate_of = models.CharField(max_length=50, blank=True, default='')
+
+ # External defect specific values
+ priority = models.IntegerField(choices=DEFECT_PRIORITY, default=DEFECT_LOW)
+ status = models.IntegerField(choices=DEFECT_STATUS, default=DEFECT_STATUS_OPEN)
+ resolution = models.IntegerField(choices=DEFECT_RESOLUTION, default=DEFECT_UNRESOLVED)
+ # SRTool compatible values
+ srt_priority = models.IntegerField(choices=SRT_PRIORITY, default=LOW)
+ srt_status = models.IntegerField(choices=SRT_STATUS, default=INVESTIGATE)
+ srt_outcome = models.IntegerField(choices=SRT_OUTCOME, default=OPEN)
+
publish = models.TextField(blank=True)
release_version = models.CharField(max_length=50)
product = models.ForeignKey(Product,related_name="product_defect",on_delete=models.CASCADE,)
@@ -812,25 +1163,77 @@ class Defect(models.Model):
# Methods
@property
+ def get_defect_priority_text(self):
+ return Defect.DEFECT_PRIORITY[int(self.priority)][1]
+ @property
+ def get_defect_status_text(self):
+ return Defect.DEFECT_STATUS[int(self.status)][1]
+ @property
+ def get_defect_resolution_text(self):
+ return Defect.DEFECT_RESOLUTION[int(self.resolution)][1]
+ @property
def get_priority_text(self):
- return Defect.Priority[int(self.priority)][1]
+ return SRTool.priority_text(self.srt_priority)
@property
def get_status_text(self):
- return Defect.Status[int(self.status)][1]
+ return SRTool.status_text(self.srt_status)
+ @property
+ def get_outcome_text(self):
+ return SRTool.outcome_text(self.srt_outcome)
+ @property
+ def get_date_created_text(self):
+ return re.sub(r"T.*", "", self.date_created)
+ @property
+ def get_date_updated_text(self):
+ return re.sub(r"T.*", "", self.date_updated)
@property
- def get_resolution_text(self):
- return Defect.Resolution[int(self.resolution)][1]
def get_long_name(self):
if self.release_version:
return "%s (%s)" % (self.name,self.release_version)
return "%s" % (self.name)
+ @property
+ def get_cve_names(self):
+ cve_list = []
+ for di in InvestigationToDefect.objects.filter(defect = self):
+ for i2v in VulnerabilityToInvestigation.objects.filter(investigation = di.investigation):
+ for v2c in CveToVulnerablility.objects.filter(vulnerability = i2v.vulnerability):
+ cve_list.append(v2c.cve.name)
+ return ','.join(cve_list)
+ @property
+ def get_cve_ids(self):
+ cve_list = []
+ for di in InvestigationToDefect.objects.filter(defect = self):
+ for i2v in VulnerabilityToInvestigation.objects.filter(investigation = di.investigation):
+ for v2c in CveToVulnerablility.objects.filter(vulnerability = i2v.vulnerability):
+ cve_list.append(str(v2c.cve.id))
+ return ','.join(cve_list)
+ @property
+ def get_publishset_state(self):
+ pub_list = []
+ cve_list = self.get_cve_names
+ if not cve_list:
+ return PublishSet.PUBLISH_SET_STATE[PublishSet.PUBLISH_SET_NONE][1]
+ for cve_name in cve_list.split(','):
+ try:
+ cve = Cve.objects.get(name = cve_name)
+ pub_list.append(cve.get_publishset_state)
+ except Exception as e:
+ pass
+ return ','.join(pub_list)
+
+class DefectHistory(models.Model):
+ search_allowed_fields = ['defect__name', 'comment', 'date', 'author']
+ defect = models.ForeignKey(Defect,related_name="defect_history",on_delete=models.CASCADE,)
+ comment = models.TextField(blank=True)
+ date = models.DateField(null=True, blank=True)
+ author = models.TextField(blank=True)
# INVESTIGATION
# Product-level Vulnerablility Investigation Record
class Investigation(models.Model):
- search_allowed_fields = ['name', 'comments', 'comments_private']
+ search_allowed_fields = ['name', 'comments', 'comments_private', 'tags']
HISTORICAL = 0
NEW = 1
@@ -858,18 +1261,22 @@ class Investigation(models.Model):
(NOT_FIX, "Closed (Won't Fix)"),
)
+ # SRTool Priority
UNDEFINED = 0
- MINOR = 1
- LOW = 2
- MEDIUM = 3
- HIGH = 4
+ LOW = 1
+ MEDIUM = 2
+ HIGH = 3
+ CRITICAL = 4
+ PRIORITY_ERROR = 5
PRIORITY = (
(UNDEFINED, 'Undefined'),
- (MINOR, 'Minor'),
(LOW, 'Low'),
(MEDIUM, 'Medium'),
(HIGH, 'High'),
+ (CRITICAL, 'Critical'),
+ (PRIORITY_ERROR, 'PRIORITY_ERROR'),
)
+
name = models.CharField(max_length=50)
vulnerability = models.ForeignKey(Vulnerability,related_name="vulnerability_investigation",on_delete=models.CASCADE,)
product = models.ForeignKey(Product,related_name="product_investigation",on_delete=models.CASCADE,)
@@ -877,21 +1284,25 @@ class Investigation(models.Model):
public = models.BooleanField(default=True)
comments = models.TextField(blank=True)
comments_private = models.TextField(blank=True)
+ tags = models.TextField(blank=True, default='')
status = models.IntegerField(choices=STATUS, default=OPEN)
outcome = models.IntegerField(choices=OUTCOME, default=INVESTIGATE)
priority = models.IntegerField(choices=PRIORITY, default=LOW)
+ srt_updated = models.DateTimeField(auto_now=True, null=True)
+ srt_created = models.DateTimeField(auto_now_add=True, null=True)
+
# Methods
@property
+ def get_priority_text(self):
+ return SRTool.priority_text(self.priority)
+ @property
def get_status_text(self):
- return Investigation.STATUS[int(self.status)][1]
+ return SRTool.status_text(self.status)
@property
def get_outcome_text(self):
- return Investigation.OUTCOME[int(self.outcome)][1]
- @property
- def get_priority_text(self):
- return Investigation.PRIORITY[int(self.priority)][1]
+ return SRTool.outcome_text(self.outcome)
@property
def get_long_name(self):
if self.vulnerability and self.vulnerability.cve_primary_name:
@@ -920,6 +1331,7 @@ class InvestigationComments(models.Model):
author = models.TextField(blank=True)
class InvestigationHistory(models.Model):
+ search_allowed_fields = ['investigation__name', 'comment', 'date', 'author']
investigation = models.ForeignKey(Investigation,related_name="investigation_history",on_delete=models.CASCADE,)
comment = models.TextField(blank=True)
date = models.DateField(null=True, blank=True)
@@ -979,17 +1391,21 @@ def _log_args(msg, *args, **kwargs):
# Action items waiting
class Notify(models.Model):
search_allowed_fields = ['category','description','url']
+
+ # SRTool Priority
UNDEFINED = 0
- MINOR = 1
- LOW = 2
- MEDIUM = 3
- HIGH = 4
+ LOW = 1
+ MEDIUM = 2
+ HIGH = 3
+ CRITICAL = 4
+ PRIORITY_ERROR = 5
PRIORITY = (
(UNDEFINED, 'Undefined'),
- (MINOR, 'Minor'),
(LOW, 'Low'),
(MEDIUM, 'Medium'),
(HIGH, 'High'),
+ (CRITICAL, 'Critical'),
+ (PRIORITY_ERROR, 'PRIORITY_ERROR'),
)
category = models.CharField(max_length=50)
@@ -997,8 +1413,10 @@ class Notify(models.Model):
priority = models.IntegerField(default=0)
url = models.TextField(blank=True)
author = models.TextField(blank=True)
- srt_updated = models.DateTimeField(auto_now_add=True)
- srt_created = models.DateTimeField(auto_now=True)
+## srt_updated = models.DateTimeField(auto_now_add=True)
+## srt_created = models.DateTimeField(auto_now=True)
+ srt_updated = models.DateTimeField(auto_now=True, null=True)
+ srt_created = models.DateTimeField(auto_now_add=True, null=True)
@property
def get_priority_text(self):
@@ -1013,6 +1431,35 @@ class NotifyAccess(models.Model):
class NotifyCategories(models.Model):
category = models.CharField(max_length=50)
+class PublishSet(models.Model):
+ search_allowed_fields = ['cve__name','cve__description','cve__status','cve__publishedDate','cve__lastModifiedDate']
+
+ # Publish state
+ PUBLISH_SET_NONE = 0
+ PUBLISH_SET_NEW = 1
+ PUBLISH_SET_MODIFIED = 2
+ PUBLISH_SET_NEW_USER = 3
+ PUBLISH_SET_MODIFIED_USER = 4
+ PUBLISH_SET_ERROR = 5
+ PUBLISH_SET_STATE = (
+ (PUBLISH_SET_NONE, 'Skip'),
+ (PUBLISH_SET_NEW, 'New'),
+ (PUBLISH_SET_MODIFIED, 'Modified'),
+ (PUBLISH_SET_NEW_USER, 'New_User'),
+ (PUBLISH_SET_MODIFIED_USER, 'Modified_User'),
+ (PUBLISH_SET_ERROR, 'PUBLISH_SET_ERROR'),
+ )
+
+ cve = models.ForeignKey(default=None, to='orm.cve', null=True, on_delete=models.CASCADE,)
+ state = models.IntegerField(choices=PUBLISH_SET_STATE, default=PUBLISH_SET_NONE)
+ reason = models.TextField(blank=True)
+
+ @property
+ def state_text(self):
+ if (0 > self.state) or (self.state >= len(self.PUBLISH_SET_STATE)):
+ return self.PUBLISH_SET_STATE[self.PUBLISH_SET_ERROR][1]
+ return self.PUBLISH_SET_STATE[self.state][1]
+
#
# Database Cache Support
#