Skip to content

Commit

Permalink
Explore context and Package class approaches for affected-fixed packa…
Browse files Browse the repository at this point in the history
…ge matching #1228

Reference: #1228

Note that my updated code is still in testing/dev stage and has not yet been completed or cleaned.

Signed-off-by: John M. Horan <[email protected]>
  • Loading branch information
johnmhoran committed Jul 28, 2023
1 parent 1e4079d commit 624f047
Show file tree
Hide file tree
Showing 3 changed files with 221 additions and 28 deletions.
80 changes: 68 additions & 12 deletions vulnerabilities/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
from django.core.validators import MinValueValidator
from django.db import models
from django.db.models import Count
from django.db.models import Prefetch
from django.db.models import Q
from django.db.models.functions import Length
from django.db.models.functions import Trim
Expand Down Expand Up @@ -588,18 +589,6 @@ def affected_by(self):
# legacy aliases
vulnerable_to = affected_by

@property
def test_get_fixing_purls(self):
"""
This is a test -- the goal is to display the closest fixing version for a PURL that is greater
than the affected version and is the same type. We want to filter on type, namespace,
name, qualifiers and subpath for the affected PURL.
"""
return [
abc.fixed_by_packages
for abc in self.vulnerabilities.filter(packagerelatedvulnerability__fix=False)
]

@property
# TODO: consider renaming to "fixes" or "fixing" ? (TBD) and updating the docstring
def fixing(self):
Expand Down Expand Up @@ -631,6 +620,73 @@ def get_absolute_url(self):
"""
return reverse("package_details", args=[self.purl])

def get_fixed_packages(self, package):
"""
Return a queryset of all packages that fix a vulnerability with
same type, namespace, name, subpath and qualifiers of the `package`
"""
return Package.objects.filter(
name=package.name,
namespace=package.namespace,
type=package.type,
qualifiers=package.qualifiers,
subpath=package.subpath,
packagerelatedvulnerability__fix=True,
).distinct()

@property
def test_get_fixing_purls(self):
"""
This is a test -- the goal is to display the closest fixing version for a PURL that is greater
than the affected version and is the same type. We want to filter on type, namespace,
name, qualifiers and subpath for the affected PURL.
"""

fixed_packages = self.get_fixed_packages(package=self)

# Prefetch:

# Where do we get "fix" from?
# qs = self.vulnerabilities.filter(packagerelatedvulnerability__fix=fix)

# Not clear to me how we use this:
# qs = qs.prefetch_related(
# Prefetch(
# "packages",
# queryset=fixed_packages,
# to_attr="filtered_fixed_packages",
# )
# )

matching_fixed_packages = []

# closest_subsequent_fixed_package = []

test_dict = {"affected_purl": self.purl}
test_dict["vulnerabilities"] = []

for vuln in self.affected_by:
test_dict["vulnerabilities"].append({"vulnerability": vuln.vulnerability_id})

for fixing_pkg in vuln.fixed_by_packages:
# Do not add "backports". TODO: Do we need to use univers to compare versions?
if fixing_pkg in fixed_packages and fixing_pkg.version > self.version:
matching_fixed_packages.append(fixing_pkg)

# TODO: We also need to check if there is more than one fixing package and if so, keep only the package closest to the affect package's version.
# TODO: Do we want to check whether the fixing version has any vulnerabilities of its own?

# ========================================================
print("\ntest_dict = \n{}\n".format(test_dict))
print(json.dumps(test_dict, indent=4))
# ========================================================

return matching_fixed_packages


# 2023-07-27 Thursday 09:50:45. JMH: check this out re related api.py code
# TODO: Not clear how this is involved.


class PackageRelatedVulnerability(models.Model):
"""
Expand Down
134 changes: 118 additions & 16 deletions vulnerabilities/templates/package_details.html
Original file line number Diff line number Diff line change
Expand Up @@ -43,52 +43,131 @@
<div class="content ml-3 mr-3" style="background-color: #f8f8f8; padding: 10px; border: solid 1px #d8d8d8; border-radius: 5px;">
<span style="font-weight: 700; color: #0066ff;">Let's try to display fixing packages for this package: {{ package.purl }}</span>
<div style="padding: 5px 0px;">
<span style="font-weight: 700; color: #cc0099;">package.purl</span> = {{ package.purl }}
<span style="font-weight: 700; color: #996633;">package.purl</span> = {{ package.purl }}
</div>
<div style="padding: 5px 0px;">
<span style="font-weight: 700; color: #cc0099;">package.qualifiers</span> = {{ package.qualifiers }}
<span style="font-weight: 700; color: #996633;">package.qualifiers</span> = {{ package.qualifiers }}
</div>
<div style="padding: 5px 0px;">
<span style="font-weight: 700; color: #cc0099;">package.vulnerabilities</span> = {{ package.vulnerabilities }}
<span style="font-weight: 700; color: #996633;">package.vulnerabilities</span> = {{ package.vulnerabilities }}
</div>
<div style="padding: 5px 0px;">
<span style="font-weight: 700; color: #cc0099;">package.package_url</span> = {{ package.package_url }}
<span style="font-weight: 700; color: #996633;">package.package_url</span> = {{ package.package_url }}
</div>
<div style="padding: 5px 0px;">
<span style="font-weight: 700; color: #cc0099;">package.plain_package_url</span> = {{ package.plain_package_url }}
<span style="font-weight: 700; color: #996633;">package.plain_package_url</span> = {{ package.plain_package_url }}
</div>
<div style="padding: 5px 0px;">
<span style="font-weight: 700; color: #cc0099;">package.purl_object</span> = {{ package.purl_object }}
<span style="font-weight: 700; color: #996633;">package.purl_object</span> = {{ package.purl_object }}
</div>

<div style="padding: 5px 0px;">
<span style="font-weight: 700; color: #cc0099;">package.fixing</span> = {{ package.fixing }}
<span style="font-weight: 700; color: #996633;">package.fixing</span> = {{ package.fixing }}
</div>
<div style="padding: 5px 0px;">
<span style="font-weight: 700; color: #cc0099;">package.fixed_packages</span> = <span class="inline-code">Server Error (500)</span>
<span style="font-weight: 700; color: #996633;">package.fixed_packages</span> = <span class="inline-code">Server Error (500)</span>
</div>
<div style="padding: 5px 0px;">
<span style="font-weight: 700; color: #cc0099;">package.is_vulnerable</span> = {{ package.is_vulnerable }}
<span style="font-weight: 700; color: #996633;">package.is_vulnerable</span> = {{ package.is_vulnerable }}
</div>
<div style="padding: 5px 0px;">
<span style="font-weight: 700; color: #cc0099;">package.get_absolute_url</span> = {{ package.get_absolute_url }}
<span style="font-weight: 700; color: #996633;">package.get_absolute_url</span> = {{ package.get_absolute_url }}
</div>

<div style="padding: 5px 0px;">
<span style="font-weight: 700; color: #cc0099;">package.affected_by</span> = {{ package.affected_by }}
<span style="font-weight: 700; color: #996633;">package.affected_by</span> = {{ package.affected_by }}
</div>

<div style="padding: 5px 0px;">
<span style="font-weight: 700; color: #996633;">package.test_get_fixing_purls</span> = {{ package.test_get_fixing_purls }}
</div>

<div style="padding: 5px 0px;">
<span style="font-weight: 700; color: #cc0099;">package.test_get_fixing_purls</span> = {{ package.test_get_fixing_purls }}
<span style="font-weight: 700; color: #996633;">package.test_get_fixing_purls</span> = {{ package.test_get_fixing_purls }}
</div>

{% for abc in package.affected_by %}

<div style="padding: 5px 0px;"><span style="font-weight: 700; color: #cc0099;">{{ abc }}</span> -- {{ abc.fixed_by_packages }}</div>
<div style="padding: 5px 0px;"><span style="font-weight: 700; color: #cc0099;">{{ abc }}</span> -- {% for pkg in abc.fixed_by_packages %}{{ pkg.purl }}{% endfor %}</div>
<div style="padding: 5px 0px;"><span style="font-weight: 700; color: #996633;">{{ abc }}</span> -- {{ abc.fixed_by_packages }}</div>
<div style="padding: 5px 0px;"><span style="font-weight: 700; color: #996633;">{{ abc }}</span> -- {% for pkg in abc.fixed_by_packages %}{{ pkg.purl }}{% endfor %}</div>

{% endfor %}

<div style="padding: 5px 0px; font-weight: 700; color: #008888;">abc.test_matching_fixed_by_packages</div>
{% for abc in package.affected_by %}

<!-- <div style="padding: 5px 0px;">
<span style="font-weight: 700; color: #008888;"">{{ abc }}</span> -- {{ abc.test_matching_fixed_by_packages }}
</div> -->

<div style="padding: 5px 0px;"><span style="font-weight: 700; color: #008888;">{{ abc }}</span> --
{% for pkg in abc.test_matching_fixed_by_packages %}
<div style="padding: 5px 0px;">{{ pkg.purl }}</div>
{% endfor %}
</div>

{% endfor %}

<div>
<div style="font-weight: 700; color: #ff0000;">test01</div>
{% for thing in test01 %}
{{ thing }}
<br />
{% endfor %}
</div>

<div>
<div style="font-weight: 700; color: #ff0000;">test02</div>
{% for thing in test02 %}
- {{ thing }}
<br />
{% endfor %}
</div>

<div>
<div style="font-weight: 700; color: #ff0000;">test03</div>
{% for thing in test03 %}
- {{ thing }}
<br />
{% for stuff in thing.test_matching_fixed_by_packages %}
==> {{ stuff }}
<br />
{% endfor %}
<br />
{% endfor %}
</div>

<div>
<div style="font-weight: 700; color: #009933;">test04</div>
{% for thing in test04 %}
<span style="color: #009933;">- {{ thing }}</span>
<br />
{% endfor %}
</div>

<div style="padding: 10px 0px;">
<!-- The next div formerly was named "test05 -- test_get_fixing_purls" -->
<div style="font-weight: 700; color: #cc0099;">context["test_get_fixing_purls"]</div>
{% for thing in test_get_fixing_purls %}
<span style="color: #cc0099;">- {{ thing }}</span>
<br />
{% endfor %}

{% for vulnerability in affected_by_vulnerabilities %}
<div style="color: #cc0099; font-weight: 700; margin-left: 10px;">
{{ vulnerability }}
</div>
<div style="margin-left: 20px;">
{% for pkg in vulnerability.fixed_by_packages %}
{% if pkg in test_get_fixing_purls %}
<div style="padding: 0px 0px 5px 0px; line-height: 18px;">
<span style="color: #cc0099;">{{ pkg.purl }}</span>
</div>
{% endif %}
{% endfor %}
</div>
{% endfor %}
</div>

</div>

Expand All @@ -103,7 +182,7 @@
<th style="width: 175px;">Vulnerability</th>
<th>Summary</th>
<th style="width: 225px;">Aliases</th>
<th style="color: #ff0000;">Test fixing PURLs</th>
<th style="color: #ff0000;">Fixing Packages</th>
</tr>
</thead>

Expand Down Expand Up @@ -131,8 +210,31 @@
<!-- {{ vulnerability.fixed_by_packages }} -->
<!-- <br /> -->
{% for pkg in vulnerability.fixed_by_packages %}
{{ pkg.purl }}
<div style="font-size: 14px; padding: 0px 0px 5px 0px; line-height: 18px;">
{{ pkg.purl }}
</div>
{% endfor %}

<hr style="border-top: solid 1px #000000;">

{% for pkg in vulnerability.fixed_by_packages %}
{% if pkg in test04 %}
<div style="font-size: 14px; padding: 0px 0px 5px 0px; line-height: 18px;">
<span style="color: #009933;">{{ pkg.purl }}</span>
</div>
{% endif %}
{% endfor %}

<hr style="border-top: solid 1px #000000;">

{% for pkg in vulnerability.fixed_by_packages %}
{% if pkg in test_get_fixing_purls %}
<div style="font-size: 14px; padding: 0px 0px 5px 0px; line-height: 18px;">
<span style="color: #cc0099;">{{ pkg.purl }}</span>
</div>
{% endif %}
{% endfor %}

</td>
</tr>
{% empty %}
Expand Down
35 changes: 35 additions & 0 deletions vulnerabilities/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,41 @@ def get_context_data(self, **kwargs):
context["affected_by_vulnerabilities"] = package.affected_by.order_by("vulnerability_id")
context["fixing_vulnerabilities"] = package.fixing.order_by("vulnerability_id")
context["package_search_form"] = PackageSearchForm(self.request.GET)
context["test01"] = [
"aaa",
"bbb",
"ccc",
]
context["test02"] = [
package,
package.type,
package.namespace,
package.name,
package.version,
package.qualifiers,
package.subpath,
]
context["test03"] = package.affected_by

# ========================================================
context["test04"] = [
fixing_pkg
for vuln in package.affected_by
# for fixing_pkg in vuln.test_matching_fixed_by_packages
for fixing_pkg in vuln.fixed_by_packages
if fixing_pkg.type == package.type
and fixing_pkg.namespace == package.namespace
and fixing_pkg.name == package.name
and fixing_pkg.qualifiers == package.qualifiers
and fixing_pkg.subpath == package.subpath
# I think this version comparison requires the use of univers.
# Plus we just need the closest one, not all that are greater than.
and fixing_pkg.version > package.version
]
# ========================================================
context["test_get_fixing_purls"] = package.test_get_fixing_purls
# ========================================================

return context

def get_object(self, queryset=None):
Expand Down

0 comments on commit 624f047

Please sign in to comment.