Skip to content

Commit

Permalink
Add is_reachable field on the VulnerabilityAnalysis model #103
Browse files Browse the repository at this point in the history
Signed-off-by: tdruez <[email protected]>
  • Loading branch information
tdruez committed Dec 9, 2024
1 parent 9eb7fb7 commit e335a16
Show file tree
Hide file tree
Showing 9 changed files with 87 additions and 6 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,11 @@ Release notes
Add `risk_score` filter in Package endpoint.
https://github.com/aboutcode-org/dejacode/issues/104

- Add new `is_reachable` field on the VulnerabilityAnalysis model.
It can be used to declare if a this vulnerability is reachable, not reachable, or
if this fact is not known in the context of a Product Package.
https://github.com/aboutcode-org/dejacode/issues/103

### Version 5.2.1

- Fix the models documentation navigation.
Expand Down
17 changes: 12 additions & 5 deletions dejacode/static/css/dejacode_bootstrap.css
Original file line number Diff line number Diff line change
Expand Up @@ -388,16 +388,16 @@ table.vulnerabilities-table .column-summary {
width: 210px;
}
#tab_vulnerabilities .column-affected_packages {
min-width: 300px;
min-width: 250px;
}
#tab_vulnerabilities .column-exploitability {
width: 155px;
width: 140px;
}
#tab_vulnerabilities .column-weighted_severity {
width: 120px;
width: 105px;
}
#tab_vulnerabilities .column-risk_score {
width: 90px;
width: 80px;
}
#tab_vulnerabilities .column-summary {
width: 300px;
Expand All @@ -411,6 +411,9 @@ table.vulnerabilities-table .column-summary {
#tab_vulnerabilities .column-vulnerability_analyses__responses {
min-width: 120px;
}
#tab_vulnerabilities .column-vulnerability_analyses__is_reachable {
min-width: 80px;
}
/* -- Vulnerability analysis modal -- */
#vulnerability-analysis-modal #div_id_responses .form-check {
display: inline-block;
Expand Down Expand Up @@ -655,11 +658,15 @@ td.sub-header {
.table thead tr th a.sort:hover {
color: #ccc;
text-decoration: none;
margin-left: 0.0625rem;
margin-left: 0;
}
.table thead tr th a.sort.active {
color: var(--bs-body-color);
}
.tab-content .table thead tr th {
font-size: 0.875rem;
}
th a.sort i {width: auto;}

/* -- Better looks for the popover fake links -- */
.tag_popover,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
{% load i18n %}
{% load as_icon from dje_tags %}

{% include 'tabs/pagination.html' %}
<table class="table table-bordered table-md text-break">
{% include 'includes/object_list_table_header.html' with filter=filterset include_actions=True %}
Expand Down Expand Up @@ -72,6 +74,13 @@
</ul>
{% endif %}
</td>
<td class="text-center">
{% if package.vulnerability_analysis.is_reachable %}
<i class="fa-solid fa-circle-radiation text-danger fs-5" data-bs-toggle="tooltip" title="Vulnerability is reachable"></i>
{% elif package.vulnerability_analysis.is_reachable is False %}
<i class="fa-solid fa-bug-slash" data-bs-toggle="tooltip" title="Vulnerability is NOT reachable"></i>
{% endif %}
</td>
<td class="p-1">
<span data-bs-toggle="modal"
data-bs-target="#vulnerability-analysis-modal"
Expand Down
9 changes: 9 additions & 0 deletions product_portfolio/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -1138,6 +1138,15 @@ class ProductTabVulnerabilitiesView(
),
filter="responses",
),
Header(
"vulnerability_analyses__is_reachable",
_("Reach"),
help_text=_(
"Indicates whether the vulnerability is reachable in the context of "
"this product package."
),
filter="is_reachable",
),
)

def get_context_data(self, **kwargs):
Expand Down
1 change: 1 addition & 0 deletions vulnerabilities/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ class Meta:
"justification",
"responses",
"detail",
"is_reachable",
)
extra_kwargs = {
"product_package": {
Expand Down
12 changes: 12 additions & 0 deletions vulnerabilities/filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

import django_filters

from dje.filters import BooleanChoiceFilter
from dje.filters import DataspacedFilterSet
from dje.filters import SearchFilter
from dje.widgets import SortDropDownWidget
Expand Down Expand Up @@ -122,6 +123,7 @@ class ProductVulnerabilityFilterSet(VulnerabilityFilterSet):
"vulnerability_analyses__state",
"vulnerability_analyses__justification",
"responses",
"is_reachable",
]
sort = NullsLastOrderingFilter(
label=_("Sort"),
Expand All @@ -139,13 +141,23 @@ class ProductVulnerabilityFilterSet(VulnerabilityFilterSet):
lookup_expr="icontains",
choices=VulnerabilityAnalysisMixin.Response.choices,
)
is_reachable = BooleanChoiceFilter(
field_name="vulnerability_analyses__is_reachable",
empty_label="All",
choices=(
("yes", _("Reachable")),
("no", _("Not reachable")),
("unknown", _("Reachability not known")),
),
)

class Meta:
model = Vulnerability
fields = [
"q",
"vulnerability_analyses__state",
"vulnerability_analyses__justification",
"is_reachable",
"exploitability",
]

Expand Down
3 changes: 2 additions & 1 deletion vulnerabilities/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ class Meta:
"justification",
"responses",
"detail",
"is_reachable",
"propagate_to_products",
]
widgets = {
Expand Down Expand Up @@ -84,7 +85,7 @@ def helper(self):
"",
"product_package",
"vulnerability",
Group("state", "justification"),
Group("state", "justification", "is_reachable"),
"responses",
"detail",
Field(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Generated by Django 5.0.9 on 2024-12-09 14:03

from django.conf import settings
from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('component_catalog', '0010_component_risk_score_package_risk_score'),
('dje', '0004_dataspace_vulnerabilities_updated_at'),
('product_portfolio', '0008_productdependency_is_resolved_to_is_pinned'),
('vulnerabilities', '0004_vulnerabilityanalysis_indexes'),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]

operations = [
migrations.AddField(
model_name='vulnerabilityanalysis',
name='is_reachable',
field=models.BooleanField(help_text='Indicates whether the vulnerability is reachable in the context of this product package.', null=True),
),
migrations.AddIndex(
model_name='vulnerabilityanalysis',
index=models.Index(fields=['is_reachable'], name='vulnerabili_is_reac_4ae33a_idx'),
),
]
10 changes: 10 additions & 0 deletions vulnerabilities/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -502,12 +502,21 @@ class VulnerabilityAnalysis(
on_delete=models.CASCADE,
related_name="vulnerability_analyses",
)
# Regular fields
is_reachable = models.BooleanField(
null=True,
help_text=_(
"Indicates whether the vulnerability is reachable in the context of this "
"product package."
),
)

class Meta:
unique_together = (("product_package", "vulnerability"), ("dataspace", "uuid"))
indexes = [
models.Index(fields=["state"]),
models.Index(fields=["justification"]),
models.Index(fields=["is_reachable"]),
]

def __str__(self):
Expand Down Expand Up @@ -556,6 +565,7 @@ def propagate(self, product_uuid, user):
"justification",
"responses",
"detail",
"is_reachable",
]
for field_name in fields_to_clone:
field_value = getattr(self, field_name, None)
Expand Down

0 comments on commit e335a16

Please sign in to comment.