Skip to content

Commit ca8c266

Browse files
also sync group severity
1 parent 0657ef6 commit ca8c266

File tree

50 files changed

+14488
-9138
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

50 files changed

+14488
-9138
lines changed

dojo/fixtures/dojo_testdata.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2164,7 +2164,7 @@
21642164
"epic_name_id": 10011,
21652165
"open_status_key": 11,
21662166
"close_status_key": 41,
2167-
"info_mapping_severity": "Trivial",
2167+
"info_mapping_severity": "Lowest",
21682168
"low_mapping_severity": "Low",
21692169
"medium_mapping_severity": "Medium",
21702170
"high_mapping_severity": "High",

dojo/jira_link/helper.py

Lines changed: 48 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -532,6 +532,20 @@ def get_jira_status(finding):
532532
return None
533533

534534

535+
# Used for unit testing so geting all the connections is manadatory
536+
def get_jira_priortiy(finding):
537+
if finding.has_jira_issue:
538+
j_issue = finding.jira_issue.jira_id
539+
elif finding.finding_group and finding.finding_group.has_jira_issue:
540+
j_issue = finding.finding_group.jira_issue.jira_id
541+
542+
if j_issue:
543+
project = get_jira_project(finding)
544+
issue = jira_get_issue(project, j_issue)
545+
return issue.fields.priority
546+
return None
547+
548+
535549
# Used for unit testing so geting all the connections is manadatory
536550
def get_jira_comments(finding):
537551
if finding.has_jira_issue:
@@ -675,15 +689,20 @@ def jira_description(obj):
675689
def jira_priority(obj):
676690
if isinstance(obj, Finding):
677691
return get_jira_instance(obj).get_priority(obj.severity)
692+
678693
if isinstance(obj, Finding_Group):
679-
finding_group_severity_for_jira = get_finding_group_findings_above_threshold(obj)
694+
# priority based on qualified findings, so if alls criticals get closed, the priority will gets lowered etc
695+
active_findings = get_qualified_findings(obj)
680696

681-
max_number_severity = max(Finding.get_number_severity(find.severity) for find in finding_group_severity_for_jira)
682-
return Finding.get_severity(max_number_severity)
697+
if not active_findings:
698+
# using a string literal "Info" as we don't really have a "enum" for this anywhere
699+
max_number_severity = Finding.get_number_severity("Info")
700+
else:
701+
max_number_severity = max(Finding.get_number_severity(find.severity) for find in active_findings)
702+
return get_jira_instance(obj).get_priority(Finding.get_severity(max_number_severity))
683703

684-
logger.error("unsupported object passed to push_to_jira: %s %i %s", obj.__name__, obj.id, obj)
685-
msg = f"Unsupported object passed to push_to_jira: {type(obj)}"
686-
raise RuntimeError(msg)
704+
msg = f"Unsupported object type for jira_priority: {obj.__class__.__name__}"
705+
raise ValueError(msg)
687706

688707

689708
def jira_environment(obj):
@@ -897,7 +916,7 @@ def failure_to_add_message(message: str, exception: Exception, _: Any) -> bool:
897916
return failure_to_add_message(message, e, obj)
898917
# Create a new issue in Jira with the fields set in the last step
899918
try:
900-
logger.debug("sending fields to JIRA: %s", fields)
919+
logger.debug("Creating new JIRA issue with fields: %s", json.dumps(fields, indent=4))
901920
new_issue = jira.create_issue(fields)
902921
logger.debug("saving JIRA_Issue for %s finding %s", new_issue.key, obj.id)
903922
j_issue = JIRA_Issue(jira_id=new_issue.id, jira_key=new_issue.key, jira_project=jira_project)
@@ -1000,6 +1019,14 @@ def failure_to_update_message(message: str, exception: Exception, obj: Any) -> b
10001019
labels = get_labels(obj) + get_tags(obj)
10011020
if labels:
10021021
labels = list(dict.fromkeys(labels)) # de-dup
1022+
1023+
# Only Finding Groups will have their priority synced on updates.
1024+
# For Findings we resepect any priority change made in JIRA
1025+
# https://github.com/DefectDojo/django-DefectDojo/pull/9571 and https://github.com/DefectDojo/django-DefectDojo/pull/12475
1026+
jira_priority_name = None
1027+
if isinstance(obj, Finding_Group):
1028+
jira_priority_name = jira_priority(obj)
1029+
10031030
# Set the fields that will compose the jira issue
10041031
try:
10051032
issuetype_fields = get_issuetype_fields(jira, jira_project.project_key, jira_instance.default_issue_type)
@@ -1011,20 +1038,18 @@ def failure_to_update_message(message: str, exception: Exception, obj: Any) -> b
10111038
component_name=jira_project.component if not issue.fields.components else None,
10121039
labels=labels + issue.fields.labels,
10131040
environment=jira_environment(obj),
1014-
# Do not update the priority in jira after creation as this could have changed in jira, but should not change in dojo
1015-
# priority_name=jira_priority(obj),
1041+
priority_name=jira_priority_name,
10161042
issuetype_fields=issuetype_fields)
10171043
except Exception as e:
10181044
message = f"Failed to fetch fields for {jira_instance.default_issue_type} under project {jira_project.project_key} - {e}"
10191045
return failure_to_update_message(message, e, obj)
1046+
10201047
# Update the issue in jira
10211048
try:
1022-
logger.debug("sending fields to JIRA: %s", fields)
1049+
logger.debug("Updating JIRA issue with fields: %s", json.dumps(fields, indent=4))
10231050
issue.update(
10241051
summary=fields["summary"],
10251052
description=fields["description"],
1026-
# Do not update the priority in jira after creation as this could have changed in jira, but should not change in dojo
1027-
# priority=fields['priority'],
10281053
fields=fields)
10291054
j_issue.jira_change = timezone.now()
10301055
j_issue.save()
@@ -1179,12 +1204,14 @@ def get_issuetype_fields(
11791204
try:
11801205
project = meta["projects"][0]
11811206
except Exception:
1207+
logger.debug("JIRA meta: %s", json.dumps(meta, indent=4)) # this is None safe
11821208
msg = "Project misconfigured or no permissions in Jira ?"
11831209
raise JIRAError(msg)
11841210

11851211
try:
11861212
issuetype_fields = project["issuetypes"][0]["fields"].keys()
11871213
except Exception:
1214+
logger.debug("JIRA meta: %s", json.dumps(meta, indent=4)) # this is None safe
11881215
msg = "Misconfigured default issue type ?"
11891216
raise JIRAError(msg)
11901217

@@ -1808,20 +1835,20 @@ def is_qualified(finding):
18081835
return finding.active and (finding.verified or not isenforced) and (finding.numerical_severity <= jira_minimum_threshold)
18091836

18101837

1811-
def get_qualified_findings(findings):
1838+
def get_qualified_findings(finding_group):
18121839
"""Filters findings to return only findings qualified to be pushed to JIRA, i.e. active, verified (unless not enforced) and severity is above the threshold"""
1813-
if not findings:
1840+
if not finding_group.findings.all():
18141841
return None
18151842

1816-
return [find for find in findings if is_qualified(find)]
1843+
return [find for find in finding_group.findings.all() if is_qualified(find)]
18171844

18181845

1819-
def get_non_qualified_findings(findings):
1846+
def get_non_qualified_findings(finding_group):
18201847
"""Filters findings to return only findings not qualified to be pushed to JIRA, i.e. inactive, not-verified (unless not enforced) and severity is below the threshold"""
1821-
if not findings:
1848+
if not finding_group.findings.all():
18221849
return None
18231850

1824-
return [find for find in findings if not is_qualified(find)]
1851+
return [find for find in finding_group.findings.all() if not is_qualified(find)]
18251852

18261853

18271854
def get_sla_deadline(obj):
@@ -1833,10 +1860,10 @@ def get_sla_deadline(obj):
18331860
return obj.sla_deadline()
18341861

18351862
if isinstance(obj, Finding_Group):
1836-
return min([find.sla_deadline() for find in get_qualified_findings(obj.findings.all()) if find.sla_deadline()], default=None)
1863+
return min([find.sla_deadline() for find in get_qualified_findings(obj) if find.sla_deadline()], default=None)
18371864

1838-
logger.warning("get_sla_deadline: obj passed that is not a Finding or Finding_Group")
1839-
return None
1865+
msg = f"get_sla_deadline: obj passed that is not a Finding or Finding_Group: {type(obj)}"
1866+
raise ValueError(msg)
18401867

18411868

18421869
def get_severity(findings):

dojo/templates/issue-trackers/jira_full/jira-finding-group-description.tpl

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,14 @@ h2. Group
1111
*Group*: [{{ finding_group.name|jiraencode}}|{{ finding_group_url|full_url }}] in [{{ finding_group.test.engagement.product.name|jiraencode }}|{{ product_url|full_url }}] / [{{ finding_group.test.engagement.name|jiraencode }}|{{ engagement_url|full_url }}] / [{{ finding_group.test|stringformat:'s'|jiraencode }}|{{ test_url|full_url }}]
1212

1313
h2. Summary
14-
*Severity:* {{ finding_group.findings.all | jira_severity }} {% if finding_group.sla_deadline %} *Due Date:* {{ finding_group.findings.all | jira_sla_deadline }} {% endif %}
14+
*Severity:* {{ finding_group.findings.all | jira_severity }} {% if finding_group.sla_deadline %} *Due Date:* {{ finding_group | jira_sla_deadline }} {% endif %}
1515

1616
Findings matching the Active,{% if system_settings.enforce_verified_status or system_settings.enforce_verified_status_jira %} Verified{% endif %} and Severity criteria:
17-
|| Severity || CVE || CWE || Component || Version || Title || Status ||{% for finding in finding_group.findings.all|jira_qualified_findings %}
17+
|| Severity || CVE || CWE || Component || Version || Title || Status ||{% for finding in finding_group|jira_qualified_findings %}
1818
|{{finding.severity}}|{% if finding.cve %}[{{finding.cve}}|{{finding.cve|vulnerability_url}}]{% else %}None{% endif %}|[{{finding.cwe}}|{{finding.cwe|cwe_url}}]|{{finding.component_name|jiraencode_component}}|{{finding.component_version}}|{% url 'view_finding' finding.id as finding_url %}[{{ finding.title|jiraencode}}|{{ finding_url|full_url }}]|{{ finding.status }}|{% endfor %}
1919

2020
Findings *not* matching the Active,{% if system_settings.enforce_verified_status or system_settings.enforce_verified_status_jira %} Verified{% endif %} and Severity criteria:
21-
|| Severity || CVE || CWE || Component || Version || Title || Status ||{% for finding in finding_group.findings.all|jira_non_qualified_findings %}
21+
|| Severity || CVE || CWE || Component || Version || Title || Status ||{% for finding in finding_group|jira_non_qualified_findings %}
2222
|{{finding.severity}}|{% if finding.cve %}[{{finding.cve}}|{{finding.cve|vulnerability_url}}]{% else %}None{% endif %}|[{{finding.cwe}}|{{finding.cwe|cwe_url}}]|{{finding.component_name|jiraencode_component}}|{{finding.component_version}}|{% url 'view_finding' finding.id as finding_url %}[{{ finding.title|jiraencode}}|{{ finding_url|full_url }}]|{{ finding.status }}|{% endfor %}
2323

2424
{% if finding_group.test.engagement.branch_tag %}

dojo/templatetags/display_tags.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -871,18 +871,18 @@ def jira_change(obj):
871871

872872

873873
@register.filter
874-
def jira_qualified_findings(findings):
875-
return jira_helper.get_qualified_findings(findings)
874+
def jira_qualified_findings(finding_group):
875+
return jira_helper.get_qualified_findings(finding_group)
876876

877877

878878
@register.filter
879-
def jira_non_qualified_findings(findings):
880-
return jira_helper.get_non_qualified_findings(findings)
879+
def jira_non_qualified_findings(finding_group):
880+
return jira_helper.get_non_qualified_findings(finding_group)
881881

882882

883883
@register.filter
884-
def jira_sla_deadline(findings):
885-
return jira_helper.get_sla_deadline(findings)
884+
def jira_sla_deadline(obj):
885+
return jira_helper.get_sla_deadline(obj)
886886

887887

888888
@register.filter

unittests/dojo_test_case.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -406,6 +406,10 @@ def get_jira_issue_status(self, finding_id):
406406
finding = Finding.objects.get(id=finding_id)
407407
return jira_helper.get_jira_status(finding)
408408

409+
def get_jira_issue_priority(self, finding_id):
410+
finding = Finding.objects.get(id=finding_id)
411+
return jira_helper.get_jira_priortiy(finding)
412+
409413
def get_jira_issue_updated(self, finding_id):
410414
finding = Finding.objects.get(id=finding_id)
411415
return jira_helper.get_jira_updated(finding)

0 commit comments

Comments
 (0)