diff --git a/docker-compose.yml b/docker-compose.yml index ada66ba1a57..19e475a6f34 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -57,6 +57,7 @@ services: - type: bind source: ./docker/extra_settings target: /app/docker/extra_settings + - "defectdojo_media:${DD_MEDIA_ROOT:-/app/media}" celerybeat: image: "defectdojo/defectdojo-django:${DJANGO_VERSION:-latest}" diff --git a/dojo/engagement/views.py b/dojo/engagement/views.py index 706210b569c..10708bccdae 100644 --- a/dojo/engagement/views.py +++ b/dojo/engagement/views.py @@ -360,7 +360,7 @@ def delete_engagement(request, eid): messages.SUCCESS, message, extra_tags="alert-success") - return HttpResponseRedirect(reverse("view_engagements", args=(product.id, ))) + return HttpResponseRedirect(reverse("view_product", args=(product.id, ))) rels = ["Previewing the relationships has been disabled.", ""] display_preview = get_setting("DELETE_PREVIEW") diff --git a/dojo/models.py b/dojo/models.py index 282a8c4d667..32375bdb058 100644 --- a/dojo/models.py +++ b/dojo/models.py @@ -1580,6 +1580,13 @@ def __str__(self): def get_absolute_url(self): return reverse("view_engagement", args=[str(self.id)]) + @property + def engagement_id(self): + try: + return f"ENG-{self.id:03d}" + except Exception: + return str(self.id) + def copy(self): copy = copy_model_util(self) # Save the necessary ManyToMany relationships diff --git a/dojo/settings/settings.dist.py b/dojo/settings/settings.dist.py index f13696c586b..ef02fc5defb 100644 --- a/dojo/settings/settings.dist.py +++ b/dojo/settings/settings.dist.py @@ -1846,6 +1846,10 @@ def saml2_attrib_map_format(din): # Maximum size of a scan file in MB SCAN_FILE_MAX_SIZE = env("DD_SCAN_FILE_MAX_SIZE") +# Engagement ID format +# Example: "ENG-{id:04d}" +ENGAGEMENT_ID_FORMAT = env("DD_ENGAGEMENT_ID_FORMAT", default="ENG-{id:04d}") + # Apply a severity level to "Security Weaknesses" in Qualys WAS QUALYS_WAS_WEAKNESS_IS_VULN = env("DD_QUALYS_WAS_WEAKNESS_IS_VULN") diff --git a/dojo/templates/dojo/engagement.html b/dojo/templates/dojo/engagement.html index 684b0777a73..cdda4bea561 100644 --- a/dojo/templates/dojo/engagement.html +++ b/dojo/templates/dojo/engagement.html @@ -4,202 +4,217 @@ {% load authorization_tags %} {% block content %} - {{ block.super }} -
-
-
-
-

- {{ view }} Engagements - +

+
+
+ {% include "dojo/filter_snippet.html" with form=filter_form %}
- {% if engagements %} +
+ {% if engagements %} -
- {% include "dojo/paging_snippet.html" with page=engagements page_size=True %} -
+
+ {% include "dojo/paging_snippet.html" with page=engagements page_size=True %} +
-
- - - - {% comment %} The display field is translated in the function. No need to translate here as well{% endcomment %} - - {% comment %} The display field is translated in the function. No need to translate here as well{% endcomment %} - - - {% comment %} The display field is translated in the function. No need to translate here as well{% endcomment %} - - {% comment %} The display field is translated in the function. No need to translate here as well{% endcomment %} - - {% comment %} The display field is translated in the function. No need to translate here as well{% endcomment %} - - - {% if system_settings.enable_jira %} - - {% endif %} - +
+
{% dojo_sort request 'Engagement' 'name' 'asc' %}{% dojo_sort request 'Period' 'target_start' 'asc' %}Status{% dojo_sort request labels.ASSET_LABEL 'product__name' 'asc' %}{% dojo_sort request labels.ORG_LABEL 'product__prod_type__name' %}{% dojo_sort request 'Lead' 'lead__first_name' %}TestsJira
+ + + {% comment %} The display field is translated in the function. No need to translate here as well{% endcomment %} + + + {% comment %} The display field is translated in the function. No need to translate here as well{% endcomment %} + + + {% comment %} The display field is translated in the function. No need to translate here as well{% endcomment %} + + {% comment %} The display field is translated in the function. No need to translate here as well{% endcomment %} + + {% comment %} The display field is translated in the function. No need to translate here as well{% endcomment %} + + + {% if system_settings.enable_jira %} + + {% endif %} + - {% for e in engagements %} - - - - - - - - - - {% if system_settings.enable_jira %} - - {% endif %} - - {% endfor %} -
ID{% dojo_sort request .Engagement. .name. .asc. %}{% dojo_sort request 'Period' 'target_start' 'asc' %}Status{% dojo_sort request labels.ASSET_LABEL 'product__name' 'asc' %}{% dojo_sort request labels.ORG_LABEL 'product__prod_type__name' %}{% dojo_sort request 'Lead' 'lead__first_name' %}TestsJira
-
-
- {% if e.name %}{{ e.name }}{% endif %} -
- {% include "dojo/snippets/tags.html" with tags=e.tags.all %} -
-
{{ e.target_start }} - {{ e.target_end }} - {% if e.is_overdue and e.status != 'Completed' %} - - {{ e.target_end|overdue }} overdue - - {% endif %} - {{ e.status }} - - {{ e.product.name }} - - {{ e.product|jira_project_tag }} - {% include "dojo/snippets/tags.html" with tags=e.product.tags.all %} - - - {{ e.product.prod_type.name }} - - {{ e.lead.first_name }} {{ e.lead.last_name }} - - {{ e.test_count|default:0 }} - - - {{ e|jira_project_tag }} -
-
-
- {% include "dojo/paging_snippet.html" with page=engagements page_size=True %} -
- {% else %} -
No active engagements
- {% endif %} + {% for e in engagements %} + + +
+ +
+ {% include "dojo/paging_snippet.html" with page=engagements page_size=True %}
+ {% else %} +
+
No active engagements
+
+ {% endif %}
+
{% endblock %} {% block postscript %} - {{ block.super }} - - + - {% include "dojo/filter_js_snippet.html" %} + +{% include "dojo/filter_js_snippet.html" %} {% endblock %} diff --git a/dojo/templates/dojo/engagements_all.html b/dojo/templates/dojo/engagements_all.html index ec31cefd2cd..ce4f4bceb4f 100644 --- a/dojo/templates/dojo/engagements_all.html +++ b/dojo/templates/dojo/engagements_all.html @@ -3,184 +3,196 @@ {% load display_tags %} {% load authorization_tags %} {% block content %} - {{ block.super }} -
-
-
-
-

- Engagements - -

-
-
- {% include "dojo/filter_snippet.html" with form=filter_form %} -
+{{ block.super }} +
+
+
+
+

+ Engagements + +

- {% if products %} +
+ {% include "dojo/filter_snippet.html" with form=filter_form %} +
+
+ {% if products %} -
- {% include "dojo/paging_snippet.html" with page=products page_size=True %} -
+
+ {% include "dojo/paging_snippet.html" with page=products page_size=True %} +
-
- - - - - - - - {% if system_settings.enable_jira %} - - {% endif %} - - - - - - - +
+
{{ labels.ASSET_LABEL }}{{ labels.ASSET_LABEL }}Engagement NameJIRAStatusPeriodLeadTestsEngagement
+ + + + + + + + {% if system_settings.enable_jira %} + + {% endif %} + + + + + + + - - {% for p in products %} - {% for e in p.engagement_set.all %} - - - - - - {% if system_settings.enable_jira %} - - {% endif %} - - + {% for p in products %} + {% for e in p.engagement_set.all %} + + - - - - + {% if e|has_object_permission:"Import_Scan_Result" %} +
  • + + Import Scan Results + +
  • + {% endif %} + +
  • + + View Active Findings + +
  • +
  • + + View Active and Verified Findings + +
  • +
  • + + View Mitigated Findings + +
  • +
  • + + View Accepted Findings + +
  • +
  • + + View All Findings + +
  • + +
  • + + Engagement Report + +
  • + {% if e|has_object_permission:"Engagement_Delete" %} + +
  • + + Delete Engagement + +
  • + {% endif %} + + + + + + + + + {% if system_settings.enable_jira %} + + {% endif %} + + + + + + - {% endfor %} - {% endfor %} - -
    {{ labels.ASSET_LABEL }}{{ labels.ASSET_LABEL }}Engagement NameJIRAStatusPeriodLeadTestsEngagement
    -
    -
    {{ p.name }} - {% include "dojo/snippets/tags.html" with tags=p.tags.all %} - - {{ p.prod_type.name }} - - {% if e.name %}{{ e.name }}{% endif %} - {% include "dojo/snippets/tags.html" with tags=e.tags.all %} -
    -
    - {{ e|jira_project_tag }} - {{ e.status }} {{ e.target_start }} - {{ e.target_end }} - {% if e.is_overdue and e.active and e.status != 'Completed' %} -
    {{ e.target_end|overdue }} overdue
    +
    + {{ e.lead.first_name }} {{ e.lead.last_name }} - - {{ e.test_count }} - - - {% if p|has_object_permission:"Engagement_Add" %} - - Add - + {% if e|has_object_permission:"Test_Add" %} +
  • + + Add Tests + +
  • {% endif %} -
    {{ p.name }} + {% include "dojo/snippets/tags.html" with tags=p.tags.all %} + + {{ p.prod_type.name }} + + {% if e.name %}{{ e.name }}{% + endif %} + {% include "dojo/snippets/tags.html" with tags=e.tags.all %} +
    +
    + {{ e|jira_project_tag }} + {{ e.status }} {{ e.target_start }} - {{ e.target_end }} + {% if e.is_overdue and e.active and e.status != 'Completed' %} + +
    {{ e.target_end|overdue }} overdue
    +
    + {% endif %} +
    {{ e.lead.first_name }} {{ e.lead.last_name }} + + {{ e.test_count }} + + + {% if p|has_object_permission:"Engagement_Add" %} + + Add + + {% endif %} +
    -
    -
    - {% include "dojo/paging_snippet.html" with page=products page_size=True %} -
    - {% else %} -
    No engagements found
    - {% endif %} + {% endfor %} + {% endfor %} + +
    +
    + {% include "dojo/paging_snippet.html" with page=products page_size=True %} +
    + {% else %} +
    +
    No engagements found
    +
    + {% endif %}
    +
    {% endblock %} {% block postscript %} - {{ block.super }} - - + - + - {% include "dojo/filter_js_snippet.html" %} -{% endblock %} + {% endif %} + }); + +{% include "dojo/filter_js_snippet.html" %} +{% endblock %} \ No newline at end of file diff --git a/dojo/templates/dojo/snippets/engagement_list.html b/dojo/templates/dojo/snippets/engagement_list.html index 757b6e222ef..75b6330f635 100644 --- a/dojo/templates/dojo/snippets/engagement_list.html +++ b/dojo/templates/dojo/snippets/engagement_list.html @@ -2,363 +2,379 @@ {% load display_tags %} {% load authorization_tags %}
    -
    -
    -

    {% if status == "open" %}Active{% elif status == "paused" %}Paused {% else %}Closed{% endif %} Engagements ({{ count }}) -

    +
    +
    + {% include "dojo/filter_snippet.html" with form=filter.form %} +
    -
    - {% include "dojo/paging_snippet.html" with page=engs prefix=prefix page_size=True %} -
    - {% if engs %} - - - - - - - - - - {% if system_settings.enable_jira %} - - {% endif %} - - - - - - - {% if status == "paused" or status == "closed" %} - - {% endif %} - - - - {% for eng in engs %} - - - - - - + + + + + + {% if status == "paused" or status == "closed" %} + + {% endif %} + {% endfor %} + +
    NameTypeLeadDateLengthJIRATestsActive (Verified / Fixable)MitigatedAcceptedAllDuplicatesStatus
    -
    -
    - - {{ eng.name|truncatechars_html:35|default:"N/A" }} - {% if eng.version %} - - - {{ eng.version }} - - {% endif %} - {% include "dojo/snippets/tags.html" with tags=eng.tags.all %} - {{ eng.engagement_type }} - {% if eng.lead.get_full_name and eng.lead.get_full_name.strip %} - {{ eng.lead.get_full_name }} - {% else %} - {{ eng.lead |default_if_none:""}} - {% endif %} - - - {{ eng.target_start|date:"jS F" }} {% if eng.target_start|datediff_time:eng.target_end != "1 day" %} - {{ eng.target_end|date:"jS F" }}{% endif %} +
    + {% include "dojo/paging_snippet.html" with page=engs prefix=prefix page_size=True %} +
    + {% if engs %} + + + + + + + + + + {% if system_settings.enable_jira %} + + {% endif %} + + + + + + + {% if status == "paused" or status == "closed" %} + + {% endif %} + + + + {% for eng in engs %} + + - - {% if system_settings.enable_jira %} - - {% endif %} - - - - - - - {% if status == "paused" or status == "closed" %} - + + + + + + {% if system_settings.enable_jira %} + + {% endif %} + - {% endif %} - {% endfor %} - -
    NameTypeLeadDateLengthJIRATestsActive (Verified / Fixable)MitigatedAcceptedAllDuplicatesStatus
    + {{ eng.target_start|datediff_time:eng.target_end }} - {% if status == "open" %} - {% if eng.is_overdue and eng.status != 'Completed' %} - -
    - {{ eng.target_end|overdue }} overdue -
    -
    - {% endif %} - {% if eng.count_tests == 0 %} -   -
    - no tests -
    -
    - {% endif %} - {% if eng.count_findings_all == 0 %} -   -
    - no findings -
    -
    - {% endif %} - {% endif %} -
    - {{ eng|jira_project_tag }} - - - {{ eng.count_findings_open }} ({{ eng.count_findings_open_verified}}/{{ eng.count_findings_fix_available}}){{ eng.count_findings_close }}{{ eng.count_findings_accepted }}{{ eng.count_findings_all }}{{ eng.count_findings_duplicate }} - {% if eng.status == "Blocked" %} - - {% elif eng.status == "On Hold" %} - + + +
  • + {% endif %} + {% if eng|has_object_permission:"Test_Add" %} +
  • + + Add Tests + +
  • + {% endif %} + {% if eng|has_object_permission:"Import_Scan_Result" %} +
  • + + Import Scan Results + +
  • + {% endif %} +
  • +
  • + + View Active Findings + +
  • +
  • + + View Active and Verified Findings + +
  • +
  • + + View Mitigated Findings + +
  • +
  • + + View Accepted Findings + +
  • +
  • + + View All Findings + +
  • +
  • +
  • + + Engagement Report + +
  • + {% if eng|has_object_permission:"Engagement_Delete" %} +
  • +
  • + + Delete Engagement + +
  • + {% endif %} + + + +
    + + {{ eng.name|truncatechars_html:35|default:"N/A" }} + {% if eng.version %} + + + {{ eng.version }} + + {% endif %} + {% include "dojo/snippets/tags.html" with tags=eng.tags.all %} + {{ eng.engagement_type }} + {% if eng.lead.get_full_name and eng.lead.get_full_name.strip %} + {{ eng.lead.get_full_name }} + {% else %} + {{ eng.lead |default_if_none:""}} + {% endif %} + + + {{ eng.target_start|date:"jS F" }} {% if eng.target_start|datediff_time:eng.target_end != "1 day" %} - {{ + eng.target_end|date:"jS F" }}{% endif %} + + {{ eng.target_start|datediff_time:eng.target_end }} + {% if status == "open" %} + {% if eng.is_overdue and eng.status != 'Completed' %} + +
    + {{ eng.target_end|overdue }} overdue +
    +
    + {% endif %} + {% if eng.count_tests == 0 %} +   +
    + no tests +
    +
    + {% endif %} + {% if eng.count_findings_all == 0 %} +   +
    + no findings +
    +
    + {% endif %} + {% endif %} +
    + {{ eng|jira_project_tag }} + +
    - {% else %} -
    + {% else %} + {{ eng.count_tests }} + {% endif %} - {% endif %} +
    {{ eng.count_findings_open }} ({{ + eng.count_findings_open_verified}}/{{ eng.count_findings_fix_available}}){{ eng.count_findings_close }}{{ eng.count_findings_accepted }}{{ eng.count_findings_all }}{{ eng.count_findings_duplicate }} + {% if eng.status == "Blocked" %} + + {% elif eng.status == "On Hold" %} + + {% else %} + + {% endif %} + {{ eng.status }} + +
    + {% else %} +
    +

    No {% if status == "open" %}active{% elif status == "paused" %}paused{% else %}closed{% + endif %} engagements found.

    +
    + {% endif %} -
    - {% include "dojo/paging_snippet.html" with page=engs prefix=prefix page_size=True %} -
    +
    + {% include "dojo/paging_snippet.html" with page=engs prefix=prefix page_size=True %}
    +
    {% block postscript %} - {% endblock %} + +{% endblock %} \ No newline at end of file diff --git a/dojo/templates/dojo/view_eng.html b/dojo/templates/dojo/view_eng.html index ab09dadb7c5..2a1b8d1ceb3 100644 --- a/dojo/templates/dojo/view_eng.html +++ b/dojo/templates/dojo/view_eng.html @@ -5,1084 +5,1148 @@ {% load authorization_tags %} {% load static %} {% block add_styles %} - .tooltip-inner { - max-width: 350px; - } +.tooltip-inner { +max-width: 350px; +} {% endblock %} {% block content %} -
    -
    -
    -
    -
    -

    - Description -

    - +
    +
    +
    + {% if eng.description %} + {{ eng.description|markdown_render }} + {% else %} + There is no description. + {% endif %} +
    +
    + {% if eng.preset %} +
    +
    +
    +
    +
    +

    + Engagement Presets {{ eng.preset.title|truncatechars_html:60 }} +

    + {% if eng.product|has_object_permission:"Product_Edit" %} + + {% endif %} +
    +
    +
    + + + + + + + + + + + + + +
    Test TypeNetwork
    + {% if preset_test_type.count > 1 %} + {% for test in preset_test_type %} + {{test.name}}{%if not forloop.last%},{%endif%} + {% endfor %} {% else %} - - Reopen Engagement - + {{ preset_test_type.0.name }} {% endif %} - - {% endif %} -
  • - - Report - -
  • -
  • - - Add To Calendar - -
  • -
  • - - View History - -
  • - {% if eng|has_object_permission:"Engagement_Edit" %} - -
  • - {% if eng.test_strategy %} - View Test - Strategy +
  • + {% if network.count > 1 %} + {% for net in network %} + {{ net.location }}{%if not forloop.last%},{%endif%} + {% endfor %} {% else %} - Add a Test Strategy + {{ network.0.location }} {% endif %} - - {% if threat != 'none' %} +
    +
    +
    + {% if eng.preset.notes %} + Notes: {{ eng.preset.notes|markdown_render }} + {% else %} + No test notes found. + {% endif %} + {% if eng.preset.scope %} + Scope: {{ eng.preset.scope|markdown_render }} + {% else %} + Testing scope not specified. + {% endif %} +
    +
    +
    +
    + {% endif %} +
    +
    +
    +
    +
    +

    + Tests ({{tests.paginator.count}}) {{ eng.id|get_severity_count:"engagement" }} + +

    -
    -
    - {% if eng.description %} - {{ eng.description|markdown_render }} - {% else %} - There is no description. - {% endif %} -
    -
    - {% if eng.preset %} -
    -
    -
    -
    -
    -

    - Engagement Presets {{ eng.preset.title|truncatechars_html:60 }} -

    - {% if eng.product|has_object_permission:"Product_Edit" %} -
    -
    -
    -
    -
    -

    Risk Acceptance - {% if eng.product.enable_full_risk_acceptance %} - {% if eng|has_object_permission:"Risk_Acceptance" %} - - +

    +
    +
    +
    +
    +

    Risk Acceptance + {% if eng.product.enable_full_risk_acceptance %} + {% if eng|has_object_permission:"Risk_Acceptance" %} + + + {% endif %} + {% endif %} +

    +
    + {% if risks_accepted %} +
    + + + + {% block risk_acceptance_header %} + + + + + + + + + + + {% endblock risk_acceptance_header %} + + + + {% for risk_acceptance in risks_accepted %} + + {% block risk_acceptances %} + + + + + + + + + {% if risk_acceptance.filename %} + + {% else %} + {% endif %} - {% endif %} - - - {% if risks_accepted %} + + {% endblock risk_acceptances %} + + {% endfor %} + +
    DateAccepted ByNameDecisionExpirationFindingsProofOwner
    +
      + +
    +
    {{ risk_acceptance.created|date }}{{ risk_acceptance.accepted_by }}{{ risk_acceptance.name }} + {{ risk_acceptance.get_decision_display|default_if_none:"" }} + {% if risk_acceptance.decision_details %} +   + {% endif %} + + {% if risk_acceptance.expiration_date %} + {{ risk_acceptance.expiration_date|date }} + {% else %} + Never + {% endif %} + {{ risk_acceptance.accepted_findings_count }}Yes +   + No{{ risk_acceptance.owner.get_full_name }}
    +
    + {% else %} +
    + No Risk Acceptances found. +
    + {% endif %} +
    +
    +
    + {% block global_risk_acceptances %}{% endblock %} +
    +
    +

    Additional Features + +

    +
    +
    + {% if eng.engagement_type == "Interactive" and system_settings.enable_checklists %} +
    +
    +

    Checklist +   + + + {% if eng|has_object_permission:"Engagement_Edit" %} + {% if check %} + + + {% else %} + + + {% endif %} + {% endif %} +

    +
    +
    + {% if check %} +
    - +
    - {% block risk_acceptance_header %} - - - - - - - - - - - {% endblock risk_acceptance_header %} + + + + + + + + - {% for risk_acceptance in risks_accepted %} - - {% block risk_acceptances %} - - - - - - - - - {% if risk_acceptance.filename %} - - {% else %} - - {% endif %} - - {% endblock risk_acceptances %} - - {% endfor %} + + + + + + + + + +
    DateAccepted ByNameDecisionExpirationFindingsProofOwnerSessionEncryptionConfigurationAuthenticationAuthorizationData InputSensitive DataOther
    -
      - -
    -
    {{ risk_acceptance.created|date }}{{ risk_acceptance.accepted_by }}{{ risk_acceptance.name }} - {{ risk_acceptance.get_decision_display|default_if_none:"" }} - {% if risk_acceptance.decision_details %} -   - {% endif %} - - {% if risk_acceptance.expiration_date %} - {{ risk_acceptance.expiration_date|date }} - {% else %} - Never - {% endif %} - {{ risk_acceptance.accepted_findings_count }}Yes -   - No{{ risk_acceptance.owner.get_full_name }}
    {{ check.session_management }}{{ check.encryption_crypto }}{{ check.configuration_management }}{{ check.authentication }}{{ check.authorization_and_access_control }}{{ check.data_input_sanitization_validation }}{{ check.sensitive_data }}{{ check.other }}
    +
    {% else %} +
    - No Risk Acceptances found. + Checklist has not been completed.
    +
    {% endif %}
    -
    - {% block global_risk_acceptances %}{% endblock %} -
    -
    -

    Additional Features - -

    -
    -
    - {% if eng.engagement_type == "Interactive" and system_settings.enable_checklists %} -
    -
    -

    Checklist -   - + {% endif %} + {% if system_settings.enable_questionnaires %} +
    +
    +

    Questionnaires +   + - {% if eng|has_object_permission:"Engagement_Edit" %} - {% if check %} - - - {% else %} - - - {% endif %} - {% endif %} -

    + {% if eng|has_object_permission:"Engagement_Edit" %} + {% add_surveys eng %} + {% endif %} +

    +
    +
    +
    +
    +
    + {% show_surveys eng users %} +
    -
    - {% if check %} -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - - -
    SessionEncryptionConfigurationAuthenticationAuthorizationData InputSensitive DataOther
    {{ check.session_management }}{{ check.encryption_crypto }}{{ check.configuration_management }}{{ check.authentication }}{{ check.authorization_and_access_control }}{{ check.data_input_sanitization_validation }}{{ check.sensitive_data }}{{ check.other }}
    + - {% endif %} - {% if system_settings.enable_questionnaires %} +
    +
    + {% endif %} +
    +
    +

    Notes + + +

    +
    +
    + {% if eng|has_object_permission:"Note_Add" %} +
    + {% csrf_token %} + {% include "dojo/form_fields.html" with form=form %} +
    +
    + +
    +
    +
    + {% endif %}
    -

    Questionnaires -   - - - {% if eng|has_object_permission:"Engagement_Edit" %} - {% add_surveys eng %} - {% endif %} +

    Note Log + +

    -
    -
    -
    -
    - {% show_surveys eng users %} -
    -
    -