From 710f21ec537e9e9f80a42d0f19fe8c30af8af4b4 Mon Sep 17 00:00:00 2001 From: Leonardo de Oliveira Maia <101437950+LeoOMaia@users.noreply.github.com> Date: Mon, 23 Dec 2024 20:38:17 -0300 Subject: [PATCH] updating problem_id, filter problem and setting problem variable --- .../0219_problem_finding_problem.py | 4 +- dojo/models.py | 9 ++-- dojo/problem/helper.py | 41 +++++++++++-------- dojo/problem/update_mappings.py | 2 +- dojo/settings/settings.dist.py | 12 ++---- dojo/templates/base.html | 5 +++ .../templates/dojo/problems_list_snippet.html | 4 +- ...ent_total_script_id.py => problem_tags.py} | 7 +++- 8 files changed, 51 insertions(+), 33 deletions(-) rename dojo/templatetags/{get_different_total_script_id.py => problem_tags.py} (51%) diff --git a/dojo/db_migrations/0219_problem_finding_problem.py b/dojo/db_migrations/0219_problem_finding_problem.py index 5ac019f990..bd3055ec6f 100644 --- a/dojo/db_migrations/0219_problem_finding_problem.py +++ b/dojo/db_migrations/0219_problem_finding_problem.py @@ -1,4 +1,4 @@ -# Generated by Django 5.0.8 on 2024-12-22 19:33 +# Generated by Django 5.0.8 on 2024-12-23 22:35 import django.db.models.deletion from django.db import migrations, models @@ -16,7 +16,7 @@ class Migration(migrations.Migration): fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('name', models.CharField(help_text='A short name or title for the problem.', max_length=255, verbose_name='Name')), - ('problem_id', models.TextField(help_text='Problem identifier. This field is used to uniquely identify the problem.', verbose_name='Problem ID')), + ('problem_id', models.CharField(help_text='Problem identifier. This field is used to uniquely identify the problem.', max_length=255, unique=True, verbose_name='Problem ID')), ('created_at', models.DateTimeField(auto_now_add=True, help_text='Timestamp when this problem was created.', verbose_name='Created At')), ('updated_at', models.DateTimeField(auto_now=True, help_text='Timestamp when this problem was last updated.', verbose_name='Updated At')), ('severity', models.CharField(choices=[('Critical', 'Critical'), ('High', 'High'), ('Medium', 'Medium'), ('Low', 'Low'), ('Info', 'Info')], help_text='The severity level of this problem.', max_length=50, verbose_name='Severity')), diff --git a/dojo/models.py b/dojo/models.py index 6a3e7c09d0..e187a0699b 100644 --- a/dojo/models.py +++ b/dojo/models.py @@ -2261,9 +2261,12 @@ class Problem(models.Model): name = models.CharField(max_length=255, verbose_name=_("Name"), help_text=_("A short name or title for the problem.")) - problem_id = models.TextField( - verbose_name=_("Problem ID"), - help_text=_("Problem identifier. This field is used to uniquely identify the problem.")) + problem_id = models.CharField(max_length=255, + unique=True, + null=True, + blank=True, + verbose_name=_("Problem ID"), + help_text=_("Problem identifier. This field is used to uniquely identify the problem.")) created_at = models.DateTimeField(auto_now_add=True, verbose_name=_("Created At"), help_text=_("Timestamp when this problem was created.")) diff --git a/dojo/problem/helper.py b/dojo/problem/helper.py index 09c49a958b..72785ab4f4 100644 --- a/dojo/problem/helper.py +++ b/dojo/problem/helper.py @@ -36,14 +36,20 @@ def download_json(json_url): return response.json() def load_cached_json(): - try: - if os.path.exists(CACHED_JSON_FILE): + if os.path.exists(CACHED_JSON_FILE): + try: with open(CACHED_JSON_FILE, 'r') as f: data = json.load(f) if validate_json(data): return data - except (ValueError, json.JSONDecodeError): - pass + else: + logger.warning('Cached JSON failed validation.') + except json.JSONDecodeError: + logger.error('Error decoding JSON from cache.') + except Exception as e: + logger.error(f'Unexpected error loading JSON from cache: {e}') + else: + logger.info('Cached JSON file does not exist.') return None def save_json_to_cache(data): @@ -59,22 +65,26 @@ def mapping_script_problem_id(mappings_json_findings): } return script_to_problem_mapping -def load_json(check_cash=True): +def load_json(check_cache=True): try: - if check_cash: + if check_cache: cached_data = load_cached_json() if cached_data and validate_json(cached_data): return mapping_script_problem_id(cached_data) - data = download_json(settings.PROBLEM_MAPPINGS_JSON_URL) - if validate_json(data): - save_json_to_cache(data) - return mapping_script_problem_id(data) - - except (requests.RequestException, ValueError, json.JSONDecodeError) as e: - logger.error('Error loading disambiguator JSON: %s', e) - pass - + if settings.PROBLEM_MAPPINGS_JSON_URL: + data = download_json(settings.PROBLEM_MAPPINGS_JSON_URL) + if validate_json(data): + save_json_to_cache(data) + return mapping_script_problem_id(data) + else: + logger.error('No disambiguator JSON URL provided.') + except requests.RequestException as e: + logger.error('HTTP error while loading JSON: %s', e) + except json.JSONDecodeError as e: + logger.error('JSON decoding error: %s', e) + except Exception as e: + logger.error('Unexpected error: %s', e) return {} def find_or_create_problem(finding, script_to_problem_mapping): @@ -108,7 +118,6 @@ def _get_or_create_problem_by_script_id(finding): return Problem.objects.create( name=finding.title, - problem_id=finding.description, severity=finding.severity ) diff --git a/dojo/problem/update_mappings.py b/dojo/problem/update_mappings.py index e6d5816f17..f9c86f8400 100644 --- a/dojo/problem/update_mappings.py +++ b/dojo/problem/update_mappings.py @@ -14,4 +14,4 @@ @app.task def daily_cache_update(**kwargs): logger.info("Starting daily cache update") - load_json(check_cash=False) + load_json(check_cache=False) diff --git a/dojo/settings/settings.dist.py b/dojo/settings/settings.dist.py index 026c65ad1c..1a8195f43c 100644 --- a/dojo/settings/settings.dist.py +++ b/dojo/settings/settings.dist.py @@ -1748,14 +1748,10 @@ def saml2_attrib_map_format(dict): # see https://github.com/laymonage/django-jsonfield-backport SILENCED_SYSTEM_CHECKS = ["django_jsonfield_backport.W001"] -# Problem utilizes mappings from a JSON file to disambiguate Findings. -# The JSON file should have the following structure: -# { -# "problem_id_1": ["script_id_1", "script_id_2", "script_id_3"], -# "problem_id_2": ["script_id_4", "script_id_5"], -# "problem_id_3": ["script_id_6"] -# } -PROBLEM_MAPPINGS_JSON_URL = "https://homepages.dcc.ufmg.br/~leonardooliveira/disambiguator.json" +# By default, this mapping is not configured (set to None). If configured, it allows +# the "Problems" button to appear in Dojo's left toolbar. +# You can check more information in https://homepages.dcc.ufmg.br/~leonardooliveira/defectdojo/README.md +PROBLEM_MAPPINGS_JSON_URL = None VULNERABILITY_URLS = { "CVE": "https://nvd.nist.gov/vuln/detail/", diff --git a/dojo/templates/base.html b/dojo/templates/base.html index 76207b8253..6c2c5e945b 100644 --- a/dojo/templates/base.html +++ b/dojo/templates/base.html @@ -3,6 +3,7 @@ {% load authorization_tags %} {% load i18n %} {% load static %} +{% load problem_tags %}
@@ -325,6 +326,7 @@ + {% if None|check_problem_habilit %}