Skip to content

Commit 243ddff

Browse files
committed
Cleanup and improve the openvasd API
Drop the safe argument from all methods and replace it with a instance variable. Improve the types and docstrings of all methods.
1 parent 94d78f7 commit 243ddff

File tree

12 files changed

+368
-262
lines changed

12 files changed

+368
-262
lines changed

gvm/protocols/http/openvasd/_api.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# SPDX-FileCopyrightText: 2025 Greenbone AG
2+
#
3+
# SPDX-License-Identifier: GPL-3.0-or-later
4+
5+
6+
import httpx
7+
8+
9+
class OpenvasdAPI:
10+
def __init__(
11+
self, client: httpx.Client, *, suppress_exceptions: bool = False
12+
):
13+
"""
14+
Initialize the OpenvasdAPI entry point.
15+
16+
Args:
17+
client: An initialized `httpx.Client` configured for communicating
18+
with the openvasd server.
19+
suppress_exceptions: If True, suppress exceptions and return structured error responses.
20+
Default is False, which means exceptions will be raised.
21+
"""
22+
self._client = client
23+
self._suppress_exceptions = suppress_exceptions

gvm/protocols/http/openvasd/_health.py

Lines changed: 15 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,10 @@
88

99
import httpx
1010

11+
from ._api import OpenvasdAPI
1112

12-
class HealthAPI:
13+
14+
class HealthAPI(OpenvasdAPI):
1315
"""
1416
Provides access to the openvasd /health endpoints, which expose the
1517
operational state of the scanner.
@@ -18,28 +20,16 @@ class HealthAPI:
1820
if the server returns an error response (4xx or 5xx).
1921
"""
2022

21-
def __init__(self, client: httpx.Client):
22-
"""
23-
Create a new HealthAPI instance.
24-
25-
Args:
26-
client: An initialized `httpx.Client` configured for communicating
27-
with the openvasd server.
28-
"""
29-
self._client = client
30-
31-
def get_alive(self, safe: bool = False) -> int:
23+
def get_alive(self) -> int:
3224
"""
3325
Check if the scanner process is alive.
3426
35-
Args:
36-
safe: If True, suppress exceptions and return structured error responses.
37-
3827
Returns:
3928
HTTP status code (e.g., 200 if alive).
4029
4130
Raises:
42-
httpx.HTTPStatusError: If the server response indicates failure and safe is False.
31+
httpx.HTTPStatusError: If the server response indicates failure and
32+
exceptions are not suppressed.
4333
4434
See: GET /health/alive in the openvasd API documentation.
4535
"""
@@ -48,22 +38,20 @@ def get_alive(self, safe: bool = False) -> int:
4838
response.raise_for_status()
4939
return response.status_code
5040
except httpx.HTTPStatusError as e:
51-
if safe:
41+
if self._suppress_exceptions:
5242
return e.response.status_code
5343
raise
5444

55-
def get_ready(self, safe: bool = False) -> int:
45+
def get_ready(self) -> int:
5646
"""
5747
Check if the scanner is ready to accept requests (e.g., feed loaded).
5848
59-
Args:
60-
safe: If True, suppress exceptions and return structured error responses.
61-
6249
Returns:
6350
HTTP status code (e.g., 200 if ready).
6451
6552
Raises:
66-
httpx.HTTPStatusError: If the server response indicates failure and safe is False.
53+
httpx.HTTPStatusError: If the server response indicates failure and
54+
exceptions are not suppressed.
6755
6856
See: GET /health/ready in the openvasd API documentation.
6957
"""
@@ -72,22 +60,20 @@ def get_ready(self, safe: bool = False) -> int:
7260
response.raise_for_status()
7361
return response.status_code
7462
except httpx.HTTPStatusError as e:
75-
if safe:
63+
if self._suppress_exceptions:
7664
return e.response.status_code
7765
raise
7866

79-
def get_started(self, safe: bool = False) -> int:
67+
def get_started(self) -> int:
8068
"""
8169
Check if the scanner has fully started.
8270
83-
Args:
84-
safe: If True, suppress exceptions and return structured error responses.
85-
8671
Returns:
8772
HTTP status code (e.g., 200 if started).
8873
8974
Raises:
90-
httpx.HTTPStatusError: If the server response indicates failure and safe is False.
75+
httpx.HTTPStatusError: If the server response indicates failure and
76+
exceptions are not suppressed.
9177
9278
See: GET /health/started in the openvasd API documentation.
9379
"""
@@ -96,6 +82,6 @@ def get_started(self, safe: bool = False) -> int:
9682
response.raise_for_status()
9783
return response.status_code
9884
except httpx.HTTPStatusError as e:
99-
if safe:
85+
if self._suppress_exceptions:
10086
return e.response.status_code
10187
raise

gvm/protocols/http/openvasd/_metadata.py

Lines changed: 12 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,14 @@
66
API wrapper for retrieving metadata from the openvasd HTTP API using HEAD requests.
77
"""
88

9+
from typing import Union
10+
911
import httpx
1012

13+
from ._api import OpenvasdAPI
14+
1115

12-
class MetadataAPI:
16+
class MetadataAPI(OpenvasdAPI):
1317
"""
1418
Provides access to metadata endpoints exposed by the openvasd server
1519
using lightweight HTTP HEAD requests.
@@ -23,35 +27,23 @@ class MetadataAPI:
2327
is handled gracefully.
2428
"""
2529

26-
def __init__(self, client: httpx.Client):
27-
"""
28-
Initialize a MetadataAPI instance.
29-
30-
Args:
31-
client: An `httpx.Client` configured to communicate with the openvasd server.
32-
"""
33-
self._client = client
34-
35-
def get(self, safe: bool = False) -> dict:
30+
def get(self) -> dict[str, Union[str, int]]:
3631
"""
3732
Perform a HEAD request to `/` to retrieve top-level API metadata.
3833
39-
Args:
40-
safe: If True, suppress exceptions and return structured error responses.
41-
4234
Returns:
4335
A dictionary containing:
4436
4537
- "api-version"
4638
- "feed-version"
4739
- "authentication"
4840
49-
Or if safe=True and error occurs:
41+
Or if exceptions are suppressed and error occurs:
5042
5143
- {"error": str, "status_code": int}
5244
5345
Raises:
54-
httpx.HTTPStatusError: For non-401 HTTP errors if safe=False.
46+
httpx.HTTPStatusError: For non-401 HTTP errors if exceptions are not suppressed.
5547
5648
See: HEAD / in the openvasd API documentation.
5749
"""
@@ -64,17 +56,14 @@ def get(self, safe: bool = False) -> dict:
6456
"authentication": response.headers.get("authentication"),
6557
}
6658
except httpx.HTTPStatusError as e:
67-
if safe:
59+
if self._suppress_exceptions:
6860
return {"error": str(e), "status_code": e.response.status_code}
6961
raise
7062

71-
def get_scans(self, safe: bool = False) -> dict:
63+
def get_scans(self) -> dict[str, Union[str, int]]:
7264
"""
7365
Perform a HEAD request to `/scans` to retrieve scan endpoint metadata.
7466
75-
Args:
76-
safe: If True, suppress exceptions and return structured error responses.
77-
7867
Returns:
7968
A dictionary containing:
8069
@@ -87,7 +76,7 @@ def get_scans(self, safe: bool = False) -> dict:
8776
- {"error": str, "status_code": int}
8877
8978
Raises:
90-
httpx.HTTPStatusError: For non-401 HTTP errors if safe=False.
79+
httpx.HTTPStatusError: For non-401 HTTP errors if exceptions are not suppressed.
9180
9281
See: HEAD /scans in the openvasd API documentation.
9382
"""
@@ -100,6 +89,6 @@ def get_scans(self, safe: bool = False) -> dict:
10089
"authentication": response.headers.get("authentication"),
10190
}
10291
except httpx.HTTPStatusError as e:
103-
if safe:
92+
if self._suppress_exceptions:
10493
return {"error": str(e), "status_code": e.response.status_code}
10594
raise

gvm/protocols/http/openvasd/_notus.py

Lines changed: 10 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -6,36 +6,25 @@
66
API wrapper for interacting with the Notus component of the openvasd HTTP API.
77
"""
88

9-
import urllib.parse
10-
from typing import List
9+
import urllib
1110

1211
import httpx
1312

13+
from ._api import OpenvasdAPI
1414

15-
class NotusAPI:
15+
16+
class NotusAPI(OpenvasdAPI):
1617
"""
1718
Provides access to the Notus-related endpoints of the openvasd HTTP API.
1819
1920
This includes retrieving supported operating systems and triggering
2021
package-based vulnerability scans for a specific OS.
2122
"""
2223

23-
def __init__(self, client: httpx.Client):
24-
"""
25-
Initialize a NotusAPI instance.
26-
27-
Args:
28-
client: An `httpx.Client` configured to communicate with the openvasd server.
29-
"""
30-
self._client = client
31-
32-
def get_os_list(self, safe: bool = False) -> httpx.Response:
24+
def get_os_list(self) -> httpx.Response:
3325
"""
3426
Retrieve the list of supported operating systems from the Notus service.
3527
36-
Args:
37-
safe: If True, return error info on failure instead of raising.
38-
3928
Returns:
4029
The full `httpx.Response` on success.
4130
@@ -46,20 +35,21 @@ def get_os_list(self, safe: bool = False) -> httpx.Response:
4635
response.raise_for_status()
4736
return response
4837
except httpx.HTTPStatusError as e:
49-
if safe:
38+
if self._suppress_exceptions:
5039
return e.response
5140
raise
5241

5342
def run_scan(
54-
self, os: str, package_list: List[str], safe: bool = False
43+
self,
44+
os: str,
45+
package_list: list[str],
5546
) -> httpx.Response:
5647
"""
5748
Trigger a Notus scan for a given OS and list of packages.
5849
5950
Args:
6051
os: Operating system name (e.g., "debian", "alpine").
6152
package_list: List of package names to evaluate for vulnerabilities.
62-
safe: If True, return error info on failure instead of raising.
6353
6454
Returns:
6555
The full `httpx.Response` on success.
@@ -74,6 +64,6 @@ def run_scan(
7464
response.raise_for_status()
7565
return response
7666
except httpx.HTTPStatusError as e:
77-
if safe:
67+
if self._suppress_exceptions:
7868
return e.response
7969
raise

gvm/protocols/http/openvasd/_openvasd1.py

Lines changed: 67 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ def __init__(
3939
client_cert_paths: Optional[
4040
Union[StrOrPathLike, Tuple[StrOrPathLike, StrOrPathLike]]
4141
] = None,
42+
suppress_exceptions: bool = False,
4243
):
4344
"""
4445
Initialize the OpenvasdHttpApiV1 entry point.
@@ -49,10 +50,8 @@ def __init__(
4950
api_key: Optional API key to be used for authentication.
5051
server_ca_path: Path to the server CA certificate (for HTTPS/mTLS).
5152
client_cert_paths: Path to client certificate or (cert, key) tuple for mTLS.
52-
53-
Behavior:
54-
- Sets up an underlying `httpx.Client` using `OpenvasdClient`.
55-
- Initializes sub-API modules with the shared client instance.
53+
suppress_exceptions: If True, suppress exceptions and return structured error
54+
responses. Default is False, which means exceptions will be raised.
5655
"""
5756
self._client = create_openvasd_http_client(
5857
host_name=host_name,
@@ -63,8 +62,67 @@ def __init__(
6362
)
6463

6564
# Sub-API modules
66-
self.health = HealthAPI(self._client)
67-
self.metadata = MetadataAPI(self._client)
68-
self.notus = NotusAPI(self._client)
69-
self.scans = ScansAPI(self._client)
70-
self.vts = VtsAPI(self._client)
65+
self.__health = HealthAPI(
66+
self._client, suppress_exceptions=suppress_exceptions
67+
)
68+
self.__metadata = MetadataAPI(
69+
self._client, suppress_exceptions=suppress_exceptions
70+
)
71+
self.__notus = NotusAPI(
72+
self._client, suppress_exceptions=suppress_exceptions
73+
)
74+
self.__scans = ScansAPI(
75+
self._client, suppress_exceptions=suppress_exceptions
76+
)
77+
self.__vts = VtsAPI(
78+
self._client, suppress_exceptions=suppress_exceptions
79+
)
80+
81+
@property
82+
def health(self) -> HealthAPI:
83+
"""
84+
Access the health API module.
85+
86+
Provides methods to check the health status of the openvasd service.
87+
"""
88+
return self.__health
89+
90+
@property
91+
def metadata(self) -> MetadataAPI:
92+
"""
93+
Access the metadata API module.
94+
95+
Provides methods to retrieve metadata about the openvasd service,
96+
including version and feed information.
97+
"""
98+
return self.__metadata
99+
100+
@property
101+
def notus(self) -> NotusAPI:
102+
"""
103+
Access the Notus API module.
104+
105+
Provides methods to interact with the Notus service for package-based
106+
vulnerability scanning.
107+
"""
108+
return self.__notus
109+
110+
@property
111+
def scans(self) -> ScansAPI:
112+
"""
113+
Access the scans API module.
114+
115+
Provides methods to manage and interact with vulnerability scans,
116+
including starting, stopping, and retrieving scan results.
117+
"""
118+
return self.__scans
119+
120+
@property
121+
def vts(self) -> VtsAPI:
122+
"""
123+
Access the VTS API module.
124+
125+
Provides methods to manage and interact with Vulnerability Tests
126+
(VTs) for vulnerability assessment.
127+
"""
128+
return self.__vts

0 commit comments

Comments
 (0)