Skip to content

Commit 2dd11aa

Browse files
also sync group severity
1 parent dd66bad commit 2dd11aa

50 files changed

Lines changed: 14488 additions & 9140 deletions

File tree

Some content is hidden

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

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):
@@ -900,7 +919,7 @@ def failure_to_add_message(message: str, exception: Exception, _: Any) -> bool:
900919
return failure_to_add_message(message, e, obj)
901920
# Create a new issue in Jira with the fields set in the last step
902921
try:
903-
logger.debug("sending fields to JIRA: %s", fields)
922+
logger.debug("Creating new JIRA issue with fields: %s", json.dumps(fields, indent=4))
904923
new_issue = jira.create_issue(fields)
905924
logger.debug("saving JIRA_Issue for %s finding %s", new_issue.key, obj.id)
906925
j_issue = JIRA_Issue(jira_id=new_issue.id, jira_key=new_issue.key, jira_project=jira_project)
@@ -1003,6 +1022,14 @@ def failure_to_update_message(message: str, exception: Exception, obj: Any) -> b
10031022
labels = get_labels(obj) + get_tags(obj)
10041023
if labels:
10051024
labels = list(dict.fromkeys(labels)) # de-dup
1025+
1026+
# Only Finding Groups will have their priority synced on updates.
1027+
# For Findings we resepect any priority change made in JIRA
1028+
# https://github.com/DefectDojo/django-DefectDojo/pull/9571 and https://github.com/DefectDojo/django-DefectDojo/pull/12475
1029+
jira_priority_name = None
1030+
if isinstance(obj, Finding_Group):
1031+
jira_priority_name = jira_priority(obj)
1032+
10061033
# Set the fields that will compose the jira issue
10071034
try:
10081035
issuetype_fields = get_issuetype_fields(jira, jira_project.project_key, jira_instance.default_issue_type)
@@ -1014,20 +1041,18 @@ def failure_to_update_message(message: str, exception: Exception, obj: Any) -> b
10141041
component_name=jira_project.component if not issue.fields.components else None,
10151042
labels=labels + issue.fields.labels,
10161043
environment=jira_environment(obj),
1017-
# Do not update the priority in jira after creation as this could have changed in jira, but should not change in dojo
1018-
# priority_name=jira_priority(obj),
1044+
priority_name=jira_priority_name,
10191045
issuetype_fields=issuetype_fields)
10201046
except Exception as e:
10211047
message = f"Failed to fetch fields for {jira_instance.default_issue_type} under project {jira_project.project_key} - {e}"
10221048
return failure_to_update_message(message, e, obj)
1049+
10231050
# Update the issue in jira
10241051
try:
1025-
logger.debug("sending fields to JIRA: %s", fields)
1052+
logger.debug("Updating JIRA issue with fields: %s", json.dumps(fields, indent=4))
10261053
issue.update(
10271054
summary=fields["summary"],
10281055
description=fields["description"],
1029-
# Do not update the priority in jira after creation as this could have changed in jira, but should not change in dojo
1030-
# priority=fields['priority'],
10311056
fields=fields)
10321057
j_issue.jira_change = timezone.now()
10331058
j_issue.save()
@@ -1182,12 +1207,14 @@ def get_issuetype_fields(
11821207
try:
11831208
project = meta["projects"][0]
11841209
except Exception:
1210+
logger.debug("JIRA meta: %s", json.dumps(meta, indent=4)) # this is None safe
11851211
msg = "Project misconfigured or no permissions in Jira ?"
11861212
raise JIRAError(msg)
11871213

11881214
try:
11891215
issuetype_fields = project["issuetypes"][0]["fields"].keys()
11901216
except Exception:
1217+
logger.debug("JIRA meta: %s", json.dumps(meta, indent=4)) # this is None safe
11911218
msg = "Misconfigured default issue type ?"
11921219
raise JIRAError(msg)
11931220

@@ -1816,20 +1843,20 @@ def is_qualified(finding):
18161843
return finding.active and (finding.verified or not isenforced) and (finding.numerical_severity <= jira_minimum_threshold)
18171844

18181845

1819-
def get_qualified_findings(findings):
1846+
def get_qualified_findings(finding_group):
18201847
"""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"""
1821-
if not findings:
1848+
if not finding_group.findings.all():
18221849
return None
18231850

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

18261853

1827-
def get_non_qualified_findings(findings):
1854+
def get_non_qualified_findings(finding_group):
18281855
"""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"""
1829-
if not findings:
1856+
if not finding_group.findings.all():
18301857
return None
18311858

1832-
return [find for find in findings if not is_qualified(find)]
1859+
return [find for find in finding_group.findings.all() if not is_qualified(find)]
18331860

18341861

18351862
def get_sla_deadline(obj):
@@ -1841,10 +1868,10 @@ def get_sla_deadline(obj):
18411868
return obj.sla_deadline()
18421869

18431870
if isinstance(obj, Finding_Group):
1844-
return min([find.sla_deadline() for find in get_qualified_findings(obj.findings.all()) if find.sla_deadline()], default=None)
1871+
return min([find.sla_deadline() for find in get_qualified_findings(obj) if find.sla_deadline()], default=None)
18451872

1846-
logger.warning("get_sla_deadline: obj passed that is not a Finding or Finding_Group")
1847-
return None
1873+
msg = f"get_sla_deadline: obj passed that is not a Finding or Finding_Group: {type(obj)}"
1874+
raise ValueError(msg)
18481875

18491876

18501877
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)