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

Add patched package #436

Merged
merged 33 commits into from
Apr 22, 2021
Merged

Add patched package #436

merged 33 commits into from
Apr 22, 2021

Conversation

sbs2001
Copy link
Collaborator

@sbs2001 sbs2001 commented Apr 9, 2021

Fixes #375

I've done a terrible job at naming things here(see review comments), need help there.

We would want to move all the intermediate data structures to one place. That will be done in another PR.

See high level overview at #436 (comment)

@sbs2001 sbs2001 force-pushed the add-patched-pkg branch 4 times, most recently from c342565 to 25c6972 Compare April 12, 2021 06:22
@sbs2001 sbs2001 changed the title [WIP] Add patched package Add patched package Apr 19, 2021

# FIXME: The fixture code is duplicated. setUpClass is not working with the pytest mark.
@pytest.mark.django_db
class TestPackageRelatedVulnerablity(TestCase):
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@tdruez these are the tests

@@ -87,17 +88,16 @@ class Advisory:

summary: str
vulnerability_id: Optional[str] = None
impacted_package_urls: Iterable[PackageURL] = dataclasses.field(default_factory=list)
resolved_package_urls: Iterable[PackageURL] = dataclasses.field(default_factory=list)
affected_packages_with_patched_package: List[
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Name problem 1

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you survey the words use to depict affected/patched in other tools?

  • kaybee/vulas
  • dependencycheck and dependency track (and OWASP)
  • in general all the data source we use
    ...
    with these listed here we can make a good pick together!

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The general renaming should be tracked in a separate ticket IMHO, not here.

Beyond this, what about affected_packages or just impacted_packages?



@dataclasses.dataclass(order=True, frozen=True)
class AffectedPackageWithPatchedPackage:
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will be moved somewhere else in another PR

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use AffectedPackageWithPatch

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or just AffectedPackage ?

"""
Return True if the input 'string' contains any alphabet
"""
def nearest_patched_package(vulnerable_packages, resolved_packages):
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is where the magic happens, again it has poor naming. Help.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we will fix that in a separate ticket.

Copy link
Member

@pombredanne pombredanne left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some commits message is just "WIP"... may be there is a better message to reword? 👼

Copy link
Member

@pombredanne pombredanne left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!
We need to find better names alright and settle on this once and for all IMHO.
vulnerable/affected/resolved/patched are used and I feel we are not consistent.

Also can you explain the high level design here?

@@ -51,7 +51,7 @@ class PackageAdmin(admin.ModelAdmin):

@admin.register(PackageRelatedVulnerability)
class PackageRelatedVulnerabilityAdmin(admin.ModelAdmin):
list_filter = ("is_vulnerable", "package__type", "package__namespace")
list_filter = ("package__type", "package__namespace")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there anything that could replace is_vulnerable?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that should be patched_package adding it.

@@ -87,17 +88,16 @@ class Advisory:

summary: str
vulnerability_id: Optional[str] = None
impacted_package_urls: Iterable[PackageURL] = dataclasses.field(default_factory=list)
resolved_package_urls: Iterable[PackageURL] = dataclasses.field(default_factory=list)
affected_packages_with_patched_package: List[
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you survey the words use to depict affected/patched in other tools?

  • kaybee/vulas
  • dependencycheck and dependency track (and OWASP)
  • in general all the data source we use
    ...
    with these listed here we can make a good pick together!

is_cve = re.compile(r"CVE-\d{4}-\d{4,7}", re.IGNORECASE).match
def contains_alpha(string):
"""
Return True if the input 'string' contains any alphabet
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Return True if the input 'string' contains any alphabet
Return True if the input 'string' contains any alphanumeric character```

Return True if the input 'string' contains any alphabet
"""
def nearest_patched_package(vulnerable_packages, resolved_packages):
# This class is used to get around bisect module's lack of supplying custom
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be a docstring

)

resolved_package_count = len(resolved_packages)
affected_package_with_patched_package_objects = []
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why the _objects suffix?

Suggested change
affected_package_with_patched_package_objects = []
affected_package_with_patched_packages = []

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm aware of the principle of not specifying the type. The problem here is this list contains instances of AffectedPackageWithPatchedPackage . I don't know how to pluralise that,

affected_package_with_patched_packages -> is it one one affected package with multiple patched packages
affected_packages_with_patched_package -> vice versa

This is a mess :(

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Based on other review, affected_package would be a better name for now.

"data_source": "SUSEBackportsDataSource",
"data_source_cfg": {"url": "http://ftp.suse.com/pub/projects/security/yaml/", "etags": {}},
},
# {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this disabled?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We probably want to get rid of that importer, since it only contains (vulnerability, fixed/backported package)

@sbs2001
Copy link
Collaborator Author

sbs2001 commented Apr 20, 2021

@pombredanne here's a high level overview:

This PR removes the notion of resolved_package essentially only storing packages which are vulnerable. It also links these vulnerable packages with nearest(version-wise) package which is safe.

On a lower level, this required :

  1. Removing PackageRelatedVulnerability's is_vulnerable flag, since now we only store vulnerable packages primarily.

  2. Adding a field called patched_package to PackageRelatedVulnerability . This is a foreign key to the nearest(wrt PackageRelatedVulnerability.package version wise) safe package .

  3. Implementing a method called nearest_patched_package which accepts 2 lists of vulnerable packages and safe packages (wrt to some same vulnerablity) respectively. This method does the following:

a. Sort both the lists , ie the packages are now in ascending order wrt their versions. univers is used here.
b. Iterate over each vulnerable package, let's call the package being iterated pkg. For each pkg we find a package
which is just greater(version-wise ) than itself in the safe packages list. See the code here

c. If there exists such a package in (b) we bind this safe package with pkg by creating a AffectedPackageWithPatchedPackage instance

@sbs2001 sbs2001 force-pushed the add-patched-pkg branch 2 times, most recently from 39fe25b to efeea4f Compare April 21, 2021 06:27
Copy link
Member

@pombredanne pombredanne left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added a few more comments for your consideration and please merge.
Let's have a separate ticket for the naming issue.

@@ -87,17 +88,16 @@ class Advisory:

summary: str
vulnerability_id: Optional[str] = None
impacted_package_urls: Iterable[PackageURL] = dataclasses.field(default_factory=list)
resolved_package_urls: Iterable[PackageURL] = dataclasses.field(default_factory=list)
affected_packages_with_patched_package: List[
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The general renaming should be tracked in a separate ticket IMHO, not here.

Beyond this, what about affected_packages or just impacted_packages?



@dataclasses.dataclass(order=True, frozen=True)
class AffectedPackageWithPatchedPackage:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or just AffectedPackage ?

@dataclasses.dataclass(order=True, frozen=True)
class AffectedPackageWithPatchedPackage:
vulnerable_package: PackageURL
patched_package: Optional[PackageURL] = None
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about:

Suggested change
patched_package: Optional[PackageURL] = None
patched_version: Optional[str] = None

"""
Return True if the input 'string' contains any alphabet
"""
def nearest_patched_package(vulnerable_packages, resolved_packages):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we will fix that in a separate ticket.

# This class is used to get around bisect module's lack of supplying custom
# compartor. Get rid of this once we use python 3.10 which supports this.
# See https://github.com/python/cpython/pull/20556
class PackageURLWithVersionComparator:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you missing a @total_ordering there?

Also you should mention this is only to compare packages of the same type OR you could implement comparison and sorting across types.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You may want to check that the type/ns/name are the same too

)

resolved_package_count = len(resolved_packages)
affected_package_with_patched_package_objects = []
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Based on other review, affected_package would be a better name for now.

Notes about migrations :

 - Remove the is_vulnerable flag from PackageRelatedVulnerability model
 - Add the patched_package fk in PackageRelatedVulnerability model
 - Add data migrations to populate the patched_package

Signed-off-by: Shivam Sandbhor <[email protected]>
Signed-off-by: Shivam Sandbhor <[email protected]>
Signed-off-by: Shivam Sandbhor <[email protected]>
Signed-off-by: Shivam Sandbhor <[email protected]>
Signed-off-by: Shivam Sandbhor <[email protected]>
Signed-off-by: Shivam Sandbhor <[email protected]>
Signed-off-by: Shivam Sandbhor <[email protected]>
Signed-off-by: Shivam Sandbhor <[email protected]>
Signed-off-by: Shivam Sandbhor <[email protected]>
Signed-off-by: Shivam Sandbhor <[email protected]>
Signed-off-by: Shivam Sandbhor <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Get rid of bazillions of resolved/patched packages
2 participants