SecInfoMixin.get_scan_config_nvts()   C
last analyzed

Complexity

Conditions 10

Size

Total Lines 60
Code Lines 32

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 10
eloc 32
nop 11
dl 0
loc 60
rs 5.9999
c 0
b 0
f 0

How to fix   Long Method    Complexity    Many Parameters   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

Complexity

Complex classes like gvm.protocols.gmpv208.entities.secinfo.SecInfoMixin.get_scan_config_nvts() often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
# -*- coding: utf-8 -*-
2
# Copyright (C) 2021 Greenbone Networks GmbH
3
#
4
# SPDX-License-Identifier: GPL-3.0-or-later
5
#
6
# This program is free software: you can redistribute it and/or modify
7
# it under the terms of the GNU General Public License as published by
8
# the Free Software Foundation, either version 3 of the License, or
9
# (at your option) any later version.
10
#
11
# This program is distributed in the hope that it will be useful,
12
# but WITHOUT ANY WARRANTY; without even the implied warranty of
13
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
# GNU General Public License for more details.
15
#
16
# You should have received a copy of the GNU General Public License
17
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
18
19
from enum import Enum
20
from typing import Any, Optional
21
22
from gvm.errors import InvalidArgument, InvalidArgumentType, RequiredArgument
23
from gvm.utils import add_filter, to_bool
24
from gvm.xml import XmlCommand
25
26
27
class InfoType(Enum):
28
    """Enum for info types"""
29
30
    CERT_BUND_ADV = "CERT_BUND_ADV"
31
    CPE = "CPE"
32
    CVE = "CVE"
33
    DFN_CERT_ADV = "DFN_CERT_ADV"
34
    OVALDEF = "OVALDEF"
35
    NVT = "NVT"
36
37
38
def get_info_type_from_string(info_type: Optional[str]) -> Optional[InfoType]:
39
    """Convert a info type string to an actual InfoType instance
40
41
    Arguments:
42
        info_type: Info type string to convert to a InfoType
43
    """
44
    if not info_type:
45
        return None
46
    try:
47
        return InfoType[info_type.upper()]
48
    except KeyError:
49
        raise InvalidArgument(
50
            argument='info_type', function=get_info_type_from_string.__name__
51
        ) from None
52
53
54
class SecInfoMixin:
55
    def get_nvt_families(self, *, sort_order: Optional[str] = None):
56
        """Request a list of nvt families
57
58
        Arguments:
59
            sort_order: Sort order
60
61
        Returns:
62
            The response. See :py:meth:`send_command` for details.
63
        """
64
        cmd = XmlCommand("get_nvt_families")
65
66
        if sort_order:
67
            cmd.set_attribute("sort_order", sort_order)
68
69
        return self._send_xml_command(cmd)
70
71
    def get_scan_config_nvts(
72
        self,
73
        *,
74
        details: Optional[bool] = None,
75
        preferences: Optional[bool] = None,
76
        preference_count: Optional[bool] = None,
77
        timeout: Optional[bool] = None,
78
        config_id: Optional[str] = None,
79
        preferences_config_id: Optional[str] = None,
80
        family: Optional[str] = None,
81
        sort_order: Optional[str] = None,
82
        sort_field: Optional[str] = None,
83
    ):
84
        """Request a list of nvts
85
86
        Arguments:
87
            details: Whether to include full details
88
            preferences: Whether to include nvt preferences
89
            preference_count: Whether to include preference count
90
            timeout: Whether to include the special timeout preference
91
            config_id: UUID of scan config to which to limit the NVT listing
92
            preferences_config_id: UUID of scan config to use for preference
93
                values
94
            family: Family to which to limit NVT listing
95
            sort_order: Sort order
96
            sort_field: Sort field
97
98
        Returns:
99
            The response. See :py:meth:`send_command` for details.
100
        """
101
        cmd = XmlCommand("get_nvts")
102
103
        if details is not None:
104
            cmd.set_attribute("details", to_bool(details))
105
106
        if preferences is not None:
107
            cmd.set_attribute("preferences", to_bool(preferences))
108
109
        if preference_count is not None:
110
            cmd.set_attribute("preference_count", to_bool(preference_count))
111
112
        if timeout is not None:
113
            cmd.set_attribute("timeout", to_bool(timeout))
114
115
        if config_id:
116
            cmd.set_attribute("config_id", config_id)
117
118
        if preferences_config_id:
119
            cmd.set_attribute("preferences_config_id", preferences_config_id)
120
121
        if family:
122
            cmd.set_attribute("family", family)
123
124
        if sort_order:
125
            cmd.set_attribute("sort_order", sort_order)
126
127
        if sort_field:
128
            cmd.set_attribute("sort_field", sort_field)
129
130
        return self._send_xml_command(cmd)
131
132
    def get_scan_config_nvt(self, nvt_oid: str):
133
        """Request a single nvt
134
135
        Arguments:
136
            nvt_oid: OID of an existing nvt
137
138
        Returns:
139
            The response. See :py:meth:`send_command` for details.
140
        """
141
        cmd = XmlCommand("get_nvts")
142
143
        if not nvt_oid:
144
            raise RequiredArgument(
145
                function=self.get_scan_config_nvt.__name__, argument='nvt_oid'
146
            )
147
148
        cmd.set_attribute("nvt_oid", nvt_oid)
149
150
        # for single entity always request all details
151
        cmd.set_attribute("details", "1")
152
        cmd.set_attribute("preferences", "1")
153
        cmd.set_attribute("preference_count", "1")
154
        return self._send_xml_command(cmd)
155
156
    def get_cve_list(
157
        self,
158
        *,
159
        filter_string: Optional[str] = None,
160
        filter_id: Optional[str] = None,
161
        name: Optional[str] = None,
162
        details: Optional[bool] = None,
163
    ) -> Any:
164
        """Request a list of CVEs
165
166
        Arguments:
167
            filter_string: Filter term to use for the query
168
            filter_id: UUID of an existing filter to use for the query
169
            name: Name or identifier of the requested information
170
            details: Whether to include information about references to this
171
                information
172
173
        Returns:
174
            The response. See :py:meth:`send_command` for details.
175
        """
176
177
        return self.get_info_list(
178
            info_type=InfoType.CVE,
179
            filter_string=filter_string,
180
            filter_id=filter_id,
181
            name=name,
182
            details=details,
183
        )
184
185
    def get_cpe_list(
186
        self,
187
        *,
188
        filter_string: Optional[str] = None,
189
        filter_id: Optional[str] = None,
190
        name: Optional[str] = None,
191
        details: Optional[bool] = None,
192
    ) -> Any:
193
        """Request a list of CPEs
194
195
        Arguments:
196
            filter_string: Filter term to use for the query
197
            filter_id: UUID of an existing filter to use for the query
198
            name: Name or identifier of the requested information
199
            details: Whether to include information about references to this
200
                information
201
202
        Returns:
203
            The response. See :py:meth:`send_command` for details.
204
        """
205
206
        return self.get_info_list(
207
            info_type=InfoType.CPE,
208
            filter_string=filter_string,
209
            filter_id=filter_id,
210
            name=name,
211
            details=details,
212
        )
213
214
    def get_nvt_list(
215
        self,
216
        *,
217
        filter_string: Optional[str] = None,
218
        filter_id: Optional[str] = None,
219
        name: Optional[str] = None,
220
        details: Optional[bool] = None,
221
    ) -> Any:
222
        """Request a list of NVTs
223
224
        Arguments:
225
            filter_string: Filter term to use for the query
226
            filter_id: UUID of an existing filter to use for the query
227
            name: Name or identifier of the requested information
228
            details: Whether to include information about references to this
229
                information
230
231
        Returns:
232
            The response. See :py:meth:`send_command` for details.
233
        """
234
235
        return self.get_info_list(
236
            info_type=InfoType.NVT,
237
            filter_string=filter_string,
238
            filter_id=filter_id,
239
            name=name,
240
            details=details,
241
        )
242
243
    def get_dfn_cert_advisory_list(
244
        self,
245
        *,
246
        filter_string: Optional[str] = None,
247
        filter_id: Optional[str] = None,
248
        name: Optional[str] = None,
249
        details: Optional[bool] = None,
250
    ) -> Any:
251
        """Request a list of DFN-CERT Advisories
252
253
        Arguments:
254
            filter_string: Filter term to use for the query
255
            filter_id: UUID of an existing filter to use for the query
256
            name: Name or identifier of the requested information
257
            details: Whether to include information about references to this
258
                information
259
260
        Returns:
261
            The response. See :py:meth:`send_command` for details.
262
        """
263
264
        return self.get_info_list(
265
            info_type=InfoType.DFN_CERT_ADV,
266
            filter_string=filter_string,
267
            filter_id=filter_id,
268
            name=name,
269
            details=details,
270
        )
271
272
    def get_cert_bund_advisory_list(
273
        self,
274
        *,
275
        filter_string: Optional[str] = None,
276
        filter_id: Optional[str] = None,
277
        name: Optional[str] = None,
278
        details: Optional[bool] = None,
279
    ) -> Any:
280
        """Request a list of CERT-BUND Advisories
281
282
        Arguments:
283
            filter_string: Filter term to use for the query
284
            filter_id: UUID of an existing filter to use for the query
285
            name: Name or identifier of the requested information
286
            details: Whether to include information about references to this
287
                information
288
289
        Returns:
290
            The response. See :py:meth:`send_command` for details.
291
        """
292
293
        return self.get_info_list(
294
            info_type=InfoType.CERT_BUND_ADV,
295
            filter_string=filter_string,
296
            filter_id=filter_id,
297
            name=name,
298
            details=details,
299
        )
300
301
    def get_oval_definition_list(
302
        self,
303
        *,
304
        filter_string: Optional[str] = None,
305
        filter_id: Optional[str] = None,
306
        name: Optional[str] = None,
307
        details: Optional[bool] = None,
308
    ) -> Any:
309
        """Request a list of OVAL definitions
310
311
        Arguments:
312
            filter_string: Filter term to use for the query
313
            filter_id: UUID of an existing filter to use for the query
314
            name: Name or identifier of the requested information
315
            details: Whether to include information about references to this
316
                information
317
318
        Returns:
319
            The response. See :py:meth:`send_command` for details.
320
        """
321
322
        return self.get_info_list(
323
            info_type=InfoType.OVALDEF,
324
            filter_string=filter_string,
325
            filter_id=filter_id,
326
            name=name,
327
            details=details,
328
        )
329
330
    def get_info_list(
331
        self,
332
        info_type: InfoType,
333
        *,
334
        filter_string: Optional[str] = None,
335
        filter_id: Optional[str] = None,
336
        name: Optional[str] = None,
337
        details: Optional[bool] = None,
338
    ) -> Any:
339
        """Request a list of security information
340
341
        Arguments:
342
            info_type: Type must be either CERT_BUND_ADV, CPE, CVE,
343
                DFN_CERT_ADV, OVALDEF, NVT or ALLINFO
344
            filter_string: Filter term to use for the query
345
            filter_id: UUID of an existing filter to use for the query
346
            name: Name or identifier of the requested information
347
            details: Whether to include information about references to this
348
                information
349
350
        Returns:
351
            The response. See :py:meth:`send_command` for details.
352
        """
353
        if not info_type:
354
            raise RequiredArgument(
355
                function=self.get_info_list.__name__, argument='info_type'
356
            )
357
358
        if not isinstance(info_type, InfoType):
359
            raise InvalidArgumentType(
360
                function=self.get_info_list.__name__,
361
                argument='info_type',
362
                arg_type=InfoType.__name__,
363
            )
364
365
        cmd = XmlCommand("get_info")
366
367
        cmd.set_attribute("type", info_type.value)
368
369
        add_filter(cmd, filter_string, filter_id)
370
371
        if name:
372
            cmd.set_attribute("name", name)
373
374
        if details is not None:
375
            cmd.set_attribute("details", to_bool(details))
376
377
        return self._send_xml_command(cmd)
378
379
    def get_cve(self, cve_id: str) -> Any:
380
        """Request a single CVE
381
382
        Arguments:
383
            cve_id: ID of an existing CVE
384
385
        Returns:
386
            The response. See :py:meth:`send_command` for details.
387
        """
388
389
        return self.get_info(cve_id, InfoType.CVE)
390
391
    def get_cpe(self, cpe_id: str) -> Any:
392
        """Request a single CPE
393
394
        Arguments:
395
            cpe_id: ID of an existing CPE
396
397
        Returns:
398
            The response. See :py:meth:`send_command` for details.
399
        """
400
401
        return self.get_info(cpe_id, InfoType.CPE)
402
403
    def get_nvt(self, nvt_id: str) -> Any:
404
        """Request a single NVT
405
406
        Arguments:
407
            nvt_id: ID of an existing NVT
408
409
        Returns:
410
            The response. See :py:meth:`send_command` for details.
411
        """
412
413
        return self.get_info(nvt_id, InfoType.NVT)
414
415
    def get_dfn_cert_advisory(self, cert_id: str) -> Any:
416
        """Request a single DFN-CERT Advisory
417
418
        Arguments:
419
            cert_id: ID of an existing DFN-CERT Advisory
420
421
        Returns:
422
            The response. See :py:meth:`send_command` for details.
423
        """
424
425
        return self.get_info(cert_id, InfoType.DFN_CERT_ADV)
426
427
    def get_cert_bund_advisory(self, cert_id: str) -> Any:
428
        """Request a single CERT-BUND Advisory
429
430
        Arguments:
431
            cert_id: ID of an existing CERT-BUND Advisory
432
433
        Returns:
434
            The response. See :py:meth:`send_command` for details.
435
        """
436
437
        return self.get_info(cert_id, InfoType.CERT_BUND_ADV)
438
439
    def get_oval_definition(self, oval_id: str) -> Any:
440
        """Request a single Oval definition
441
442
        Arguments:
443
            oval_id: ID of an existing Oval definition
444
445
        Returns:
446
            The response. See :py:meth:`send_command` for details.
447
        """
448
449
        return self.get_info(oval_id, InfoType.OVALDEF)
450
451
    def get_info(self, info_id: str, info_type: InfoType) -> Any:
452
        """Request a single secinfo
453
454
        Arguments:
455
            info_id: ID of an existing secinfo
456
            info_type: Type must be either CERT_BUND_ADV, CPE, CVE,
457
                DFN_CERT_ADV, OVALDEF, NVT
458
459
        Returns:
460
            The response. See :py:meth:`send_command` for details.
461
        """
462
        if not info_type:
463
            raise RequiredArgument(
464
                function=self.get_info.__name__, argument='info_type'
465
            )
466
467
        if not isinstance(info_type, InfoType):
468
            raise InvalidArgumentType(
469
                function=self.get_info.__name__,
470
                argument='info_type',
471
                arg_type=InfoType.__name__,
472
            )
473
474
        if not info_id:
475
            raise RequiredArgument(
476
                function=self.get_info.__name__, argument='info_id'
477
            )
478
479
        cmd = XmlCommand("get_info")
480
        cmd.set_attribute("info_id", info_id)
481
482
        cmd.set_attribute("type", info_type.value)
483
484
        # for single entity always request all details
485
        cmd.set_attribute("details", "1")
486
        return self._send_xml_command(cmd)
487
488
    def get_nvt_preferences(
489
        self,
490
        *,
491
        nvt_oid: Optional[str] = None,
492
    ) -> Any:
493
        """Request a list of preferences
494
495
        The preference element includes just the
496
        name and value, with the NVT and type built into the name.
497
498
        Arguments:
499
            nvt_oid: OID of nvt
500
501
        Returns:
502
            The response. See :py:meth:`send_command` for details.
503
        """
504
        cmd = XmlCommand("get_preferences")
505
506
        if nvt_oid:
507
            cmd.set_attribute("nvt_oid", nvt_oid)
508
509
        return self._send_xml_command(cmd)
510
511
    def get_nvt_preference(
512
        self,
513
        name: str,
514
        *,
515
        nvt_oid: Optional[str] = None,
516
    ) -> Any:
517
        """Request a nvt preference
518
519
        Arguments:
520
            name: name of a particular preference
521
            nvt_oid: OID of nvt
522
            config_id: UUID of scan config of which to show preference values
523
524
        Returns:
525
            The response. See :py:meth:`send_command` for details.
526
        """
527
        cmd = XmlCommand("get_preferences")
528
529
        if not name:
530
            raise RequiredArgument(
531
                function=self.get_nvt_preference.__name__, argument='name'
532
            )
533
534
        cmd.set_attribute("preference", name)
535
536
        if nvt_oid:
537
            cmd.set_attribute("nvt_oid", nvt_oid)
538
539
        return self._send_xml_command(cmd)
540