mirror of
https://github.com/cve-search/PyVulnerabilityLookup.git
synced 2024-11-25 08:17:20 +00:00
new: Support all public API calls
This commit is contained in:
parent
2e26d60150
commit
0df80fb8f3
2 changed files with 176 additions and 4 deletions
|
@ -3,7 +3,7 @@
|
|||
from __future__ import annotations
|
||||
|
||||
from importlib.metadata import version
|
||||
from pathlib import Path
|
||||
from pathlib import PurePosixPath
|
||||
from typing import Any
|
||||
from urllib.parse import urljoin, urlparse
|
||||
|
||||
|
@ -46,5 +46,76 @@ class PyVulnerabilityLookup():
|
|||
return r.json()
|
||||
|
||||
def get_vulnerability(self, vulnerability_id: str) -> dict[str, Any]:
|
||||
r = self.session.get(urljoin(self.root_url, str(Path('vulnerability', vulnerability_id))))
|
||||
'''Get a vulnerability
|
||||
|
||||
:param vulnerability_id: The ID of the vulnerability to get (can be from any source, as long as it is a valid ID)
|
||||
'''
|
||||
r = self.session.get(urljoin(self.root_url, str(PurePosixPath('vulnerability', vulnerability_id))))
|
||||
return r.json()
|
||||
|
||||
def get_info(self) -> dict[str, Any]:
|
||||
'''Get more information about the current databases in use and when it was updated'''
|
||||
r = self.session.get(urljoin(self.root_url, 'info'))
|
||||
return r.json()
|
||||
|
||||
def get_last(self, number: int | None=None, source: str | None = None) -> dict[str, Any]:
|
||||
'''Get the last vulnerabilities
|
||||
|
||||
:param number: The number of vulnerabilities to get
|
||||
:param source: The source of the vulnerabilities
|
||||
'''
|
||||
path = PurePosixPath('last')
|
||||
if source:
|
||||
path /= source
|
||||
if number is not None:
|
||||
path /= str(number)
|
||||
r = self.session.get(urljoin(self.root_url, str(path)))
|
||||
return r.json()
|
||||
|
||||
def get_vendors(self) -> list[str]:
|
||||
'''Get the list of known vendors'''
|
||||
r = self.session.get(urljoin(self.root_url, str(PurePosixPath('api', 'browse'))))
|
||||
return r.json()
|
||||
|
||||
def get_vendor_products(self, vendor: str) -> list[str]:
|
||||
'''Get the known products for a vendor
|
||||
|
||||
:params vendor: A vendor owning products (must be in the known vendor list)
|
||||
'''
|
||||
r = self.session.get(urljoin(self.root_url, str(PurePosixPath('api', 'browse', vendor))))
|
||||
return r.json()
|
||||
|
||||
def get_vendor_product_vulnerabilities(self, vendor: str, product: str) -> list[str]:
|
||||
'''Get the the vulnerabilities per vendor and a specific product
|
||||
|
||||
:param vendor: A vendor owning products (must be in the known vendor list)
|
||||
:param product: A product owned by that vendor
|
||||
'''
|
||||
r = self.session.get(urljoin(self.root_url, str(PurePosixPath('api', 'search', vendor, product))))
|
||||
return r.json()
|
||||
|
||||
# NOTE: endpoints /api/cve/*, /api/dbInfo, /api/last are alises for backward compat.
|
||||
|
||||
def get_comments(self, uuid: str | None = None, vuln_id: str | None = None,
|
||||
author: str | None = None) -> dict[str, Any]:
|
||||
'''Get comment(s)
|
||||
|
||||
:param uuid: The UUID a specific comment
|
||||
:param vuln_id: The vulnerability ID to get comments of
|
||||
:param author: The author of the comment(s)
|
||||
'''
|
||||
r = self.session.get(urljoin(self.root_url, str(PurePosixPath('api', 'comment'))),
|
||||
params={'uuid': uuid, 'vuln_id': vuln_id, 'author': author})
|
||||
return r.json()
|
||||
|
||||
def get_bundles(self, uuid: str | None = None, vuln_id: str | None = None,
|
||||
author: str | None = None) -> dict[str, Any]:
|
||||
'''Get bundle(s)
|
||||
|
||||
:param uuid: The UUID a specific bundle
|
||||
:param vuln_id: The vulnerability ID to get bundles of
|
||||
:param author: The author of the bundle(s)
|
||||
'''
|
||||
r = self.session.get(urljoin(self.root_url, str(PurePosixPath('api', 'bundle'))),
|
||||
params={'uuid': uuid, 'vuln_id': vuln_id, 'author': author})
|
||||
return r.json()
|
||||
|
|
|
@ -6,10 +6,12 @@ import time
|
|||
from pyvulnerabilitylookup import PyVulnerabilityLookup
|
||||
|
||||
|
||||
class TestBasic(unittest.TestCase):
|
||||
class TestPublic(unittest.TestCase):
|
||||
|
||||
def setUp(self) -> None:
|
||||
self.client = PyVulnerabilityLookup(root_url="http://127.0.0.1:10001")
|
||||
self.client = PyVulnerabilityLookup(root_url="https://vulnerability.circl.lu")
|
||||
|
||||
# Test default
|
||||
|
||||
def test_up(self) -> None:
|
||||
self.assertTrue(self.client.is_up)
|
||||
|
@ -22,3 +24,102 @@ class TestBasic(unittest.TestCase):
|
|||
break
|
||||
print('waiting for pysec to be imported')
|
||||
time.sleep(1)
|
||||
|
||||
def test_get_info(self) -> None:
|
||||
info = self.client.get_info()
|
||||
self.assertTrue(info['last_updates'])
|
||||
self.assertTrue(info['db_sizes'])
|
||||
|
||||
def test_get_last(self) -> None:
|
||||
last = self.client.get_last()
|
||||
self.assertTrue(last)
|
||||
self.assertTrue(isinstance(last, list))
|
||||
last = self.client.get_last(number=1)
|
||||
self.assertTrue(isinstance(last, list))
|
||||
self.assertEqual(len(last), 1)
|
||||
last = self.client.get_last(source='pysec')
|
||||
for vuln in last:
|
||||
self.assertTrue(vuln['id'].startswith('PYSEC'))
|
||||
last = self.client.get_last(source='pysec', number=1)
|
||||
self.assertEqual(len(last), 1)
|
||||
self.assertTrue(last[-1]['id'].startswith('PYSEC'))
|
||||
|
||||
# TODO: POST Vulnerability / Delete vulnerability
|
||||
# Test API
|
||||
|
||||
def test_get_vendors(self) -> None:
|
||||
vendors = self.client.get_vendors()
|
||||
self.assertTrue(isinstance(vendors, list))
|
||||
|
||||
def test_get_vendor_products(self) -> None:
|
||||
products = self.client.get_vendor_products('misp')
|
||||
self.assertTrue(isinstance(products, list))
|
||||
self.assertTrue('misp' in products)
|
||||
|
||||
def test_get_vendor_product_vulnerabilities(self) -> None:
|
||||
vulns = self.client.get_vendor_product_vulnerabilities('misp', 'misp')
|
||||
self.assertTrue(isinstance(vulns, dict))
|
||||
self.assertTrue('cvelistv5' in vulns)
|
||||
|
||||
# Test comments
|
||||
|
||||
def test_get_comments(self) -> None:
|
||||
comments = self.client.get_comments()
|
||||
self.assertTrue('metadata' in comments)
|
||||
self.assertTrue('data' in comments)
|
||||
self.assertTrue(len(comments['data']) > 0)
|
||||
|
||||
comments = self.client.get_comments(uuid='a309d024-2714-4a81-a425-60f83f6d5740')
|
||||
self.assertTrue(len(comments['data']) == 1)
|
||||
self.assertEqual(comments['data'][0]['uuid'], 'a309d024-2714-4a81-a425-60f83f6d5740')
|
||||
|
||||
comments = self.client.get_comments(vuln_id='CVE-2024-20401')
|
||||
self.assertTrue(len(comments['data']) >= 1)
|
||||
for comment in comments['data']:
|
||||
self.assertEqual(comment['vulnerability'], 'CVE-2024-20401')
|
||||
|
||||
comments = self.client.get_comments(author='admin')
|
||||
self.assertTrue(len(comments['data']) >= 1)
|
||||
for comment in comments['data']:
|
||||
self.assertEqual(comment['author']['login'], 'admin')
|
||||
|
||||
comments = self.client.get_comments(uuid='a309d024-2714-4a81-a425-60f83f6d5740',
|
||||
vuln_id='CVE-2024-20401',
|
||||
author='admin')
|
||||
self.assertTrue(len(comments['data']) == 1)
|
||||
self.assertEqual(comments['data'][0]['uuid'], 'a309d024-2714-4a81-a425-60f83f6d5740')
|
||||
self.assertEqual(comments['data'][0]['vulnerability'], 'CVE-2024-20401')
|
||||
self.assertEqual(comments['data'][0]['author']['login'], 'admin')
|
||||
|
||||
# TODO: POST / Delete Comment
|
||||
# TODO: POST / Get user
|
||||
|
||||
# Test bundles
|
||||
|
||||
def test_get_bundles(self) -> None:
|
||||
bundles = self.client.get_bundles()
|
||||
self.assertTrue('metadata' in bundles)
|
||||
self.assertTrue('data' in bundles)
|
||||
self.assertTrue(len(bundles['data']) > 0)
|
||||
|
||||
bundles = self.client.get_bundles(uuid='a23cbcad-e890-4df8-8736-9332ed4c3d47')
|
||||
self.assertTrue(len(bundles['data']) == 1)
|
||||
self.assertEqual(bundles['data'][0]['uuid'], 'a23cbcad-e890-4df8-8736-9332ed4c3d47')
|
||||
|
||||
bundles = self.client.get_bundles(vuln_id='CVE-2024-39573')
|
||||
self.assertTrue(len(bundles['data']) >= 1)
|
||||
for bundle in bundles['data']:
|
||||
self.assertTrue('CVE-2024-39573' in bundle['related_vulnerabilities'])
|
||||
|
||||
bundles = self.client.get_bundles(author='admin')
|
||||
self.assertTrue(len(bundles['data']) >= 1)
|
||||
for bundle in bundles['data']:
|
||||
self.assertEqual(bundle['author']['login'], 'admin')
|
||||
|
||||
bundles = self.client.get_bundles(uuid='a23cbcad-e890-4df8-8736-9332ed4c3d47',
|
||||
vuln_id='CVE-2024-39573',
|
||||
author='admin')
|
||||
self.assertTrue(len(bundles['data']) == 1)
|
||||
self.assertEqual(bundles['data'][0]['uuid'], 'a23cbcad-e890-4df8-8736-9332ed4c3d47')
|
||||
self.assertTrue('CVE-2024-39573' in bundles['data'][0]['related_vulnerabilities'])
|
||||
self.assertEqual(bundles['data'][0]['author']['login'], 'admin')
|
||||
|
|
Loading…
Reference in a new issue