python-gvm 26.2.0__py3-none-any.whl → 26.3.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
gvm/__version__.py CHANGED
@@ -2,4 +2,4 @@
2
2
 
3
3
  # THIS IS AN AUTOGENERATED FILE. DO NOT TOUCH!
4
4
 
5
- __version__ = "26.2.0"
5
+ __version__ = "26.3.0"
@@ -9,13 +9,14 @@ In most circumstances you will want to use the :class:`GMP` class which
9
9
  dynamically selects the supported GMP protocol of the remote manager daemon.
10
10
 
11
11
  If you need to use a specific GMP version, you can use the :class:`GMPv224`,
12
- :class:`GMPv225`, :class:`GMPv226` or :class:`GMPv227` classes.
12
+ :class:`GMPv225`, :class:`GMPv226`, :class:`GMPv227` or :class:`GMPv228` classes.
13
13
 
14
14
  * :class:`GMP` - Dynamically select supported GMP protocol of the remote manager daemon.
15
15
  * :class:`GMPv224` - GMP version 22.4
16
16
  * :class:`GMPv225` - GMP version 22.5
17
17
  * :class:`GMPv226` - GMP version 22.6
18
18
  * :class:`GMPv227` - GMP version 22.7
19
+ * :class:`GMPv228` - GMP version 22.8
19
20
  """
20
21
 
21
22
  from ._gmp import GMP
@@ -23,6 +24,7 @@ from ._gmp224 import GMPv224
23
24
  from ._gmp225 import GMPv225
24
25
  from ._gmp226 import GMPv226
25
26
  from ._gmp227 import GMPv227
27
+ from ._gmp228 import GMPv228
26
28
 
27
29
  Gmp = GMP # for backwards compatibility
28
30
 
@@ -33,4 +35,5 @@ __all__ = (
33
35
  "GMPv225",
34
36
  "GMPv226",
35
37
  "GMPv227",
38
+ "GMPv228",
36
39
  )
gvm/protocols/gmp/_gmp.py CHANGED
@@ -16,10 +16,13 @@ from ._gmp224 import GMPv224
16
16
  from ._gmp225 import GMPv225
17
17
  from ._gmp226 import GMPv226
18
18
  from ._gmp227 import GMPv227
19
+ from ._gmp228 import GMPv228
19
20
  from .requests import Version
20
21
 
21
- SUPPORTED_GMP_VERSIONS = Union[GMPv224[T], GMPv225[T], GMPv226[T], GMPv227[T]]
22
- _SUPPORTED_GMP_VERSION_STRINGS = ["22.4", "22.5", "22.6", "22.7"]
22
+ SUPPORTED_GMP_VERSIONS = Union[
23
+ GMPv224[T], GMPv225[T], GMPv226[T], GMPv227[T], GMPv228[T]
24
+ ]
25
+ _SUPPORTED_GMP_VERSION_STRINGS = ["22.4", "22.5", "22.6", "22.7", "22.8"]
23
26
 
24
27
 
25
28
  class GMP(GvmProtocol[T]):
@@ -38,7 +41,8 @@ class GMP(GvmProtocol[T]):
38
41
  # gvm.protocols.gmp.GMPv224,
39
42
  # gvm.protocols.gmp.GMPv225,
40
43
  # gvm.protocols.gmp.GMPv226,
41
- # or gvm.protocols.gmp.GMPv227
44
+ # gvm.protocols.gmp.GMPv227,
45
+ # or gvm.protocols.gmp.GMPv228
42
46
  # depending on the supported GMP version of the remote manager daemon
43
47
  resp = gmp.get_tasks()
44
48
  """
@@ -91,9 +95,13 @@ class GMP(GvmProtocol[T]):
91
95
  gmp_class = GMPv224
92
96
  elif major_version == 22 and minor_version == 5:
93
97
  gmp_class = GMPv225
94
- elif major_version == 22 and minor_version >= 6:
98
+ elif major_version == 22 and minor_version == 6:
95
99
  gmp_class = GMPv226
96
- if minor_version > 6:
100
+ elif major_version == 22 and minor_version == 7:
101
+ gmp_class = GMPv227
102
+ elif major_version == 22 and minor_version >= 8:
103
+ gmp_class = GMPv228
104
+ if minor_version > 8:
97
105
  warnings.warn(
98
106
  "Remote manager daemon uses a newer GMP version than "
99
107
  f"supported by python-gvm {__version__}. Please update to "
@@ -0,0 +1,76 @@
1
+ # SPDX-FileCopyrightText: 2025 Greenbone AG
2
+ #
3
+ # SPDX-License-Identifier: GPL-3.0-or-later
4
+
5
+ from typing import Optional
6
+
7
+ from gvm.protocols.gmp.requests import EntityID
8
+
9
+ from .._protocol import T
10
+ from ._gmp227 import GMPv227
11
+ from .requests.v228 import AgentInstallers
12
+
13
+
14
+ class GMPv228(GMPv227[T]):
15
+ """
16
+ A class implementing the Greenbone Management Protocol (GMP) version 22.8
17
+
18
+ Example:
19
+
20
+ .. code-block:: python
21
+
22
+ from gvm.protocols.gmp import GMPv228 as GMP
23
+
24
+ with GMP(connection) as gmp:
25
+ resp = gmp.get_tasks()
26
+ """
27
+
28
+ @staticmethod
29
+ def get_protocol_version() -> tuple[int, int]:
30
+ return (22, 8)
31
+
32
+ def get_agent_installers(
33
+ self,
34
+ *,
35
+ filter_string: Optional[str] = None,
36
+ filter_id: Optional[EntityID] = None,
37
+ trash: Optional[bool] = None,
38
+ details: Optional[bool] = None,
39
+ ) -> T:
40
+ """Request a list of agent installers
41
+
42
+ Args:
43
+ filter_string: Filter term to use for the query
44
+ filter_id: UUID of an existing filter to use for the query
45
+ trash: Whether to get the trashcan agent installers instead
46
+ details: Whether to include extra details like tasks using this
47
+ scanner
48
+ """
49
+ return self._send_request_and_transform_response(
50
+ AgentInstallers.get_agent_installers(
51
+ filter_string=filter_string,
52
+ filter_id=filter_id,
53
+ trash=trash,
54
+ details=details,
55
+ )
56
+ )
57
+
58
+ def get_agent_installer(self, agent_installer_id: EntityID) -> T:
59
+ """Request a single agent installer
60
+
61
+ Args:
62
+ agent_installer_id: UUID of an existing agent installer
63
+ """
64
+ return self._send_request_and_transform_response(
65
+ AgentInstallers.get_agent_installer(agent_installer_id)
66
+ )
67
+
68
+ def get_agent_installer_file(self, agent_installer_id: EntityID) -> T:
69
+ """Request a single agent installer file
70
+
71
+ Args:
72
+ agent_installer_id: UUID of an existing agent installer
73
+ """
74
+ return self._send_request_and_transform_response(
75
+ AgentInstallers.get_agent_installer_file(agent_installer_id)
76
+ )
@@ -0,0 +1,150 @@
1
+ # SPDX-FileCopyrightText: 2025 Greenbone AG
2
+ #
3
+ # SPDX-License-Identifier: GPL-3.0-or-later
4
+
5
+ from gvm.protocols.gmp.requests.v228._agent_installers import AgentInstallers
6
+
7
+ from .._entity_id import EntityID
8
+ from .._version import Version
9
+ from ..v227 import (
10
+ Aggregates,
11
+ AggregateStatistic,
12
+ AlertCondition,
13
+ AlertEvent,
14
+ AlertMethod,
15
+ Alerts,
16
+ AliveTest,
17
+ AuditReports,
18
+ Audits,
19
+ Authentication,
20
+ CertBundAdvisories,
21
+ Cpes,
22
+ CredentialFormat,
23
+ Credentials,
24
+ CredentialType,
25
+ Cves,
26
+ DfnCertAdvisories,
27
+ EntityType,
28
+ Feed,
29
+ FeedType,
30
+ Filters,
31
+ FilterType,
32
+ Groups,
33
+ Help,
34
+ HelpFormat,
35
+ Hosts,
36
+ HostsOrdering,
37
+ InfoType,
38
+ Notes,
39
+ Nvts,
40
+ OperatingSystems,
41
+ Overrides,
42
+ Permissions,
43
+ PermissionSubjectType,
44
+ Policies,
45
+ PortLists,
46
+ PortRangeType,
47
+ ReportConfigParameter,
48
+ ReportConfigs,
49
+ ReportFormats,
50
+ ReportFormatType,
51
+ Reports,
52
+ ResourceNames,
53
+ ResourceType,
54
+ Results,
55
+ Roles,
56
+ ScanConfigs,
57
+ Scanners,
58
+ ScannerType,
59
+ Schedules,
60
+ SecInfo,
61
+ Severity,
62
+ SnmpAuthAlgorithm,
63
+ SnmpPrivacyAlgorithm,
64
+ SortOrder,
65
+ SystemReports,
66
+ Tags,
67
+ Targets,
68
+ Tasks,
69
+ Tickets,
70
+ TicketStatus,
71
+ TLSCertificates,
72
+ TrashCan,
73
+ UserAuthType,
74
+ Users,
75
+ UserSettings,
76
+ Vulnerabilities,
77
+ )
78
+
79
+ __all__ = (
80
+ "AgentInstallers",
81
+ "Aggregates",
82
+ "AggregateStatistic",
83
+ "Alerts",
84
+ "AlertCondition",
85
+ "AlertEvent",
86
+ "AlertMethod",
87
+ "AliveTest",
88
+ "AuditReports",
89
+ "Audits",
90
+ "Authentication",
91
+ "CertBundAdvisories",
92
+ "Cpes",
93
+ "Credentials",
94
+ "CredentialFormat",
95
+ "CredentialType",
96
+ "Cves",
97
+ "DfnCertAdvisories",
98
+ "EntityID",
99
+ "EntityType",
100
+ "Feed",
101
+ "FeedType",
102
+ "Filters",
103
+ "FilterType",
104
+ "Groups",
105
+ "Help",
106
+ "HelpFormat",
107
+ "Hosts",
108
+ "HostsOrdering",
109
+ "InfoType",
110
+ "Notes",
111
+ "Nvts",
112
+ "OperatingSystems",
113
+ "Overrides",
114
+ "Permissions",
115
+ "PermissionSubjectType",
116
+ "Policies",
117
+ "PortLists",
118
+ "PortRangeType",
119
+ "ReportConfigs",
120
+ "ReportConfigParameter",
121
+ "ReportFormatType",
122
+ "ReportFormats",
123
+ "Reports",
124
+ "ResourceNames",
125
+ "ResourceType",
126
+ "Results",
127
+ "Roles",
128
+ "ScanConfigs",
129
+ "Scanners",
130
+ "ScannerType",
131
+ "Schedules",
132
+ "SecInfo",
133
+ "Severity",
134
+ "SortOrder",
135
+ "SnmpAuthAlgorithm",
136
+ "SnmpPrivacyAlgorithm",
137
+ "SystemReports",
138
+ "Tags",
139
+ "Targets",
140
+ "Tasks",
141
+ "Tickets",
142
+ "TicketStatus",
143
+ "TLSCertificates",
144
+ "TrashCan",
145
+ "UserAuthType",
146
+ "UserSettings",
147
+ "Users",
148
+ "Version",
149
+ "Vulnerabilities",
150
+ )
@@ -0,0 +1,83 @@
1
+ # SPDX-FileCopyrightText: 2025 Greenbone AG
2
+ #
3
+ # SPDX-License-Identifier: GPL-3.0-or-later
4
+ #
5
+ # SPDX-License-Identifier: GPL-3.0-or-later
6
+
7
+ from typing import Optional
8
+
9
+ from gvm.errors import RequiredArgument
10
+ from gvm.protocols.core import Request
11
+ from gvm.protocols.gmp.requests._entity_id import EntityID
12
+ from gvm.utils import to_bool
13
+ from gvm.xml import XmlCommand
14
+
15
+
16
+ class AgentInstallers:
17
+
18
+ @staticmethod
19
+ def get_agent_installers(
20
+ *,
21
+ filter_string: Optional[str] = None,
22
+ filter_id: Optional[EntityID] = None,
23
+ trash: Optional[bool] = None,
24
+ details: Optional[bool] = None,
25
+ ) -> Request:
26
+ """Request a list of agent installers
27
+
28
+ Args:
29
+ filter_string: Filter term to use for the query
30
+ filter_id: UUID of an existing filter to use for the query
31
+ trash: Whether to get the trashcan agent installers instead
32
+ details: Whether to include extra details like tasks using this
33
+ scanner
34
+ """
35
+ cmd = XmlCommand("get_agent_installers")
36
+ cmd.add_filter(filter_string, filter_id)
37
+
38
+ if trash is not None:
39
+ cmd.set_attribute("trash", to_bool(trash))
40
+
41
+ if details is not None:
42
+ cmd.set_attribute("details", to_bool(details))
43
+
44
+ return cmd
45
+
46
+ @classmethod
47
+ def get_agent_installer(cls, agent_installer_id: EntityID) -> Request:
48
+ """Request a single agent installer
49
+
50
+ Args:
51
+ agent_installer_id: UUID of an existing agent installer
52
+ """
53
+ if not agent_installer_id:
54
+ raise RequiredArgument(
55
+ function=cls.get_agent_installer.__name__,
56
+ argument="agent_installer_id",
57
+ )
58
+
59
+ cmd = XmlCommand("get_agent_installers")
60
+ cmd.set_attribute("agent_installer_id", str(agent_installer_id))
61
+
62
+ # for single entity always request all details
63
+ cmd.set_attribute("details", "1")
64
+
65
+ return cmd
66
+
67
+ @classmethod
68
+ def get_agent_installer_file(cls, agent_installer_id: EntityID) -> Request:
69
+ """Request a single agent installer
70
+
71
+ Args:
72
+ agent_installer_id: UUID of an existing agent installer
73
+ """
74
+ if not agent_installer_id:
75
+ raise RequiredArgument(
76
+ function=cls.get_agent_installer.__name__,
77
+ argument="agent_installer_id",
78
+ )
79
+
80
+ cmd = XmlCommand("get_agent_installer_file")
81
+ cmd.set_attribute("agent_installer_id", str(agent_installer_id))
82
+
83
+ return cmd
@@ -0,0 +1,9 @@
1
+ # SPDX-FileCopyrightText: 2025 Greenbone AG
2
+ #
3
+ # SPDX-License-Identifier: GPL-3.0-or-later
4
+
5
+ """
6
+ Package for supported Greenbone HTTP APIs.
7
+
8
+ Currently only `openvasd version 1 <https://greenbone.github.io/scanner-api/#/>`_ is supported.
9
+ """
@@ -0,0 +1,18 @@
1
+ # SPDX-FileCopyrightText: 2025 Greenbone AG
2
+ #
3
+ # SPDX-License-Identifier: GPL-3.0-or-later
4
+
5
+ """
6
+ High-level API interface for interacting with openvasd HTTP services via
7
+ logical modules (health, metadata, scans, etc.).
8
+
9
+ Usage:
10
+
11
+ .. code-block:: python
12
+
13
+ from gvm.protocols.http.openvasd import OpenvasdHttpAPIv1
14
+ """
15
+
16
+ from ._openvasd1 import OpenvasdHttpAPIv1
17
+
18
+ __all__ = ["OpenvasdHttpAPIv1"]
@@ -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
@@ -0,0 +1,80 @@
1
+ # SPDX-FileCopyrightText: 2025 Greenbone AG
2
+ #
3
+ # SPDX-License-Identifier: GPL-3.0-or-later
4
+
5
+ """
6
+ http client for initializing a connection to the openvasd HTTP API using optional mTLS authentication.
7
+ """
8
+
9
+ import ssl
10
+ from os import PathLike
11
+ from typing import Optional, Tuple, Union
12
+
13
+ from httpx import Client
14
+
15
+ StrOrPathLike = Union[str, PathLike[str]]
16
+
17
+
18
+ def create_openvasd_http_client(
19
+ host_name: str,
20
+ *,
21
+ api_key: Optional[str] = None,
22
+ server_ca_path: Optional[StrOrPathLike] = None,
23
+ client_cert_paths: Optional[
24
+ Union[StrOrPathLike, Tuple[StrOrPathLike, StrOrPathLike]]
25
+ ] = None,
26
+ port: int = 3000,
27
+ ) -> Client:
28
+ """
29
+ Create a `httpx.Client` configured for mTLS-secured or API KEY access
30
+ to an openvasd HTTP API instance.
31
+
32
+ Args:
33
+ host_name: Hostname or IP of the OpenVASD server (e.g., "localhost").
34
+ api_key: Optional API key used for authentication via HTTP headers.
35
+ server_ca_path: Path to the server's CA certificate (for verifying the server).
36
+ client_cert_paths: Path to the client certificate (str) or a tuple of
37
+ (cert_path, key_path) for mTLS authentication.
38
+ port: The port to connect to (default: 3000).
39
+
40
+ Behavior:
41
+ - If both `server_ca_path` and `client_cert_paths` are set, an mTLS connection
42
+ is established using an SSLContext.
43
+ - If not, `verify` is set to False (insecure), and HTTP is used instead of HTTPS.
44
+ HTTP connection needs api_key for authorization.
45
+ """
46
+ headers = {}
47
+
48
+ context: Optional[ssl.SSLContext] = None
49
+
50
+ # Prepare mTLS SSL context if needed
51
+ if client_cert_paths and server_ca_path:
52
+ context = ssl.create_default_context(
53
+ ssl.Purpose.SERVER_AUTH, cafile=server_ca_path
54
+ )
55
+ if isinstance(client_cert_paths, tuple):
56
+ context.load_cert_chain(
57
+ certfile=client_cert_paths[0], keyfile=client_cert_paths[1]
58
+ )
59
+ else:
60
+ context.load_cert_chain(certfile=client_cert_paths)
61
+
62
+ context.check_hostname = False
63
+ context.verify_mode = ssl.CERT_REQUIRED
64
+
65
+ # Set verify based on context presence
66
+ verify: Union[bool, ssl.SSLContext] = context if context else False
67
+
68
+ if api_key:
69
+ headers["X-API-KEY"] = api_key
70
+
71
+ protocol = "https" if context else "http"
72
+ base_url = f"{protocol}://{host_name}:{port}"
73
+
74
+ return Client(
75
+ base_url=base_url,
76
+ headers=headers,
77
+ verify=verify,
78
+ http2=True,
79
+ timeout=10.0,
80
+ )
@@ -0,0 +1,87 @@
1
+ # SPDX-FileCopyrightText: 2025 Greenbone AG
2
+ #
3
+ # SPDX-License-Identifier: GPL-3.0-or-later
4
+
5
+ """
6
+ API wrapper for accessing the /health endpoints of the openvasd HTTP API.
7
+ """
8
+
9
+ import httpx
10
+
11
+ from ._api import OpenvasdAPI
12
+
13
+
14
+ class HealthAPI(OpenvasdAPI):
15
+ """
16
+ Provides access to the openvasd /health endpoints, which expose the
17
+ operational state of the scanner.
18
+
19
+ All methods return the HTTP status code of the response and raise an exception
20
+ if the server returns an error response (4xx or 5xx).
21
+ """
22
+
23
+ def get_alive(self) -> int:
24
+ """
25
+ Check if the scanner process is alive.
26
+
27
+ Returns:
28
+ HTTP status code (e.g., 200 if alive).
29
+
30
+ Raises:
31
+ httpx.HTTPStatusError: If the server response indicates failure and
32
+ exceptions are not suppressed.
33
+
34
+ See: GET /health/alive in the openvasd API documentation.
35
+ """
36
+ try:
37
+ response = self._client.get("/health/alive")
38
+ response.raise_for_status()
39
+ return response.status_code
40
+ except httpx.HTTPStatusError as e:
41
+ if self._suppress_exceptions:
42
+ return e.response.status_code
43
+ raise
44
+
45
+ def get_ready(self) -> int:
46
+ """
47
+ Check if the scanner is ready to accept requests (e.g., feed loaded).
48
+
49
+ Returns:
50
+ HTTP status code (e.g., 200 if ready).
51
+
52
+ Raises:
53
+ httpx.HTTPStatusError: If the server response indicates failure and
54
+ exceptions are not suppressed.
55
+
56
+ See: GET /health/ready in the openvasd API documentation.
57
+ """
58
+ try:
59
+ response = self._client.get("/health/ready")
60
+ response.raise_for_status()
61
+ return response.status_code
62
+ except httpx.HTTPStatusError as e:
63
+ if self._suppress_exceptions:
64
+ return e.response.status_code
65
+ raise
66
+
67
+ def get_started(self) -> int:
68
+ """
69
+ Check if the scanner has fully started.
70
+
71
+ Returns:
72
+ HTTP status code (e.g., 200 if started).
73
+
74
+ Raises:
75
+ httpx.HTTPStatusError: If the server response indicates failure and
76
+ exceptions are not suppressed.
77
+
78
+ See: GET /health/started in the openvasd API documentation.
79
+ """
80
+ try:
81
+ response = self._client.get("/health/started")
82
+ response.raise_for_status()
83
+ return response.status_code
84
+ except httpx.HTTPStatusError as e:
85
+ if self._suppress_exceptions:
86
+ return e.response.status_code
87
+ raise