Skip to content

Commit 7437d29

Browse files
committed
Implement the new filter types audit report and report config
Support both new filter types.
1 parent 8b2ef47 commit 7437d29

File tree

6 files changed

+675
-5
lines changed

6 files changed

+675
-5
lines changed

gvm/protocols/gmp/_gmp226.py

Lines changed: 59 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
from .requests.v226 import (
1414
AuditReports,
1515
EntityID,
16+
Filters,
17+
FilterType,
1618
ReportFormatType,
1719
Reports,
1820
ResourceNames,
@@ -81,7 +83,9 @@ def get_resource_names(
8183
)
8284

8385
def get_resource_name(
84-
self, resource_id: str, resource_type: ResourceType # type: ignore[override]
86+
self,
87+
resource_id: str,
88+
resource_type: ResourceType, # type: ignore[override]
8589
) -> T:
8690
"""Request a single resource name
8791
@@ -276,3 +280,57 @@ def get_audit_reports(
276280
details=details,
277281
)
278282
)
283+
284+
def create_filter(
285+
self,
286+
name: str,
287+
*,
288+
filter_type: Optional[FilterType] = None, # type: ignore[override]
289+
comment: Optional[str] = None,
290+
term: Optional[str] = None,
291+
) -> T:
292+
"""Create a new filter
293+
294+
Args:
295+
name: Name of the new filter
296+
filter_type: Filter for entity type
297+
comment: Comment for the filter
298+
term: Filter term e.g. 'name=foo'
299+
"""
300+
# override create_filter because of the different FilterType enum
301+
# this avoids warnings with type checkers
302+
return self._send_and_transform_command(
303+
Filters.create_filter(
304+
name, filter_type=filter_type, comment=comment, term=term
305+
)
306+
)
307+
308+
def modify_filter(
309+
self,
310+
filter_id: EntityID,
311+
*,
312+
comment: Optional[str] = None,
313+
name: Optional[str] = None,
314+
term: Optional[str] = None,
315+
filter_type: Optional[FilterType] = None, # type: ignore[override]
316+
) -> T:
317+
"""Modifies an existing filter.
318+
319+
Args:
320+
filter_id: UUID of the filter to be modified
321+
comment: Comment on filter.
322+
name: Name of filter.
323+
term: Filter term.
324+
filter_type: Resource type filter applies to.
325+
"""
326+
# override create_filter because of the different FilterType enum
327+
# this avoids warnings with type checkers
328+
return self._send_and_transform_command(
329+
Filters.modify_filter(
330+
filter_id,
331+
comment=comment,
332+
name=name,
333+
term=term,
334+
filter_type=filter_type,
335+
)
336+
)

gvm/protocols/gmp/requests/v226/__init__.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# SPDX-FileCopyrightText: 2018-2025 Greenbone AG
1+
# SPDX-FileCopyrightText: 2025 Greenbone AG
22
#
33
# SPDX-License-Identifier: GPL-3.0-or-later
44
#
@@ -28,8 +28,6 @@
2828
EntityType,
2929
Feed,
3030
FeedType,
31-
Filters,
32-
FilterType,
3331
Groups,
3432
Help,
3533
HelpFormat,
@@ -72,6 +70,7 @@
7270
Vulnerabilities,
7371
)
7472
from ._audit_reports import AuditReports
73+
from ._filters import Filters, FilterType
7574
from ._reports import Reports
7675
from ._resource_names import ResourceNames, ResourceType
7776

Lines changed: 248 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,248 @@
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._enum import Enum
8+
from gvm.errors import RequiredArgument
9+
from gvm.protocols.core import Request
10+
from gvm.utils import to_bool
11+
from gvm.xml import XmlCommand
12+
13+
from .._entity_id import EntityID
14+
15+
__all__ = (
16+
"Filters",
17+
"FilterType",
18+
)
19+
20+
21+
class FilterType(Enum):
22+
"""Enum for filter types"""
23+
24+
ALERT = "alert"
25+
ALL_SECINFO = "secinfo"
26+
ASSET = "asset"
27+
AUDIT_REPORT = "audit_report"
28+
CREDENTIAL = "credential"
29+
FILTER = "filter"
30+
GROUP = "group"
31+
HOST = "host"
32+
NOTE = "note"
33+
OPERATING_SYSTEM = "os"
34+
OVERRIDE = "override"
35+
PERMISSION = "permission"
36+
PORT_LIST = "port_list"
37+
REPORT = "report"
38+
REPORT_CONFIG = "report_config"
39+
REPORT_FORMAT = "report_format"
40+
RESULT = "result"
41+
ROLE = "role"
42+
SCAN_CONFIG = "config"
43+
SCHEDULE = "schedule"
44+
TAG = "tag"
45+
TARGET = "target"
46+
TASK = "task"
47+
TICKET = "ticket"
48+
TLS_CERTIFICATE = "tls_certificate"
49+
USER = "user"
50+
VULNERABILITY = "vuln"
51+
52+
@classmethod
53+
def from_string(
54+
cls,
55+
filter_type: Optional[str],
56+
) -> Optional["FilterType"]:
57+
"""Convert a filter type string to an actual FilterType instance
58+
59+
Args:
60+
filter_type (str): Filter type string to convert to a FilterType
61+
"""
62+
if filter_type == "vuln":
63+
return cls.VULNERABILITY
64+
65+
if filter_type == "os":
66+
return cls.OPERATING_SYSTEM
67+
68+
if filter_type == "config":
69+
return cls.SCAN_CONFIG
70+
71+
if filter_type == "secinfo":
72+
return cls.ALL_SECINFO
73+
74+
return super().from_string(filter_type)
75+
76+
77+
class Filters:
78+
@classmethod
79+
def clone_filter(cls, filter_id: EntityID) -> Request:
80+
"""Clone a filter
81+
82+
Args:
83+
filter_id: ID of the filter to clone
84+
"""
85+
if not filter_id:
86+
raise RequiredArgument(
87+
function=cls.clone_filter.__name__, argument="filter_id"
88+
)
89+
90+
cmd = XmlCommand("create_filter")
91+
cmd.add_element("copy", str(filter_id))
92+
return cmd
93+
94+
@classmethod
95+
def create_filter(
96+
cls,
97+
name: str,
98+
*,
99+
filter_type: Optional[FilterType] = None,
100+
comment: Optional[str] = None,
101+
term: Optional[str] = None,
102+
) -> Request:
103+
"""Create a new filter
104+
105+
Args:
106+
name: Name of the new filter
107+
filter_type: Filter for entity type
108+
comment: Comment for the filter
109+
term: Filter term e.g. 'name=foo'
110+
"""
111+
if not name:
112+
raise RequiredArgument(
113+
function=cls.create_filter.__name__, argument="name"
114+
)
115+
116+
cmd = XmlCommand("create_filter")
117+
cmd.add_element("name", name)
118+
119+
if comment:
120+
cmd.add_element("comment", comment)
121+
122+
if term:
123+
cmd.add_element("term", term)
124+
125+
if filter_type:
126+
if not isinstance(filter_type, FilterType):
127+
filter_type = FilterType(filter_type)
128+
129+
cmd.add_element("type", filter_type.value)
130+
131+
return cmd
132+
133+
@classmethod
134+
def delete_filter(
135+
cls, filter_id: EntityID, *, ultimate: Optional[bool] = False
136+
) -> Request:
137+
"""Deletes an existing filter
138+
139+
Args:
140+
filter_id: UUID of the filter to be deleted.
141+
ultimate: Whether to remove entirely, or to the trashcan.
142+
"""
143+
if not filter_id:
144+
raise RequiredArgument(
145+
function=cls.delete_filter.__name__, argument="filter_id"
146+
)
147+
148+
cmd = XmlCommand("delete_filter")
149+
cmd.set_attribute("filter_id", str(filter_id))
150+
cmd.set_attribute("ultimate", to_bool(ultimate))
151+
152+
return cmd
153+
154+
@staticmethod
155+
def get_filters(
156+
*,
157+
filter_string: Optional[str] = None,
158+
filter_id: Optional[EntityID] = None,
159+
trash: Optional[bool] = None,
160+
alerts: Optional[bool] = None,
161+
) -> Request:
162+
"""Request a list of filters
163+
164+
Args:
165+
filter_string: Filter term to use for the query
166+
filter_id: UUID of an existing filter to use for the query
167+
trash: Whether to get the trashcan filters instead
168+
alerts: Whether to include list of alerts that use the filter.
169+
"""
170+
cmd = XmlCommand("get_filters")
171+
172+
cmd.add_filter(filter_string, filter_id)
173+
174+
if trash is not None:
175+
cmd.set_attribute("trash", to_bool(trash))
176+
177+
if alerts is not None:
178+
cmd.set_attribute("alerts", to_bool(alerts))
179+
180+
return cmd
181+
182+
@classmethod
183+
def get_filter(
184+
cls, filter_id: EntityID, *, alerts: Optional[bool] = None
185+
) -> Request:
186+
"""Request a single filter
187+
188+
Args:
189+
filter_id: UUID of an existing filter
190+
alerts: Whether to include list of alerts that use the filter.
191+
"""
192+
cmd = XmlCommand("get_filters")
193+
194+
if not filter_id:
195+
raise RequiredArgument(
196+
function=cls.get_filter.__name__, argument="filter_id"
197+
)
198+
199+
cmd.set_attribute("filter_id", str(filter_id))
200+
201+
if alerts is not None:
202+
cmd.set_attribute("alerts", to_bool(alerts))
203+
204+
return cmd
205+
206+
@classmethod
207+
def modify_filter(
208+
cls,
209+
filter_id: EntityID,
210+
*,
211+
comment: Optional[str] = None,
212+
name: Optional[str] = None,
213+
term: Optional[str] = None,
214+
filter_type: Optional[FilterType] = None,
215+
) -> Request:
216+
"""Modifies an existing filter.
217+
218+
Args:
219+
filter_id: UUID of the filter to be modified
220+
comment: Comment on filter.
221+
name: Name of filter.
222+
term: Filter term.
223+
filter_type: Resource type filter applies to.
224+
"""
225+
if not filter_id:
226+
raise RequiredArgument(
227+
function=cls.modify_filter.__name__, argument="filter_id"
228+
)
229+
230+
cmd = XmlCommand("modify_filter")
231+
cmd.set_attribute("filter_id", str(filter_id))
232+
233+
if comment:
234+
cmd.add_element("comment", comment)
235+
236+
if name:
237+
cmd.add_element("name", name)
238+
239+
if term:
240+
cmd.add_element("term", term)
241+
242+
if filter_type:
243+
if not isinstance(filter_type, FilterType):
244+
filter_type = FilterType(filter_type)
245+
246+
cmd.add_element("type", filter_type.value)
247+
248+
return cmd

0 commit comments

Comments
 (0)