Completed
Push — master ( a9e580...460381 )
by Jaspar
18s queued 16s
created

SecInfoMixin.get_scan_config_nvts()   C

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