new: Support for Sightings

Related https://github.com/cve-search/PyVulnerabilityLookup/issues/67
This commit is contained in:
Raphaël Vinot 2024-11-18 19:26:52 +01:00
parent c333f8d86f
commit 764adf228e

View file

@ -4,6 +4,7 @@ from __future__ import annotations
import logging import logging
from datetime import date, datetime
from importlib.metadata import version from importlib.metadata import version
from pathlib import PurePosixPath from pathlib import PurePosixPath
from typing import Any from typing import Any
@ -24,7 +25,7 @@ def enable_full_debug() -> None:
class PyVulnerabilityLookup(): class PyVulnerabilityLookup():
def __init__(self, root_url: str, useragent: str | None=None, token: str | None=None, def __init__(self, root_url: str='https://vulnerability.circl.lu', useragent: str | None=None, token: str | None=None,
*, proxies: dict[str, str] | None=None) -> None: *, proxies: dict[str, str] | None=None) -> None:
'''Query a specific instance. '''Query a specific instance.
@ -216,3 +217,84 @@ class PyVulnerabilityLookup():
'''Get user information''' '''Get user information'''
r = self.session.get(urljoin(self.root_url, str(PurePosixPath('api', 'user', 'me')))) r = self.session.get(urljoin(self.root_url, str(PurePosixPath('api', 'user', 'me'))))
return r.json() return r.json()
# #### Sightings ####
def get_sighting(self, sighting_uuid: str) -> dict[str, Any]:
'''Get a sighting
:param sighting_uuid: The UUID of the sighting
'''
r = self.session.get(urljoin(self.root_url, str(PurePosixPath('api', 'sighting', sighting_uuid))))
return r.json()
def get_sightings(self, /, *, sighting_uuid: str | None=None,
sighting_type: str | None=None, vuln_id: str | None = None,
author: str | None = None,
date_from: date | datetime | None=None,
date_to: date | datetime | None=None) -> dict[str, Any]:
'''Get sightings
:param sighting_uuid: The UUID of a specific sighting
:param sighting_type: The type of sighting, can be one of: 'seen', 'exploided', 'not-exploited', 'confirmed', 'not-confirmed', 'patched', 'not-patched'.
:param vuln_id: The vulnerability ID to get sightings of
:param author: The author of the sighting(s)
:param date_from: The date from which to get sightings
:param date_to: The date to which to get sightings
'''
params = {}
if sighting_uuid:
params['uuid'] = sighting_uuid
if sighting_type:
params['type'] = sighting_type
if vuln_id:
params['vuln_id'] = vuln_id
if author:
params['author'] = author
if date_from:
if isinstance(date_from, datetime):
date_from = date_from.date()
params['date_from'] = date_from.isoformat()
if date_to:
if isinstance(date_to, datetime):
date_to = date_to.date()
params['date_to'] = date_to.isoformat()
r = self.session.get(urljoin(self.root_url, str(PurePosixPath('api', 'sighting'))), params=params)
return r.json()
def create_sighting(self, /, *, sighting: dict[str, Any] | None=None,
creation_timestamp: datetime | None=None,
source: str | None = None,
sighting_type: str | None=None,
vulnerability: str | None=None) -> dict[str, Any]:
'''Create a sighting.
:param sighting: The sighting, as an object.
:param creation_timestamp: The timestamp of the sighting - set to now if not provided
:param source: The source of the sighting
:param sighting_type: The type of sighting, can be one of: 'seen', 'exploided', 'not-exploited', 'confirmed', 'not-confirmed', 'patched', 'not-patched'.
:param vulnerability: The vulnerability ID of the sighting
'''
if not sighting:
sighting = {}
if creation_timestamp:
# This calue may or may not have a TZ at this point
sighting['creation_timestamp'] = creation_timestamp
if source:
sighting['source'] = source
if sighting_type:
sighting['type'] = sighting_type
if vulnerability:
sighting['vulnerability'] = vulnerability
if 'creation_timestamp' in sighting:
# check if the datetime object has a TZ, if it doesn't, set it to localtime, make it a string
if sighting['creation_timestamp'].tzinfo is None:
sighting['creation_timestamp'] = sighting['creation_timestamp'].astimezone()
sighting['creation_timestamp'] = sighting['creation_timestamp'].isoformat()
r = self.session.post(urljoin(self.root_url, str(PurePosixPath('api', 'sighting'))),
json=sighting)
return r.json()