Completed
Push — master ( b1214c...aea294 )
by Björn
28s queued 20s
created

gvm.protocols.gmpv208.entities.secinfo   B

Complexity

Total Complexity 43

Size/Duplication

Total Lines 540
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 222
dl 0
loc 540
rs 8.96
c 0
b 0
f 0
wmc 43

19 Methods

Rating   Name   Duplication   Size   Complexity  
A SecInfoMixin.get_cve_list() 0 27 1
A SecInfoMixin.get_scan_config_nvt() 0 23 2
A SecInfoMixin.get_oval_definition() 0 11 1
A SecInfoMixin.get_oval_definition_list() 0 27 1
A SecInfoMixin.get_dfn_cert_advisory_list() 0 27 1
A SecInfoMixin.get_cert_bund_advisory() 0 11 1
A SecInfoMixin.get_cert_bund_advisory_list() 0 27 1
A SecInfoMixin.get_cpe_list() 0 27 1
A SecInfoMixin.get_dfn_cert_advisory() 0 11 1
B SecInfoMixin.get_info_list() 0 48 5
C SecInfoMixin.get_scan_config_nvts() 0 60 10
A SecInfoMixin.get_nvt_list() 0 27 1
A SecInfoMixin.get_nvt() 0 11 1
A SecInfoMixin.get_info() 0 36 4
A SecInfoMixin.get_cpe() 0 11 1
A SecInfoMixin.get_nvt_families() 0 15 2
A SecInfoMixin.get_cve() 0 11 1
A SecInfoMixin.get_nvt_preferences() 0 22 2
A SecInfoMixin.get_nvt_preference() 0 29 3

1 Function

Rating   Name   Duplication   Size   Complexity  
A get_info_type_from_string() 0 14 3

How to fix   Complexity   

Complexity

Complex classes like gvm.protocols.gmpv208.entities.secinfo 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.

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