diff --git a/vulnerabilities/importers/__init__.py b/vulnerabilities/importers/__init__.py index c0cf04ed7..3668a7662 100644 --- a/vulnerabilities/importers/__init__.py +++ b/vulnerabilities/importers/__init__.py @@ -66,6 +66,9 @@ from vulnerabilities.pipelines.v2_importers import openssl_importer as openssl_importer_v2 from vulnerabilities.pipelines.v2_importers import oss_fuzz as oss_fuzz_v2 from vulnerabilities.pipelines.v2_importers import postgresql_importer as postgresql_importer_v2 +from vulnerabilities.pipelines.v2_importers import ( + postgresql_live_importer as postgresql_live_importer_v2, +) from vulnerabilities.pipelines.v2_importers import ( project_kb_msr2019_importer as project_kb_msr2019_importer_v2, ) @@ -196,3 +199,9 @@ for key, value in IMPORTERS_REGISTRY.items() if issubclass(value, VulnerableCodeBaseImporterPipelineV2) and value.exclude_from_package_todo ] + +LIVE_IMPORTERS_REGISTRY = create_registry( + [ + postgresql_live_importer_v2.PostgreSQLLiveImporterPipeline, + ] +) diff --git a/vulnerabilities/pipelines/v2_importers/postgresql_live_importer.py b/vulnerabilities/pipelines/v2_importers/postgresql_live_importer.py new file mode 100644 index 000000000..dab92163d --- /dev/null +++ b/vulnerabilities/pipelines/v2_importers/postgresql_live_importer.py @@ -0,0 +1,77 @@ +# +# Copyright (c) nexB Inc. and others. All rights reserved. +# VulnerableCode is a trademark of nexB Inc. +# SPDX-License-Identifier: Apache-2.0 +# See https://github.com/aboutcode-org/vulnerablecode for support or download. +# + +import logging +from typing import Iterable + +from packageurl import PackageURL +from univers.versions import InvalidVersion +from univers.versions import SemverVersion + +from vulnerabilities.importer import AdvisoryDataV2 +from vulnerabilities.pipelines.v2_importers.postgresql_importer import PostgreSQLImporterPipeline + +logger = logging.getLogger(__name__) + + +class PostgreSQLLiveImporterPipeline(PostgreSQLImporterPipeline): + """ + Live importer for PostgreSQL that filters the batch output to a single PURL. + """ + + pipeline_id = "postgresql_live_importer_v2" + supported_types = ["generic"] + + @classmethod + def steps(cls): + return ( + cls.get_purl_inputs, + cls.collect_and_store_advisories, + ) + + def get_purl_inputs(self): + purl = self.inputs.get("purl") + if not purl: + raise ValueError("PURL is required for PostgreSQLLiveImporterPipeline") + + if isinstance(purl, str): + purl = PackageURL.from_string(purl) + + if not isinstance(purl, PackageURL): + raise ValueError(f"Object of type {type(purl)} {purl!r} is not a PackageURL instance") + + if purl.type not in self.supported_types: + raise ValueError( + f"PURL: {purl!s} is not among the supported package types {self.supported_types!r}" + ) + + if not purl.version: + raise ValueError(f"PURL: {purl!s} is expected to have a version") + self.purl = purl + + def collect_advisories(self) -> Iterable[AdvisoryDataV2]: + for advisory in super().collect_advisories(): + if self._advisory_related_purl(advisory): + yield advisory + + def _advisory_related_purl(self, advisory: AdvisoryDataV2) -> bool: + if not advisory.affected_packages: + return False + + try: + package_version = SemverVersion(self.purl.version) + except InvalidVersion as e: + logger.debug(f"Invalid PURL version {self.purl.version!r}: {e}") + return False + + for ap in advisory.affected_packages: + if (ap.affected_version_range and package_version in ap.affected_version_range) or ( + ap.fixed_version_range and package_version in ap.fixed_version_range + ): + return True + + return False diff --git a/vulnerabilities/tests/pipelines/v2_importers/test_postgresql_live_importer_v2.py b/vulnerabilities/tests/pipelines/v2_importers/test_postgresql_live_importer_v2.py new file mode 100644 index 000000000..0fa111516 --- /dev/null +++ b/vulnerabilities/tests/pipelines/v2_importers/test_postgresql_live_importer_v2.py @@ -0,0 +1,115 @@ +# +# Copyright (c) nexB Inc. and others. All rights reserved. +# VulnerableCode is a trademark of nexB Inc. +# SPDX-License-Identifier: Apache-2.0 +# + +import pytest +import requests +from packageurl import PackageURL + +from vulnerabilities.pipelines.v2_importers.postgresql_live_importer import ( + PostgreSQLLiveImporterPipeline, +) + +HTML_BASE = """ + +
+|
+ CVE-2022-1234 + Announcement + |
+ {affected} | +{fixed} | +9.8 | +{summary} | +