Skip to content

Commit d9efd8a

Browse files
also sync group severity
1 parent a657387 commit d9efd8a

50 files changed

Lines changed: 14488 additions & 9138 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:
@@ -676,15 +690,20 @@ def jira_description(obj):
676690
def jira_priority(obj):
677691
if isinstance(obj, Finding):
678692
return get_jira_instance(obj).get_priority(obj.severity)
693+
679694
if isinstance(obj, Finding_Group):
680-
finding_group_severity_for_jira = get_finding_group_findings_above_threshold(obj)
695+
# priority based on qualified findings, so if alls criticals get closed, the priority will gets lowered etc
696+
active_findings = get_qualified_findings(obj)
681697

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

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

689708

690709
def jira_environment(obj):
@@ -895,7 +914,7 @@ def failure_to_add_message(message: str, exception: Exception, _: Any) -> bool:
895914
return failure_to_add_message(message, e, obj)
896915
# Create a new issue in Jira with the fields set in the last step
897916
try:
898-
logger.debug("sending fields to JIRA: %s", fields)
917+
logger.debug("Creating new JIRA issue with fields: %s", json.dumps(fields, indent=4))
899918
new_issue = jira.create_issue(fields)
900919
logger.debug("saving JIRA_Issue for %s finding %s", new_issue.key, obj.id)
901920
j_issue = JIRA_Issue(jira_id=new_issue.id, jira_key=new_issue.key, jira_project=jira_project)
@@ -1016,6 +1035,14 @@ def failure_to_update_message(message: str, exception: Exception, obj: Any) -> b
10161035
labels = get_labels(obj) + get_tags(obj)
10171036
if labels:
10181037
labels = list(dict.fromkeys(labels)) # de-dup
1038+
1039+
# Only Finding Groups will have their priority synced on updates.
1040+
# For Findings we resepect any priority change made in JIRA
1041+
# https://github.com/DefectDojo/django-DefectDojo/pull/9571 and https://github.com/DefectDojo/django-DefectDojo/pull/12475
1042+
jira_priority_name = None
1043+
if isinstance(obj, Finding_Group):
1044+
jira_priority_name = jira_priority(obj)
1045+
10191046
# Set the fields that will compose the jira issue
10201047
try:
10211048
issuetype_fields = get_issuetype_fields(jira, jira_project.project_key, jira_instance.default_issue_type)
@@ -1027,20 +1054,18 @@ def failure_to_update_message(message: str, exception: Exception, obj: Any) -> b
10271054
component_name=jira_project.component if not issue.fields.components else None,
10281055
labels=labels + issue.fields.labels,
10291056
environment=jira_environment(obj),
1030-
# Do not update the priority in jira after creation as this could have changed in jira, but should not change in dojo
1031-
# priority_name=jira_priority(obj),
1057+
priority_name=jira_priority_name,
10321058
issuetype_fields=issuetype_fields)
10331059
except Exception as e:
10341060
message = f"Failed to fetch fields for {jira_instance.default_issue_type} under project {jira_project.project_key} - {e}"
10351061
return failure_to_update_message(message, e, obj)
1062+
10361063
# Update the issue in jira
10371064
try:
1038-
logger.debug("sending fields to JIRA: %s", fields)
1065+
logger.debug("Updating JIRA issue with fields: %s", json.dumps(fields, indent=4))
10391066
issue.update(
10401067
summary=fields["summary"],
10411068
description=fields["description"],
1042-
# Do not update the priority in jira after creation as this could have changed in jira, but should not change in dojo
1043-
# priority=fields['priority'],
10441069
fields=fields)
10451070
j_issue.jira_change = timezone.now()
10461071
j_issue.save()
@@ -1195,12 +1220,14 @@ def get_issuetype_fields(
11951220
try:
11961221
project = meta["projects"][0]
11971222
except Exception:
1223+
logger.debug("JIRA meta: %s", json.dumps(meta, indent=4)) # this is None safe
11981224
msg = "Project misconfigured or no permissions in Jira ?"
11991225
raise JIRAError(msg)
12001226

12011227
try:
12021228
issuetype_fields = project["issuetypes"][0]["fields"].keys()
12031229
except Exception:
1230+
logger.debug("JIRA meta: %s", json.dumps(meta, indent=4)) # this is None safe
12041231
msg = "Misconfigured default issue type ?"
12051232
raise JIRAError(msg)
12061233

@@ -1824,20 +1851,20 @@ def is_qualified(finding):
18241851
return finding.active and (finding.verified or not isenforced) and (finding.numerical_severity <= jira_minimum_threshold)
18251852

18261853

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

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

18341861

1835-
def get_non_qualified_findings(findings):
1862+
def get_non_qualified_findings(finding_group):
18361863
"""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"""
1837-
if not findings:
1864+
if not finding_group.findings.all():
18381865
return None
18391866

1840-
return [find for find in findings if not is_qualified(find)]
1867+
return [find for find in finding_group.findings.all() if not is_qualified(find)]
18411868

18421869

18431870
def get_sla_deadline(obj):
@@ -1849,10 +1876,10 @@ def get_sla_deadline(obj):
18491876
return obj.sla_deadline()
18501877

18511878
if isinstance(obj, Finding_Group):
1852-
return min([find.sla_deadline() for find in get_qualified_findings(obj.findings.all()) if find.sla_deadline()], default=None)
1879+
return min([find.sla_deadline() for find in get_qualified_findings(obj) if find.sla_deadline()], default=None)
18531880

1854-
logger.warning("get_sla_deadline: obj passed that is not a Finding or Finding_Group")
1855-
return None
1881+
msg = f"get_sla_deadline: obj passed that is not a Finding or Finding_Group: {type(obj)}"
1882+
raise ValueError(msg)
18561883

18571884

18581885
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
@@ -869,18 +869,18 @@ def jira_change(obj):
869869

870870

871871
@register.filter
872-
def jira_qualified_findings(findings):
873-
return jira_helper.get_qualified_findings(findings)
872+
def jira_qualified_findings(finding_group):
873+
return jira_helper.get_qualified_findings(finding_group)
874874

875875

876876
@register.filter
877-
def jira_non_qualified_findings(findings):
878-
return jira_helper.get_non_qualified_findings(findings)
877+
def jira_non_qualified_findings(finding_group):
878+
return jira_helper.get_non_qualified_findings(finding_group)
879879

880880

881881
@register.filter
882-
def jira_sla_deadline(findings):
883-
return jira_helper.get_sla_deadline(findings)
882+
def jira_sla_deadline(obj):
883+
return jira_helper.get_sla_deadline(obj)
884884

885885

886886
@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)