Skip to content

Commit 85d58ff

Browse files
committed
Fix LaunchPadVersionAPI
Signed-off-by: Tushar Goel <tushar.goel.dav@gmail.com>
1 parent dd5fa5a commit 85d58ff

3 files changed

Lines changed: 91 additions & 30 deletions

File tree

vulnerabilities/improvers/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@
1717
importers.github.GitHubBasicImprover,
1818
importers.debian.DebianBasicImprover,
1919
importers.gitlab.GitLabBasicImprover,
20-
oval.OvalBasicImprover,
20+
oval.DebianOvalBasicImprover,
21+
oval.UbuntuOvalBasicImprover,
2122
]
2223

2324
IMPROVERS_REGISTRY = {x.qualified_name: x for x in IMPROVERS_REGISTRY}

vulnerabilities/improvers/oval.py

Lines changed: 87 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -35,36 +35,36 @@
3535
}
3636

3737

38-
class OvalBasicImprover(Improver):
38+
def get_package_versions(
39+
package_url: PackageURL,
40+
until: Optional[datetime] = None,
41+
versions_fetcher_by_purl: Mapping[PackageURL, VersionAPI] = {},
42+
) -> List[str]:
43+
"""
44+
Return a list of `valid_versions` for the `package_url`
45+
"""
46+
api_name = get_api_package_name(package_url)
47+
if not api_name:
48+
logger.error(f"Could not get versions for {package_url!r}")
49+
return []
50+
versions_fetcher = versions_fetcher_by_purl.get(package_url)
51+
if not versions_fetcher:
52+
versions_fetcher: VersionAPI = VERSION_API_CLASS_BY_NAMESPACE[package_url.namespace]
53+
versions_fetcher_by_purl[package_url] = versions_fetcher()
54+
55+
versions_fetcher = versions_fetcher_by_purl[package_url]
56+
57+
versions_fetcher_by_purl[package_url] = versions_fetcher
58+
return versions_fetcher.get_until(package_name=api_name, until=until).valid_versions
59+
60+
61+
class DebianOvalBasicImprover(Improver):
3962
def __init__(self) -> None:
4063
self.versions_fetcher_by_purl: Mapping[str, VersionAPI] = {}
4164

4265
@property
4366
def interesting_advisories(self) -> QuerySet:
44-
return Advisory.objects.filter(
45-
Q(created_by=UbuntuImporter.qualified_name)
46-
| Q(created_by=DebianOvalImporter.qualified_name)
47-
)
48-
49-
def get_package_versions(
50-
self, package_url: PackageURL, until: Optional[datetime] = None
51-
) -> List[str]:
52-
"""
53-
Return a list of `valid_versions` for the `package_url`
54-
"""
55-
api_name = get_api_package_name(package_url)
56-
if not api_name:
57-
logger.error(f"Could not get versions for {package_url!r}")
58-
return []
59-
versions_fetcher = self.versions_fetcher_by_purl.get(package_url)
60-
if not versions_fetcher:
61-
versions_fetcher: VersionAPI = VERSION_API_CLASS_BY_NAMESPACE[package_url.namespace]
62-
self.versions_fetcher_by_purl[package_url] = versions_fetcher()
63-
64-
versions_fetcher = self.versions_fetcher_by_purl[package_url]
65-
66-
self.versions_fetcher_by_purl[package_url] = versions_fetcher
67-
return versions_fetcher.get_until(package_name=api_name, until=until).valid_versions
67+
return Advisory.objects.filter(Q(created_by=DebianOvalImporter.qualified_name))
6868

6969
def get_inferences(self, advisory_data: AdvisoryData) -> Iterable[Inference]:
7070
"""
@@ -83,9 +83,12 @@ def get_inferences(self, advisory_data: AdvisoryData) -> Iterable[Inference]:
8383
pkg_type = purl.type
8484
pkg_namespace = purl.namespace
8585
pkg_name = purl.name
86-
valid_versions = self.get_package_versions(
87-
package_url=purl, until=advisory_data.date_published
86+
valid_versions = get_package_versions(
87+
package_url=purl,
88+
until=advisory_data.date_published,
89+
versions_fetcher_by_purl=self.versions_fetcher_by_purl,
8890
)
91+
8992
for affected_version_range in affected_version_ranges:
9093
aff_vers, unaff_vers = resolve_version_range(
9194
affected_version_range=affected_version_range,
@@ -115,3 +118,60 @@ def get_inferences(self, advisory_data: AdvisoryData) -> Iterable[Inference]:
115118
affected_purls=affected_packages,
116119
fixed_purl=fixed_package,
117120
)
121+
122+
123+
class UbuntuOvalBasicImprover(Improver):
124+
def __init__(self) -> None:
125+
self.versions_fetcher_by_purl: Mapping[str, VersionAPI] = {}
126+
127+
@property
128+
def interesting_advisories(self) -> QuerySet:
129+
return Advisory.objects.filter(Q(created_by=UbuntuImporter.qualified_name))
130+
131+
def get_inferences(self, advisory_data: AdvisoryData) -> Iterable[Inference]:
132+
"""
133+
Yield Inferences for the given advisory data
134+
"""
135+
if not advisory_data.affected_packages:
136+
return
137+
138+
for affected_package in advisory_data.affected_packages:
139+
purl = affected_package.package
140+
affected_version_range = affected_package.affected_version_range
141+
pkg_type = purl.type
142+
pkg_namespace = purl.namespace
143+
pkg_name = purl.name
144+
valid_versions = get_package_versions(
145+
package_url=purl,
146+
until=advisory_data.date_published,
147+
versions_fetcher_by_purl=self.versions_fetcher_by_purl,
148+
)
149+
150+
aff_vers, unaff_vers = resolve_version_range(
151+
affected_version_range=affected_version_range,
152+
package_versions=valid_versions,
153+
)
154+
affected_purls = [
155+
PackageURL(type=pkg_type, namespace=pkg_namespace, name=pkg_name, version=version)
156+
for version in aff_vers
157+
]
158+
159+
unaffected_purls = [
160+
PackageURL(type=pkg_type, namespace=pkg_namespace, name=pkg_name, version=version)
161+
for version in unaff_vers
162+
]
163+
164+
affected_packages: List[LegacyAffectedPackage] = nearest_patched_package(
165+
vulnerable_packages=affected_purls, resolved_packages=unaffected_purls
166+
)
167+
168+
for (
169+
fixed_package,
170+
affected_packages,
171+
) in get_affected_packages_by_patched_package(affected_packages).items():
172+
yield Inference.from_advisory_data(
173+
advisory_data,
174+
confidence=100, # We are getting all valid versions to get this inference
175+
affected_purls=affected_packages,
176+
fixed_purl=fixed_package,
177+
)

vulnerabilities/package_managers.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ class LaunchpadVersionAPI(VersionAPI):
131131
def fetch(self, pkg: str) -> Iterable[PackageVersion]:
132132
url = (
133133
f"https://api.launchpad.net/1.0/ubuntu/+archive/primary?"
134-
"ws.op=getPublishedSources&source_name={pkg}&exact_match=true"
134+
f"ws.op=getPublishedSources&source_name={pkg}&exact_match=true"
135135
)
136136

137137
while True:
@@ -146,7 +146,7 @@ def fetch(self, pkg: str) -> Iterable[PackageVersion]:
146146
source_package_version = remove_debian_default_epoch(source_package_version)
147147
yield PackageVersion(
148148
value=source_package_version,
149-
release_date=release["date_published"],
149+
release_date=dateparser.parse(release["date_published"]),
150150
)
151151
if response.get("next_collection_link"):
152152
url = response["next_collection_link"]

0 commit comments

Comments
 (0)