Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Release: Merge back 2.39.1 into dev from: master-into-dev/2.39.1-2.40.0-dev #11076

Merged
merged 19 commits into from
Oct 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
4728bd4
Update versions in application files
Oct 7, 2024
43bc215
Merge pull request #11014 from DefectDojo/master-into-bugfix/2.39.0-2…
Maffooch Oct 7, 2024
67d87e7
Bump django from 5.0.8 to 5.0.9 (#11023)
dependabot[bot] Oct 9, 2024
5985567
Downgrade uwsgi to 2.0.26 (#11033)
Maffooch Oct 11, 2024
316d61a
New Jira Form: Make express the default (#11041)
Maffooch Oct 11, 2024
d56964f
AWS Security Hub: Accommodate for reports with missing AccountID (#11…
Maffooch Oct 11, 2024
51557ec
Netsparker: Attempt to accommodate any date string format (#11047)
Maffooch Oct 11, 2024
58aa6ba
Jira: Add toggle to disable an existing project (#11046)
Maffooch Oct 11, 2024
f345a4e
Fix for Findings count in Dashboard based on wrong date (#11040)
hblankenship Oct 11, 2024
b58ff49
fix for issue 11010 (#11042)
hblankenship Oct 11, 2024
409896c
remove mods, add Jannik to Hall of Fame (#11043)
hblankenship Oct 11, 2024
c494b0b
:tada: Add USN notices for vulnids (#11002)
manuel-sommer Oct 11, 2024
728ab1e
add DLA security advisory (#11058)
manuel-sommer Oct 15, 2024
985299d
Update support text and buttons (#11051)
hblankenship Oct 15, 2024
ac1048e
Parser Tests: add tag to differentiate (#11017)
Maffooch Oct 15, 2024
0962bd6
Update versions in application files
Oct 15, 2024
52e9f16
Merge pull request #11073 from DefectDojo/release/2.39.1
rossops Oct 15, 2024
309a65f
Update versions in application files
Oct 15, 2024
643461e
Merge branch 'dev' into master-into-dev/2.39.1-2.40.0-dev
rossops Oct 15, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 3 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -132,15 +132,14 @@ Core Moderators can help you with pull requests or feedback on dev ideas:
* Cody Maffucci ([@Maffooch](https://github.com/maffooch) | [LinkedIn](https://www.linkedin.com/in/cody-maffucci))

Moderators can help you with pull requests or feedback on dev ideas:
* Damien Carol ([@damiencarol](https://github.com/damiencarol) | [LinkedIn](https://www.linkedin.com/in/damien-carol/))
* Jannik Jürgens ([@alles-klar](https://github.com/alles-klar))
* Dubravko Sever ([@dsever](https://github.com/dsever))
* Charles Neill ([@cneill](https://github.com/cneill) | [@ccneill](https://twitter.com/ccneill))
* Jay Paz ([@jjpaz](https://twitter.com/jjpaz))
* Blake Owens ([@blakeaowens](https://github.com/blakeaowens))

## Hall of Fame

* Jannik Jürgens ([@alles-klar](https://github.com/alles-klar)) - Jannik was a long time contributor and moderator for
DefectDojo and made significant contributions to many areas of the platform. Jannik was instrumental in pioneering
and optimizing deployment methods.
* Valentijn Scholten ([@valentijnscholten](https://github.com/valentijnscholten) |
[Sponsor](https://github.com/sponsors/valentijnscholten) |
[LinkedIn](https://www.linkedin.com/in/valentijn-scholten/)) - Valentijn served as a core moderator for 3 years.
Expand Down
1 change: 1 addition & 0 deletions dojo/api_v2/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -1517,6 +1517,7 @@ class JiraProjectViewSet(
"jira_instance",
"product",
"engagement",
"enabled",
"component",
"project_key",
"push_all_issues",
Expand Down
18 changes: 18 additions & 0 deletions dojo/db_migrations/0217_jira_project_enabled.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Generated by Django 5.0.8 on 2024-10-10 17:07

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('dojo', '0216_alter_jira_project_push_all_issues'),
]

operations = [
migrations.AddField(
model_name='jira_project',
name='enabled',
field=models.BooleanField(blank=True, default=True, help_text='When disabled, Findings will no longer be pushed to Jira, even if they have already been pushed previously.', verbose_name='Enable Connection With Jira Project'),
),
]
3 changes: 3 additions & 0 deletions dojo/fixtures/defect_dojo_sample_data.json
Original file line number Diff line number Diff line change
Expand Up @@ -35210,6 +35210,7 @@
"engagement": null,
"component": "",
"push_all_issues": false,
"enabled": true,
"enable_engagement_epic_mapping": true,
"push_notes": false,
"product_jira_sla_notification": false,
Expand All @@ -35227,6 +35228,7 @@
"engagement": null,
"component": "",
"push_all_issues": true,
"enabled": true,
"enable_engagement_epic_mapping": true,
"push_notes": true,
"product_jira_sla_notification": false,
Expand All @@ -35244,6 +35246,7 @@
"engagement": null,
"component": "",
"push_all_issues": false,
"enabled": true,
"enable_engagement_epic_mapping": false,
"push_notes": false,
"product_jira_sla_notification": false,
Expand Down
12 changes: 9 additions & 3 deletions dojo/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -2422,7 +2422,7 @@ def clean(self):
return self.cleaned_data


class JIRAForm(BaseJiraForm):
class AdvancedJIRAForm(BaseJiraForm):
issue_template_dir = forms.ChoiceField(required=False,
choices=JIRA_TEMPLATE_CHOICES,
help_text="Choose the folder containing the Django templates used to render the JIRA issue description. These are stored in dojo/templates/issue-trackers. Leave empty to use the default jira_full templates.")
Expand All @@ -2442,8 +2442,11 @@ class Meta:
exclude = [""]


class ExpressJIRAForm(BaseJiraForm):
class JIRAForm(BaseJiraForm):
issue_key = forms.CharField(required=True, help_text="A valid issue ID is required to gather the necessary information.")
issue_template_dir = forms.ChoiceField(required=False,
choices=JIRA_TEMPLATE_CHOICES,
help_text="Choose the folder containing the Django templates used to render the JIRA issue description. These are stored in dojo/templates/issue-trackers. Leave empty to use the default jira_full templates.")

class Meta:
model = JIRA_Instance
Expand Down Expand Up @@ -2853,7 +2856,7 @@ class JIRAProjectForm(forms.ModelForm):
class Meta:
model = JIRA_Project
exclude = ["product", "engagement"]
fields = ["inherit_from_product", "jira_instance", "project_key", "issue_template_dir", "epic_issue_type_name", "component", "custom_fields", "jira_labels", "default_assignee", "add_vulnerability_id_to_jira_label", "push_all_issues", "enable_engagement_epic_mapping", "push_notes", "product_jira_sla_notification", "risk_acceptance_expiration_notification"]
fields = ["inherit_from_product", "jira_instance", "project_key", "issue_template_dir", "epic_issue_type_name", "component", "custom_fields", "jira_labels", "default_assignee", "enabled", "add_vulnerability_id_to_jira_label", "push_all_issues", "enable_engagement_epic_mapping", "push_notes", "product_jira_sla_notification", "risk_acceptance_expiration_notification"]

def __init__(self, *args, **kwargs):
from dojo.jira_link import helper as jira_helper
Expand Down Expand Up @@ -2891,6 +2894,7 @@ def __init__(self, *args, **kwargs):
self.fields["custom_fields"].disabled = False
self.fields["default_assignee"].disabled = False
self.fields["jira_labels"].disabled = False
self.fields["enabled"].disabled = False
self.fields["add_vulnerability_id_to_jira_label"].disabled = False
self.fields["push_all_issues"].disabled = False
self.fields["enable_engagement_epic_mapping"].disabled = False
Expand All @@ -2915,6 +2919,7 @@ def __init__(self, *args, **kwargs):
self.initial["custom_fields"] = jira_project_product.custom_fields
self.initial["default_assignee"] = jira_project_product.default_assignee
self.initial["jira_labels"] = jira_project_product.jira_labels
self.initial["enabled"] = jira_project_product.enabled
self.initial["add_vulnerability_id_to_jira_label"] = jira_project_product.add_vulnerability_id_to_jira_label
self.initial["push_all_issues"] = jira_project_product.push_all_issues
self.initial["enable_engagement_epic_mapping"] = jira_project_product.enable_engagement_epic_mapping
Expand All @@ -2930,6 +2935,7 @@ def __init__(self, *args, **kwargs):
self.fields["custom_fields"].disabled = True
self.fields["default_assignee"].disabled = True
self.fields["jira_labels"].disabled = True
self.fields["enabled"].disabled = True
self.fields["add_vulnerability_id_to_jira_label"].disabled = True
self.fields["push_all_issues"].disabled = True
self.fields["enable_engagement_epic_mapping"].disabled = True
Expand Down
2 changes: 1 addition & 1 deletion dojo/home/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ def dashboard(request: HttpRequest) -> HttpResponse:

date_range = [today - timedelta(days=6), today] # 7 days (6 days plus today)
finding_count = findings\
.filter(created__date__range=date_range)\
.filter(date__range=date_range)\
.count()
mitigated_count = findings\
.filter(mitigated__date__range=date_range)\
Expand Down
44 changes: 35 additions & 9 deletions dojo/jira_link/helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,11 +71,12 @@ def is_jira_configured_and_enabled(obj):
if not is_jira_enabled():
return False

if get_jira_project(obj) is None:
jira_project = get_jira_project(obj)
if jira_project is None:
logger.debug('JIRA project not found for: "%s" not doing anything', obj)
return False

return True
return jira_project.enabled


def is_push_to_jira(instance, push_to_jira_parameter=None):
Expand All @@ -88,6 +89,10 @@ def is_push_to_jira(instance, push_to_jira_parameter=None):
if push_to_jira_parameter is not None:
return push_to_jira_parameter

# Check to see if jira project is disabled to prevent pushing findings
if not jira_project.enabled:
return False

# push_to_jira was not specified, so look at push_all_issues in JIRA_Project
return jira_project.push_all_issues

Expand All @@ -96,8 +101,10 @@ def is_push_all_issues(instance):
if not is_jira_configured_and_enabled(instance):
return False

jira_project = get_jira_project(instance)
if jira_project:
if jira_project := get_jira_project(instance):
# Check to see if jira project is disabled to prevent pushing findings
if not jira_project.enabled:
return None
return jira_project.push_all_issues
return None

Expand All @@ -108,9 +115,13 @@ def is_push_all_issues(instance):
# returns True/False, error_message, error_code
def can_be_pushed_to_jira(obj, form=None):
# logger.debug('can be pushed to JIRA: %s', finding_or_form)
if not get_jira_project(obj):
jira_project = get_jira_project(obj)
if not jira_project:
return False, f"{to_str_typed(obj)} cannot be pushed to jira as there is no jira project configuration for this product.", "error_no_jira_project"

if not jira_project.enabled:
return False, f"{to_str_typed(obj)} cannot be pushed to jira as the jira project is not enabled.", "error_no_jira_project"

if not hasattr(obj, "has_jira_issue"):
return False, f"{to_str_typed(obj)} cannot be pushed to jira as there is no jira_issue attribute.", "error_no_jira_issue_attribute"

Expand Down Expand Up @@ -1389,6 +1400,13 @@ def add_comment(obj, note, force_push=False, **kwargs):

def add_simple_jira_comment(jira_instance, jira_issue, comment):
try:
jira_project = get_jira_project(jira_issue)

# Check to see if jira project is disabled to prevent pushing findings
if not jira_project.enabled:
log_jira_generic_alert("JIRA Project is disabled", "Push to JIRA for Epic skipped because JIRA Project is disabled")
return False

jira = get_jira_connection(jira_instance)

jira.add_comment(
Expand All @@ -1403,9 +1421,13 @@ def add_simple_jira_comment(jira_instance, jira_issue, comment):
def finding_link_jira(request, finding, new_jira_issue_key):
logger.debug("linking existing jira issue %s for finding %i", new_jira_issue_key, finding.id)

existing_jira_issue = jira_get_issue(get_jira_project(finding), new_jira_issue_key)

jira_project = get_jira_project(finding)
existing_jira_issue = jira_get_issue(jira_project, new_jira_issue_key)

# Check to see if jira project is disabled to prevent pushing findings
if not jira_project.enabled:
add_error_message_to_response("Push to JIRA for finding skipped because JIRA Project is disabled")
return False

if not existing_jira_issue:
raise ValueError("JIRA issue not found or cannot be retrieved: " + new_jira_issue_key)
Expand Down Expand Up @@ -1433,9 +1455,13 @@ def finding_link_jira(request, finding, new_jira_issue_key):
def finding_group_link_jira(request, finding_group, new_jira_issue_key):
logger.debug("linking existing jira issue %s for finding group %i", new_jira_issue_key, finding_group.id)

existing_jira_issue = jira_get_issue(get_jira_project(finding_group), new_jira_issue_key)

jira_project = get_jira_project(finding_group)
existing_jira_issue = jira_get_issue(jira_project, new_jira_issue_key)

# Check to see if jira project is disabled to prevent pushing findings
if not jira_project.enabled:
add_error_message_to_response("Push to JIRA for group skipped because JIRA Project is disabled")
return False

if not existing_jira_issue:
raise ValueError("JIRA issue not found or cannot be retrieved: " + new_jira_issue_key)
Expand Down
3 changes: 2 additions & 1 deletion dojo/jira_link/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
re_path(r"^jira/webhook/(?P<secret>[\w-]+)$", views.webhook, name="jira_web_hook_secret"),
re_path(r"^jira/webhook/", views.webhook, name="jira_web_hook"),
re_path(r"^jira/add", views.NewJiraView.as_view(), name="add_jira"),
re_path(r"^jira/advanced", views.AdvancedJiraView.as_view(), name="add_jira_advanced"),
re_path(r"^jira/(?P<jid>\d+)/edit$", views.EditJiraView.as_view(), name="edit_jira"),
re_path(r"^jira/(?P<tid>\d+)/delete$", views.DeleteJiraView.as_view(), name="delete_jira"),
re_path(r"^jira$", views.ListJiraView.as_view(), name="jira"),
re_path(r"^jira/express", views.ExpressJiraView.as_view(), name="express_jira")]
]
24 changes: 12 additions & 12 deletions dojo/jira_link/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
from dojo.authorization.authorization import user_has_configuration_permission

# Local application/library imports
from dojo.forms import DeleteJIRAInstanceForm, ExpressJIRAForm, JIRAForm
from dojo.forms import AdvancedJIRAForm, DeleteJIRAInstanceForm, JIRAForm
from dojo.models import JIRA_Instance, JIRA_Issue, Notes, System_Settings, User
from dojo.notifications.helper import create_notification
from dojo.utils import add_breadcrumb, add_error_message_to_response, get_setting
Expand Down Expand Up @@ -285,24 +285,24 @@ def get_custom_field(jira, label):
return field


class ExpressJiraView(View):
class NewJiraView(View):
def get_template(self):
return "dojo/express_new_jira.html"
return "dojo/new_jira.html"

def get_fallback_template(self):
return "dojo/new_jira.html"
return "dojo/new_jira_advanced.html"

def get_form_class(self):
return ExpressJIRAForm
return JIRAForm

def get_fallback_form_class(self):
return JIRAForm
return AdvancedJIRAForm

def get(self, request):
if not user_has_configuration_permission(request.user, "dojo.add_jira_instance"):
raise PermissionDenied
jform = self.get_form_class()()
add_breadcrumb(title="New Jira Configuration (Express)", top_level=False, request=request)
add_breadcrumb(title="New Jira Configuration", top_level=False, request=request)
return render(request, self.get_template(), {"jform": jform})

def post(self, request):
Expand Down Expand Up @@ -391,18 +391,18 @@ def post(self, request):
return render(request, self.get_template(), {"jform": jform})


class NewJiraView(View):
class AdvancedJiraView(View):
def get_template(self):
return "dojo/new_jira.html"
return "dojo/new_jira_advanced.html"

def get_form_class(self):
return JIRAForm
return AdvancedJIRAForm

def get(self, request):
if not user_has_configuration_permission(request.user, "dojo.add_jira_instance"):
raise PermissionDenied
jform = self.get_form_class()()
add_breadcrumb(title="New Jira Configuration", top_level=False, request=request)
add_breadcrumb(title="New Jira Configuration (Advanced)", top_level=False, request=request)
return render(request, self.get_template(), {"jform": jform})

def post(self, request):
Expand Down Expand Up @@ -442,7 +442,7 @@ def get_template(self):
return "dojo/edit_jira.html"

def get_form_class(self):
return JIRAForm
return AdvancedJIRAForm

def get(self, request, jid=None):
if not user_has_configuration_permission(request.user, "dojo.change_jira_instance"):
Expand Down
10 changes: 9 additions & 1 deletion dojo/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -3918,9 +3918,17 @@ class JIRA_Project(models.Model):
push_notes = models.BooleanField(default=False, blank=True)
product_jira_sla_notification = models.BooleanField(default=False, blank=True, verbose_name=_("Send SLA notifications as comment?"))
risk_acceptance_expiration_notification = models.BooleanField(default=False, blank=True, verbose_name=_("Send Risk Acceptance expiration notifications as comment?"))
enabled = models.BooleanField(
verbose_name=_("Enable Connection With Jira Project"),
help_text=_("When disabled, Findings will no longer be pushed to Jira, even if they have already been pushed previously."),
default=True,
blank=True)

def __str__(self):
return ("%s: " + self.project_key + "(%s)") % (str(self.id), str(self.jira_instance.url) if self.jira_instance else "None")
value = f"{self.id}: {self.project_key} ({self.jira_instance.url if self.jira_instance else 'None'})"
if not self.enabled:
value += " - Not Connected"
return value

def clean(self):
if not self.jira_instance:
Expand Down
2 changes: 1 addition & 1 deletion dojo/settings/.settings.dist.py.sha256sum
Original file line number Diff line number Diff line change
@@ -1 +1 @@
7ad5e28c5c96c6a3d40826bf32cea96c131825bd4eca857276b0458e26de36a3
4d3e91f176b73278750dc2f46d27cd4fe2b47d24682ad06d6267880bbdec599c
2 changes: 2 additions & 0 deletions dojo/settings/settings.dist.py
Original file line number Diff line number Diff line change
Expand Up @@ -1733,6 +1733,8 @@ def saml2_attrib_map_format(dict):
"RHEA": "https://access.redhat.com/errata/",
"FEDORA": "https://bodhi.fedoraproject.org/updates/",
"ALSA": "https://osv.dev/vulnerability/", # e.g. https://osv.dev/vulnerability/ALSA-2024:0827
"USN": "https://ubuntu.com/security/notices/", # e.g. https://ubuntu.com/security/notices/USN-6642-1
"DLA": "https://security-tracker.debian.org/tracker/", # e.g. https://security-tracker.debian.org/tracker/DLA-3917-1
}
# List of acceptable file types that can be uploaded to a given object via arbitrary file upload
FILE_UPLOAD_TYPES = env("DD_FILE_UPLOAD_TYPES")
Expand Down
4 changes: 2 additions & 2 deletions dojo/templates/base.html
Original file line number Diff line number Diff line change
Expand Up @@ -589,8 +589,8 @@
{% block support-tab %}
<li>
<a href="{% url 'support' %}" aria-disabled="true" aria-expanded="false" aria-label="Support">
<i class="fa-solid fa-life-ring fa-fw"></i>
<span>{% trans "Get Support" %}</span>
<i class="fa-solid fa-level-up fa-fw"></i>
<span>{% trans "Upgrade" %}</span>
</a>
</li>
{% endblock %}
Expand Down
16 changes: 0 additions & 16 deletions dojo/templates/dojo/express_new_jira.html

This file was deleted.

8 changes: 4 additions & 4 deletions dojo/templates/dojo/jira.html
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,13 @@ <h3 class="has-filters">
<ul class="dropdown-menu dropdown-menu-right" role="menu"
aria-labelledby="dropdownMenu1">
<li role="presentation">
<a href="{% url 'express_jira' %}">
<i class="fa-solid fa-plus"></i> Add Jira Instance (Express)
<a href="{% url 'add_jira' %}">
<i class="fa-solid fa-plus"></i> Add Jira Instance
</a>
</li>
<li role="presentation">
<a href="{% url 'add_jira' %}">
<i class="fa-solid fa-plus"></i> Add Jira Instance
<a href="{% url 'add_jira_advanced' %}">
<i class="fa-solid fa-plus"></i> Add Jira Instance (Advanced)
</a>
</li>
</ul>
Expand Down
Loading
Loading