Passed
Pull Request — master (#133)
by
unknown
01:41
created

gvm.protocols.gmpv8.Gmp.create_target()   A

Complexity

Conditions 1

Size

Total Lines 66
Code Lines 34

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 34
nop 17
dl 0
loc 66
rs 9.064
c 0
b 0
f 0

How to fix   Long Method    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:

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) 2018 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=arguments-differ, redefined-builtin
20
21
"""
22
Module for communication with gvmd in `Greenbone Management Protocol version 8`_
23
24
.. _Greenbone Management Protocol version 8:
25
    https://docs.greenbone.net/API/GMP/gmp-8.0.html
26
"""
27
from enum import Enum
28
29
from gvm.errors import InvalidArgument, RequiredArgument
30
from gvm.utils import get_version_string
31
from gvm.xml import XmlCommand
32
33
from .gmpv7 import Gmp as Gmpv7, _to_bool, _add_filter
34
35
PROTOCOL_VERSION = (8,)
36
37
38
class FilterType(Enum):
39
    AGENT = "agent"
40
    ALERT = "alert"
41
    ASSET = "asset"
42
    SCAN_CONFIG = "config"
43
    CREDENTIAL = "credential"
44
    FILTER = "filter"
45
    GROUP = "group"
46
    HOST = "host"
47
    NOTE = "note"
48
    OPERATING_SYSTEM = "os"
49
    OVERRIDE = "override"
50
    PERMISSION = "permission"
51
    PORT_LIST = "port_list"
52
    REPORT = "report"
53
    REPORT_FORMAT = "report_format"
54
    RESULT = "result"
55
    ROLE = "role"
56
    SCHEDULE = "schedule"
57
    ALL_SECINFO = "secinfo"
58
    TAG = "tag"
59
    TARGET = "target"
60
    TASK = "task"
61
    TICKET = "ticket"
62
    USER = "user"
63
    VULNERABILITY = "vuln"
64
65
66
class CredentialType(Enum):
67
    CLIENT_CERTIFICATE = 'cc'
68
    SNMP = 'snmp'
69
    USERNAME_PASSWORD = 'up'
70
    USERNAME_SSH_KEY = 'usk'
71
    SMIME_CERTIFICATE = 'smime'
72
    PGP_ENCRYPTION_KEY = 'pgp'
73
    PASSWORD_ONLY = 'pw'
74
75
76
class TicketStatus(Enum):
77
    OPEN = 'Open'
78
    FIXED = 'Fixed'
79
    CLOSED = 'Closed'
80
81
82
class SnmpAuthAlgorithm(Enum):
83
    SHA1 = 'sha1'
84
    MD5 = 'md5'
85
86
87
class SnmpPrivacyAlgorithm(Enum):
88
    AES = 'aes'
89
    DES = 'des'
90
91
92
class Gmp(Gmpv7):
93
    @staticmethod
94
    def get_protocol_version():
95
        """Determine the Greenbone Management Protocol version.
96
97
        Returns:
98
            str: Implemented version of the Greenbone Management Protocol
99
        """
100
        return get_version_string(PROTOCOL_VERSION)
101
102
    def create_credential(
0 ignored issues
show
Comprehensibility introduced by
This function exceeds the maximum number of variables (19/15).
Loading history...
103
        self,
104
        name,
105
        credential_type,
106
        *,
107
        comment=None,
108
        allow_insecure=None,
109
        certificate=None,
110
        key_phrase=None,
111
        private_key=None,
112
        login=None,
113
        password=None,
114
        auth_algorithm=None,
115
        community=None,
116
        privacy_algorithm=None,
117
        privacy_password=None,
118
        public_key=None
119
    ):
120
        """Create a new credential
121
122
        Create a new credential e.g. to be used in the method of an alert.
123
124
        Currently the following credential types are supported:
125
126
            - Username + Password
127
            - Username + private SSH-Key
128
            - Client Certificates
129
            - SNMPv1 or SNMPv2c protocol
130
            - S/MIME Certificate
131
            - OpenPGP Key
132
            - Password only
133
134
        Arguments:
135
            name (str): Name of the new credential
136
            credential_type (CredentialType): The credential type.
137
            comment (str, optional): Comment for the credential
138
            allow_insecure (boolean, optional): Whether to allow insecure use of
139
                the credential
140
            certificate (str, optional): Certificate for the credential.
141
                Required for cc and smime credential types.
142
            key_phrase (str, optional): Key passphrase for the private key.
143
                Used for the usk credential type.
144
            private_key (str, optional): Private key to use for login. Required
145
                for usk credential type. Also used for the cc credential type.
146
                The supported key types (dsa, rsa, ecdsa, ...) and formats (PEM,
147
                PKC#12, OpenSSL, ...) depend on your installed GnuTLS version.
148
            login (str, optional): Username for the credential. Required for
149
                up, usk and snmp credential type.
150
            password (str, optional): Password for the credential. Used for
151
                up and snmp credential types.
152
            community (str, optional): The SNMP community
153
            auth_algorithm (SnmpAuthAlgorithm, optional): The SNMP
154
                authentication algorithm. Required for snmp credential type.
155
            privacy_algorithm (SnmpPrivacyAlgorithm, optional): The SNMP privacy
156
                algorithm
157
            privacy_password (str, optional): The SNMP privacy password
158
            public_key: (str, optional): PGP public key in *armor* plain text
159
                format. Required for pgp credential type.
160
161
        Examples:
162
            Creating a Username + Password credential
163
164
            .. code-block:: python
165
166
                gmp.create_credential(
167
                    name='UP Credential',
168
                    credential_type=CredentialType.USERNAME_PASSWORD,
169
                    login='foo',
170
                    password='bar',
171
                );
172
173
            Creating a Username + SSH Key credential
174
175
            .. code-block:: python
176
177
                with open('path/to/private-ssh-key') as f:
178
                    key = f.read()
179
180
                gmp.create_credential(
181
                    name='USK Credential',
182
                    credential_type=CredentialType.USERNAME_SSH_KEY,
183
                    login='foo',
184
                    key_phrase='foobar',
185
                    private_key=key,
186
                )
187
188
            Creating a PGP credential
189
190
            .. note::
191
192
                A compatible public pgp key file can be exported with GnuPG via
193
                ::
194
195
                    $ gpg --armor --export [email protected] > alice.asc
196
197
            .. code-block:: python
198
199
                with open('path/to/pgp.key.asc') as f:
200
                    key = f.read()
201
202
                gmp.create_credential(
203
                    name='PGP Credential',
204
                    credential_type=CredentialType.PGP_ENCRYPTION_KEY,
205
                    public_key=key,
206
                )
207
208
            Creating a S/MIME credential
209
210
            .. code-block:: python
211
212
                with open('path/to/smime-cert') as f:
213
                    cert = f.read()
214
215
                gmp.create_credential(
216
                    name='SMIME Credential',
217
                    credential_type=CredentialType.SMIME_CERTIFICATE,
218
                    certificate=cert,
219
                )
220
221
            Creating a Password-Only credential
222
223
            .. code-block:: python
224
225
                gmp.create_credential(
226
                    name='Password-Only Credential',
227
                    credential_type=CredentialType.PASSWORD_ONLY,
228
                    password='foo',
229
                )
230
        Returns:
231
            The response. See :py:meth:`send_command` for details.
232
        """
233
        if not name:
234
            raise RequiredArgument("create_credential requires name argument")
235
236
        if not isinstance(credential_type, CredentialType):
237
            raise InvalidArgument(
238
                "create_credential requires type to be a CredentialType "
239
                "instance"
240
            )
241
242
        cmd = XmlCommand("create_credential")
243
        cmd.add_element("name", name)
244
245
        cmd.add_element("type", credential_type.value)
246
247
        if comment:
248
            cmd.add_element("comment", comment)
249
250
        if allow_insecure is not None:
251
            cmd.add_element("allow_insecure", _to_bool(allow_insecure))
252
253
        if (
254
            credential_type == CredentialType.CLIENT_CERTIFICATE
0 ignored issues
show
Unused Code introduced by
Consider merging these comparisons with "in" to 'credential_type in (CredentialType.CLIENT_CERTIFICATE, CredentialType.SMIME_CERTIFICATE)'
Loading history...
255
            or credential_type == CredentialType.SMIME_CERTIFICATE
256
        ):
257
            if not certificate:
258
                raise RequiredArgument(
259
                    "create_credential requires certificate argument for "
260
                    "credential_type {0}".format(credential_type.name)
261
                )
262
263
            cmd.add_element("certificate", certificate)
264
265
        if (
266
            credential_type == CredentialType.USERNAME_PASSWORD
0 ignored issues
show
Unused Code introduced by
Consider merging these comparisons with "in" to 'credential_type in (CredentialType.USERNAME_PASSWORD, CredentialType.USERNAME_SSH_KEY, CredentialType.SNMP)'
Loading history...
267
            or credential_type == CredentialType.USERNAME_SSH_KEY
268
            or credential_type == CredentialType.SNMP
269
        ):
270
            if not login:
271
                raise RequiredArgument(
272
                    "create_credential requires login argument for "
273
                    "credential_type {0}".format(credential_type.name)
274
                )
275
276
            cmd.add_element("login", login)
277
278
        if credential_type == CredentialType.PASSWORD_ONLY and not password:
279
            raise RequiredArgument(
280
                "create_credential requires password argument for "
281
                "credential_type {0}".format(credential_type.name)
282
            )
283
284
        if (
285
            credential_type == CredentialType.USERNAME_PASSWORD
0 ignored issues
show
Unused Code introduced by
Consider merging these comparisons with "in" to 'credential_type in (CredentialType.USERNAME_PASSWORD, CredentialType.SNMP, CredentialType.PASSWORD_ONLY)'
Loading history...
286
            or credential_type == CredentialType.SNMP
287
            or credential_type == CredentialType.PASSWORD_ONLY
288
        ) and password:
289
            cmd.add_element("password", password)
290
291
        if credential_type == CredentialType.USERNAME_SSH_KEY:
292
            if not private_key:
293
                raise RequiredArgument(
294
                    "create_credential requires certificate argument for "
295
                    "credential_type {0}".format(credential_type.name)
296
                )
297
298
            _xmlkey = cmd.add_element("key")
299
            _xmlkey.add_element("private", private_key)
300
301
            if key_phrase:
302
                _xmlkey.add_element("phrase", key_phrase)
303
304
        if credential_type == CredentialType.CLIENT_CERTIFICATE and private_key:
305
            _xmlkey = cmd.add_element("key")
306
            _xmlkey.add_element("private", private_key)
307
308
        if credential_type == CredentialType.SNMP:
309
            if not isinstance(auth_algorithm, SnmpAuthAlgorithm):
310
                raise InvalidArgument(
311
                    "create_credential requires auth_algorithm to be a "
312
                    "SnmpAuthAlgorithm instance"
313
                )
314
315
            cmd.add_element("auth_algorithm", auth_algorithm.value)
316
317
            if community:
318
                cmd.add_element("community", community)
319
320 View Code Duplication
            if privacy_algorithm is not None or privacy_password:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
321
                _xmlprivacy = cmd.add_element("privacy")
322
323
                if privacy_algorithm is not None:
324
                    if not isinstance(privacy_algorithm, SnmpPrivacyAlgorithm):
325
                        raise InvalidArgument(
326
                            "create_credential requires algorithm to be a "
327
                            "SnmpPrivacyAlgorithm instance"
328
                        )
329
330
                    _xmlprivacy.add_element(
331
                        "algorithm", privacy_algorithm.value
332
                    )
333
334
                if privacy_password:
335
                    _xmlprivacy.add_element("password", privacy_password)
336
337
        if credential_type == CredentialType.PGP_ENCRYPTION_KEY:
338
            if not public_key:
339
                raise RequiredArgument(
340
                    "Creating a pgp credential requires a public_key argument"
341
                )
342
343
            _xmlkey = cmd.add_element("key")
344
            _xmlkey.add_element("public", public_key)
345
346
        return self._send_xml_command(cmd)
347
348
    def modify_credential(
0 ignored issues
show
Comprehensibility introduced by
This function exceeds the maximum number of variables (20/15).
Loading history...
349
        self,
350
        credential_id,
351
        *,
352
        name=None,
353
        comment=None,
354
        allow_insecure=None,
355
        certificate=None,
356
        key_phrase=None,
357
        private_key=None,
358
        login=None,
359
        password=None,
360
        auth_algorithm=None,
361
        community=None,
362
        privacy_algorithm=None,
363
        privacy_password=None,
364
        credential_type=None,
365
        public_key=None
366
    ):
367
        """Modifies an existing credential.
368
369
        Arguments:
370
            credential_id (str): UUID of the credential
371
            name (str, optional): Name of the credential
372
            comment (str, optional): Comment for the credential
373
            allow_insecure (boolean, optional): Whether to allow insecure use of
374
                 the credential
375
            certificate (str, optional): Certificate for the credential
376
            key_phrase (str, optional): Key passphrase for the private key
377
            private_key (str, optional): Private key to use for login
378
            login (str, optional): Username for the credential
379
            password (str, optional): Password for the credential
380
            auth_algorithm (SnmpAuthAlgorithm, optional): The authentication
381
                algorithm for SNMP
382
            community (str, optional): The SNMP community
383
            privacy_algorithm (SnmpPrivacyAlgorithm, optional): The privacy
384
                algorithm for SNMP
385
            privacy_password (str, optional): The SNMP privacy password
386
            credential_type (CredentialType, optional): The credential type.
387
            public_key: (str, optional): PGP public key in *armor* plain text
388
                format
389
390
        Returns:
391
            The response. See :py:meth:`send_command` for details.
392
        """
393
        if not credential_id:
394
            raise RequiredArgument(
395
                "modify_credential requires " "a credential_id attribute"
396
            )
397
398
        cmd = XmlCommand("modify_credential")
399
        cmd.set_attribute("credential_id", credential_id)
400
401
        if credential_type:
402
            if not isinstance(credential_type, CredentialType):
403
                raise InvalidArgument(
404
                    "modify_credential requires type to be a CredentialType "
405
                    "instance"
406
                )
407
            cmd.add_element("type", credential_type.value)
408
409
        if comment:
410
            cmd.add_element("comment", comment)
411
412
        if name:
413
            cmd.add_element("name", name)
414
415
        if allow_insecure is not None:
416
            cmd.add_element("allow_insecure", _to_bool(allow_insecure))
417
418
        if certificate:
419
            cmd.add_element("certificate", certificate)
420
421
        if key_phrase or private_key:
422
            if not key_phrase or not private_key:
423
                raise RequiredArgument(
424
                    "modify_credential requires "
425
                    "a key_phrase and private_key arguments"
426
                )
427
            _xmlkey = cmd.add_element("key")
428
            _xmlkey.add_element("phrase", key_phrase)
429
            _xmlkey.add_element("private", private_key)
430
431
        if login:
432
            cmd.add_element("login", login)
433
434
        if password:
435
            cmd.add_element("password", password)
436
437
        if auth_algorithm:
438
            if not isinstance(auth_algorithm, SnmpAuthAlgorithm):
439
                raise InvalidArgument(
440
                    "modify_credential requires auth_algorithm to be a "
441
                    "SnmpAuthAlgorithm instance"
442
                )
443
            cmd.add_element("auth_algorithm", auth_algorithm.value)
444
445
        if community:
446
            cmd.add_element("community", community)
447
448 View Code Duplication
        if privacy_algorithm is not None or privacy_password is not None:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
449
            _xmlprivacy = cmd.add_element("privacy")
450
451
            if privacy_algorithm is not None:
452
                if not isinstance(privacy_algorithm, SnmpPrivacyAlgorithm):
453
                    raise InvalidArgument(
454
                        "modify_credential requires privacy_algorithm to be "
455
                        "a SnmpPrivacyAlgorithm instance"
456
                    )
457
458
                _xmlprivacy.add_element("algorithm", privacy_algorithm.value)
459
460
            if privacy_password is not None:
461
                _xmlprivacy.add_element("password", privacy_password)
462
463
        if public_key:
464
            _xmlkey = cmd.add_element("key")
465
            _xmlkey.add_element("public", public_key)
466
467
        return self._send_xml_command(cmd)
468
469
    def create_tag(
470
        self,
471
        name,
472
        resource_type,
473
        *,
474
        resource_filter=None,
475
        resource_ids=None,
476
        value=None,
477
        comment=None,
478
        active=None
479
    ):
480
        """Create a tag.
481
482
        Arguments:
483
            name (str): Name of the tag. A full tag name consisting of
484
                namespace and predicate e.g. `foo:bar`.
485
            resource_type (str): Entity type the tag is to be attached
486
                to.
487
            resource_filter (str, optional) Filter term to select
488
                resources the tag is to be attached to. Only one of
489
                resource_filter or resource_ids can be provided.
490
            resource_ids (list, optional): IDs of the resources the
491
                tag is to be attached to. Only one of resource_filter or
492
                resource_ids can be provided.
493
            value (str, optional): Value associated with the tag.
494
            comment (str, optional): Comment for the tag.
495
            active (boolean, optional): Whether the tag should be
496
                active.
497
498
        Returns:
499
            The response. See :py:meth:`send_command` for details.
500
        """
501
        if not name:
502
            raise RequiredArgument("create_tag requires name argument")
503
504
        if resource_filter and resource_ids:
505
            raise InvalidArgument(
506
                "create_tag accepts either resource_filter or resource_ids "
507
                "argument"
508
            )
509
510
        if not resource_type:
511
            raise RequiredArgument("create_tag requires resource_type argument")
512
513
        cmd = XmlCommand('create_tag')
514
        cmd.add_element('name', name)
515
516
        _xmlresources = cmd.add_element("resources")
517
        if resource_filter is not None:
518
            _xmlresources.set_attribute("filter", resource_filter)
519
520
        for resource_id in resource_ids or []:
521
            _xmlresources.add_element(
522
                "resource", attrs={"id": str(resource_id)}
523
            )
524
525
        _xmlresources.add_element("type", resource_type)
526
527
        if comment:
528
            cmd.add_element("comment", comment)
529
530
        if value:
531
            cmd.add_element("value", value)
532
533
        if active is not None:
534
            if active:
535
                cmd.add_element("active", "1")
536
            else:
537
                cmd.add_element("active", "0")
538
539
        return self._send_xml_command(cmd)
540
541
    def modify_tag(
542
        self,
543
        tag_id,
544
        *,
545
        comment=None,
546
        name=None,
547
        value=None,
548
        active=None,
549
        resource_action=None,
550
        resource_type=None,
551
        resource_filter=None,
552
        resource_ids=None
553
    ):
554
        """Modifies an existing tag.
555
556
        Arguments:
557
            tag_id (str): UUID of the tag.
558
            comment (str, optional): Comment to add to the tag.
559
            name (str, optional): Name of the tag.
560
            value (str, optional): Value of the tag.
561
            active (boolean, optional): Whether the tag is active.
562
            resource_action (str, optional) Whether to add or remove
563
                resources instead of overwriting. One of '', 'add',
564
                'set' or 'remove'.
565
            resource_type (str, optional): Type of the resources to
566
                which to attach the tag. Required if resource_filter
567
                is set.
568
            resource_filter (str, optional) Filter term to select
569
                resources the tag is to be attached to.
570
            resource_ids (list, optional): IDs of the resources to
571
                which to attach the tag.
572
573
        Returns:
574
            The response. See :py:meth:`send_command` for details.
575
        """
576
        if not tag_id:
577
            raise RequiredArgument("modify_tag requires a tag_id element")
578
579
        cmd = XmlCommand("modify_tag")
580
        cmd.set_attribute("tag_id", str(tag_id))
581
582
        if comment:
583
            cmd.add_element("comment", comment)
584
585
        if name:
586
            cmd.add_element("name", name)
587
588
        if value:
589
            cmd.add_element("value", value)
590
591
        if active is not None:
592
            cmd.add_element("active", _to_bool(active))
593
594
        if resource_action or resource_filter or resource_ids or resource_type:
595
            if resource_filter and not resource_type:
596
                raise RequiredArgument(
597
                    "modify_tag requires resource_type argument when "
598
                    "resource_filter is set"
599
                )
600
601
            _xmlresources = cmd.add_element("resources")
602
            if resource_action is not None:
603
                _xmlresources.set_attribute("action", resource_action)
604
605
            if resource_filter is not None:
606
                _xmlresources.set_attribute("filter", resource_filter)
607
608
            for resource_id in resource_ids or []:
609
                _xmlresources.add_element(
610
                    "resource", attrs={"id": str(resource_id)}
611
                )
612
613
            if resource_type is not None:
614
                _xmlresources.add_element("type", resource_type)
615
616
        return self._send_xml_command(cmd)
617
618
    def clone_ticket(self, ticket_id):
619
        """Clone an existing ticket
620
621
        Arguments:
622
            ticket_id (str): UUID of an existing ticket to clone from
623
624
        Returns:
625
            The response. See :py:meth:`send_command` for details.
626
        """
627
        if not ticket_id:
628
            raise RequiredArgument("clone_ticket requires a ticket_id argument")
629
630
        cmd = XmlCommand("create_ticket")
631
632
        _copy = cmd.add_element("copy", ticket_id)
633
634
        return self._send_xml_command(cmd)
635
636
    def create_ticket(
637
        self, *, result_id, assigned_to_user_id, note, comment=None
638
    ):
639
        """Create a new ticket
640
641
        Arguments:
642
            result_id (str): UUID of the result the ticket applies to
643
            assigned_to_user_id (str): UUID of a user the ticket should be
644
                assigned to
645
            note (str): A note about opening the ticket
646
            comment (str, optional): Comment for the ticket
647
648
        Returns:
649
            The response. See :py:meth:`send_command` for details.
650
        """
651
        if not result_id:
652
            raise RequiredArgument(
653
                "create_ticket requires a result_id argument"
654
            )
655
656
        if not assigned_to_user_id:
657
            raise RequiredArgument(
658
                "create_ticket requires a assigned_to_user_id argument"
659
            )
660
661
        if not note:
662
            raise RequiredArgument("create_ticket requires a note argument")
663
664
        cmd = XmlCommand("create_ticket")
665
666
        _result = cmd.add_element("result")
667
        _result.set_attribute("id", result_id)
668
669
        _assigned = cmd.add_element("assigned_to")
670
        _user = _assigned.add_element("user")
671
        _user.set_attribute("id", assigned_to_user_id)
672
673
        _note = cmd.add_element("open_note", note)
674
675
        if comment:
676
            cmd.add_element("comment", comment)
677
678
        return self._send_xml_command(cmd)
679
680
    def delete_ticket(self, ticket_id, *, ultimate=False):
681
        """Deletes an existing ticket
682
683
        Arguments:
684
            ticket_id (str) UUID of the ticket to be deleted.
685
            ultimate (boolean, optional): Whether to remove entirely,
686
                or to the trashcan.
687
        """
688
        if not ticket_id:
689
            raise RequiredArgument(
690
                "delete_ticket requires a " "ticket_id argument"
691
            )
692
693
        cmd = XmlCommand("delete_ticket")
694
        cmd.set_attribute("ticket_id", ticket_id)
695
        cmd.set_attribute("ultimate", _to_bool(ultimate))
696
697
        return self._send_xml_command(cmd)
698
699
    def get_tickets(self, *, trash=None, filter=None, filter_id=None):
700
        """Request a list of tickets
701
702
        Arguments:
703
            filter (str, optional): Filter term to use for the query
704
            filter_id (str, optional): UUID of an existing filter to use for
705
                the query
706
            trash (boolean, optional): True to request the tickets in the
707
                trashcan
708
        Returns:
709
            The response. See :py:meth:`send_command` for details.
710
        """
711
        cmd = XmlCommand("get_tickets")
712
713
        _add_filter(cmd, filter, filter_id)
714
715
        if not trash is None:
716
            cmd.set_attribute("trash", _to_bool(trash))
717
718
        return self._send_xml_command(cmd)
719
720
    def get_ticket(self, ticket_id):
721
        """Request a single ticket
722
723
        Arguments:
724
            ticket_id (str): UUID of an existing ticket
725
726
        Returns:
727
            The response. See :py:meth:`send_command` for details.
728
        """
729
        if not ticket_id:
730
            raise RequiredArgument("get_ticket requires a ticket_id argument")
731
732
        cmd = XmlCommand("get_tickets")
733
        cmd.set_attribute("ticket_id", ticket_id)
734
        return self._send_xml_command(cmd)
735
736
    def get_vulnerabilities(self, *, filter=None, filter_id=None):
737
        """Request a list of vulnerabilities
738
739
        Arguments:
740
            filter (str, optional): Filter term to use for the query
741
            filter_id (str, optional): UUID of an existing filter to use for
742
                the query
743
        Returns:
744
            The response. See :py:meth:`send_command` for details.
745
        """
746
        cmd = XmlCommand("get_vulns")
747
748
        _add_filter(cmd, filter, filter_id)
749
750
        return self._send_xml_command(cmd)
751
752
    def get_vulnerability(self, vulnerability_id):
753
        """Request a single vulnerability
754
755
        Arguments:
756
            vulnerability_id (str): UUID of an existing vulnerability
757
758
        Returns:
759
            The response. See :py:meth:`send_command` for details.
760
        """
761
        if not vulnerability_id:
762
            raise RequiredArgument(
763
                "get_vulnerability requires a vulnerability_id argument"
764
            )
765
766
        cmd = XmlCommand("get_vulns")
767
        cmd.set_attribute("vuln_id", vulnerability_id)
768
        return self._send_xml_command(cmd)
769
770
    def modify_ticket(
771
        self,
772
        ticket_id,
773
        *,
774
        status=None,
775
        note=None,
776
        assigned_to_user_id=None,
777
        comment=None
778
    ):
779
        """Modify a single ticket
780
781
        Arguments:
782
            ticket_id (str): UUID of an existing ticket
783
            status (TicketStatus, optional): New status for the ticket
784
            note (str, optional): Note for the status change. Required if status
785
                is set.
786
            assigned_to_user_id (str, optional): UUID of the user the ticket
787
                should be assigned to
788
            comment (str, optional): Comment for the ticket
789
790
        Returns:
791
            The response. See :py:meth:`send_command` for details.
792
        """
793
        if not ticket_id:
794
            raise RequiredArgument(
795
                "modify_ticket requires a ticket_id argument"
796
            )
797
798
        if status and not note:
799
            raise RequiredArgument(
800
                "setting a status in modify_ticket requires a note argument"
801
            )
802
803
        if note and not status:
804
            raise RequiredArgument(
805
                "setting a note in modify_ticket requires a status argument"
806
            )
807
808
        cmd = XmlCommand("modify_ticket")
809
        cmd.set_attribute("ticket_id", ticket_id)
810
811
        if assigned_to_user_id:
812
            _assigned = cmd.add_element("assigned_to")
813
            _user = _assigned.add_element("user")
814
            _user.set_attribute("id", assigned_to_user_id)
815
816
        if status:
817
            if not isinstance(status, TicketStatus):
818
                raise InvalidArgument(
819
                    "status argument of modify_ticket needs to be a "
820
                    "TicketStatus"
821
                )
822
823
            cmd.add_element('status', status.value)
824
            cmd.add_element('{}_note'.format(status.name.lower()), note)
825
826
        if comment:
827
            cmd.add_element("comment", comment)
828
829
        return self._send_xml_command(cmd)
830
831
    def create_filter(self, name, *, filter_type=None, comment=None, term=None):
832
        """Create a new filter
833
834
        Arguments:
835
            name (str): Name of the new filter
836
            filter_type (str, optional): Filter for entity type
837
            comment (str, optional): Comment for the filter
838
            term (str, optional): Filter term e.g. 'name=foo'
839
840
        Returns:
841
            The response. See :py:meth:`send_command` for details.
842
        """
843
        if not name:
844
            raise RequiredArgument("create_filter requires a name argument")
845
846
        cmd = XmlCommand("create_filter")
847
        _xmlname = cmd.add_element("name", name)
848
849
        if comment:
850
            cmd.add_element("comment", comment)
851
852
        if term:
853
            cmd.add_element("term", term)
854
855
        if filter_type:
856
            if not isinstance(filter_type, FilterType):
857
                raise InvalidArgument(
858
                    "create_filter requires type to be a FilterType instance. "
859
                    "was {}".format(filter_type)
860
                )
861
862
            cmd.add_element("type", filter_type.value)
863
864
        return self._send_xml_command(cmd)
865
866 View Code Duplication
    def modify_filter(
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
867
        self, filter_id, *, comment=None, name=None, term=None, filter_type=None
868
    ):
869
        """Modifies an existing filter.
870
871
        Arguments:
872
            filter_id (str): UUID of the filter to be modified
873
            comment (str, optional): Comment on filter.
874
            name (str, optional): Name of filter.
875
            term (str, optional): Filter term.
876
            filter_type (FilterType, optional): Resource type filter applies to.
877
878
        Returns:
879
            The response. See :py:meth:`send_command` for details.
880
        """
881
        if not filter_id:
882
            raise RequiredArgument(
883
                "modify_filter requires a filter_id " "attribute"
884
            )
885
886
        cmd = XmlCommand("modify_filter")
887
        cmd.set_attribute("filter_id", filter_id)
888
889
        if comment:
890
            cmd.add_element("comment", comment)
891
892
        if name:
893
            cmd.add_element("name", name)
894
895
        if term:
896
            cmd.add_element("term", term)
897
898
        if filter_type:
899
            if not isinstance(filter_type, FilterType):
900
                raise InvalidArgument(
901
                    "modify_filter requires type to be a FilterType instance. "
902
                    "was {}".format(filter_type)
903
                )
904
            cmd.add_element("type", filter_type.value)
905
906
        return self._send_xml_command(cmd)
907
908
    def create_target(
0 ignored issues
show
Comprehensibility introduced by
This function exceeds the maximum number of variables (17/15).
Loading history...
909
        self,
910
        name,
911
        *,
912
        asset_hosts_filter=None,
913
        hosts=None,
914
        comment=None,
915
        exclude_hosts=None,
916
        ssh_credential_id=None,
917
        ssh_credential_port=None,
918
        smb_credential_id=None,
919
        esxi_credential_id=None,
920
        snmp_credential_id=None,
921
        alive_tests=None,
922
        reverse_lookup_only=None,
923
        reverse_lookup_unify=None,
924
        port_range=None,
925
        port_list_id=None
926
    ):
927
        """Create a new target
928
929
        Arguments:
930
            name (str): Name of the target
931
            asset_hosts_filter (str, optional): Filter to select target host
932
                from assets hosts
933
            hosts (list, optional): List of hosts addresses to scan
934
            exclude_hosts (list, optional): List of hosts addresses to exclude
935
                from scan
936
            comment (str, optional): Comment for the target
937
            ssh_credential_id (str, optional): UUID of a ssh credential to use
938
                on target
939
            ssh_credential_port (int, optional): The port to use for ssh
940
                credential
941
            smb_credential_id (str, optional): UUID of a smb credential to use
942
                on target
943
            snmp_credential_id (str, optional): UUID of a snmp credential to use
944
                on target
945
            esxi_credential_id (str, optional): UUID of a esxi credential to use
946
                on target
947
            alive_tests (str, optional): Which alive tests to use
948
            reverse_lookup_only (boolean, optional): Whether to scan only hosts
949
                that have names
950
            reverse_lookup_unify (boolean, optional): Whether to scan only one
951
                IP when multiple IPs have the same name.
952
            port_range (str, optional): Port range for the target
953
            port_list_id (str, optional): UUID of the port list to use on target
954
955
        Returns:
956
            The response. See :py:meth:`send_command` for details.
957
        """
958
        return super().create_target(
959
            name,
960
            asset_hosts_filter=asset_hosts_filter,
961
            hosts=hosts,
962
            exclude_hosts=exclude_hosts,
963
            comment=comment,
964
            ssh_credential_id=ssh_credential_id,
965
            ssh_credential_port=ssh_credential_port,
966
            smb_credential_id=smb_credential_id,
967
            snmp_credential_id=snmp_credential_id,
968
            esxi_credential_id=esxi_credential_id,
969
            alive_tests=alive_tests,
970
            reverse_lookup_only=reverse_lookup_only,
971
            reverse_lookup_unify=reverse_lookup_unify,
972
            port_range=port_range,
973
            port_list_id=port_list_id,
974
        )
975