Passed
Pull Request — master (#157)
by
unknown
03:23 queued 19s
created

gvm.protocols.gmpv9.Gmp.__create_config()   A

Complexity

Conditions 3

Size

Total Lines 20
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 16
nop 5
dl 0
loc 20
rs 9.6
c 0
b 0
f 0
1
# -*- coding: utf-8 -*-
2
# Copyright (C) 2018 - 2019 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, too-many-lines
20
21
"""
22
Module for communication with gvmd in `Greenbone Management Protocol version 9`_
23
24
.. _Greenbone Management Protocol version 9:
25
    https://docs.greenbone.net/API/GMP/gmp-9.0.html
26
"""
27
import collections
28
import numbers
29
30
from enum import Enum
31
from typing import Any, List, Optional
32
33
from gvm.errors import InvalidArgument, RequiredArgument
34
from gvm.utils import deprecation
35
from gvm.xml import XmlCommand
36
37
from gvm.protocols.gmpv8 import Gmp as Gmpv8, _to_bool, _add_filter
38
from gvm.protocols.gmpv7 import _is_list_like, _to_comma_list
39
40
from . import types
41
from .types import HostsOrdering, EntityType, FilterType
42
from .types import get_entity_type_from_string, get_filter_type_from_string
43
from .types import _UsageType as UsageType
44
45
PROTOCOL_VERSION = (9,)
46
47
48
class Gmp(Gmpv8):
49
50
    types = types
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable types does not seem to be defined.
Loading history...
introduced by
Assigning the same variable 'types' to itself
Loading history...
51
52
    @staticmethod
53
    def get_protocol_version() -> tuple:
54
        """Determine the Greenbone Management Protocol version.
55
56
        Returns:
57
            tuple: Implemented version of the Greenbone Management Protocol
58
        """
59
        return PROTOCOL_VERSION
60
61 View Code Duplication
    def create_audit(
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
62
        self,
63
        name: str,
64
        audit_id: str,
65
        target_id: str,
66
        scanner_id: str,
67
        *,
68
        alterable: Optional[bool] = None,
69
        hosts_ordering: Optional[HostsOrdering] = None,
70
        schedule_id: Optional[str] = None,
71
        alert_ids: Optional[List[str]] = None,
72
        comment: Optional[str] = None,
73
        schedule_periods: Optional[int] = None,
74
        observers: Optional[List[str]] = None,
75
        preferences: Optional[dict] = None
76
    ) -> Any:
77
        """Create a new audit task
78
79
        Arguments:
80
            name: Name of the new audit
81
            audit_id: UUID of scan config to use by the audit
82
            target_id: UUID of target to be scanned
83
            scanner_id: UUID of scanner to use for scanning the target
84
            comment: Comment for the audit
85
            alterable: Whether the task should be alterable
86
            alert_ids: List of UUIDs for alerts to be applied to the audit
87
            hosts_ordering: The order hosts are scanned in
88
            schedule_id: UUID of a schedule when the audit should be run.
89
            schedule_periods: A limit to the number of times the audit will be
90
                scheduled, or 0 for no limit
91
            observers: List of names or ids of users which should be allowed to
92
                observe this audit
93
            preferences: Name/Value pairs of scanner preferences.
94
95
        Returns:
96
            The response. See :py:meth:`send_command` for details.
97
        """
98
99
        self.__create_task(
100
            name=name,
101
            config_id=audit_id,
102
            target_id=target_id,
103
            scanner_id=scanner_id,
104
            usage_type=UsageType.AUDIT,  # pylint: disable=W0212
105
            function=self.create_audit.__name__,
106
            alterable=alterable,
107
            hosts_ordering=hosts_ordering,
108
            schedule_id=schedule_id,
109
            alert_ids=alert_ids,
110
            comment=comment,
111
            schedule_periods=schedule_periods,
112
            observers=observers,
113
            preferences=preferences,
114
        )
115
116
    def create_config(self, config_id: str, name: str) -> Any:
117
        """Create a new scan config
118
        Arguments:
119
            config_id: UUID of the existing scan config
120
            name: Name of the new scan config
121
122
        Returns:
123
            The response. See :py:meth:`send_command` for details.
124
        """
125
        self.__create_config(
126
            config_id=config_id,
127
            name=name,
128
            usage_type=UsageType.SCAN,  # pylint: disable=W0212
129
            function=self.create_config.__name__,
130
        )
131
132
    def create_policy(self, policy_id: str, name: str) -> Any:
133
        """Create a new policy config
134
        Arguments:
135
            policy_id: UUID of the existing policy config
136
            name: Name of the new scan config
137
138
        Returns:
139
            The response. See :py:meth:`send_command` for details.
140
        """
141
        self.__create_config(
142
            config_id=policy_id,
143
            name=name,
144
            usage_type=UsageType.POLICY,  # pylint: disable=W0212
145
            function=self.create_policy.__name__,
146
        )
147
148 View Code Duplication
    def create_task(
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
149
        self,
150
        name: str,
151
        config_id: str,
152
        target_id: str,
153
        scanner_id: str,
154
        *,
155
        alterable: Optional[bool] = None,
156
        hosts_ordering: Optional[HostsOrdering] = None,
157
        schedule_id: Optional[str] = None,
158
        alert_ids: Optional[List[str]] = None,
159
        comment: Optional[str] = None,
160
        schedule_periods: Optional[int] = None,
161
        observers: Optional[List[str]] = None,
162
        preferences: Optional[dict] = None
163
    ) -> Any:
164
        """Create a new scan task
165
166
        Arguments:
167
            name: Name of the task
168
            config_id: UUID of scan config to use by the task
169
            target_id: UUID of target to be scanned
170
            scanner_id: UUID of scanner to use for scanning the target
171
            comment: Comment for the task
172
            alterable: Whether the task should be alterable
173
            alert_ids: List of UUIDs for alerts to be applied to the task
174
            hosts_ordering: The order hosts are scanned in
175
            schedule_id: UUID of a schedule when the task should be run.
176
            schedule_periods: A limit to the number of times the task will be
177
                scheduled, or 0 for no limit
178
            observers: List of names or ids of users which should be allowed to
179
                observe this task
180
            preferences: Name/Value pairs of scanner preferences.
181
182
        Returns:
183
            The response. See :py:meth:`send_command` for details.
184
        """
185
        self.__create_task(
186
            name=name,
187
            config_id=config_id,
188
            target_id=target_id,
189
            scanner_id=scanner_id,
190
            usage_type=UsageType.SCAN,  # pylint: disable=W0212
191
            function=self.create_task.__name__,
192
            alterable=alterable,
193
            hosts_ordering=hosts_ordering,
194
            schedule_id=schedule_id,
195
            alert_ids=alert_ids,
196
            comment=comment,
197
            schedule_periods=schedule_periods,
198
            observers=observers,
199
            preferences=preferences,
200
        )
201
202 View Code Duplication
    def create_tls_certificate(
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
203
        self,
204
        name: str,
205
        certificate: str,
206
        *,
207
        comment: Optional[str] = None,
208
        copy: Optional[str] = None,
209
        trust: Optional[bool] = None
210
    ) -> Any:
211
        """Create a new TLS certificate
212
213
        Arguments:
214
            comment: Comment for the TLS certificate.
215
            name: Name of the TLS certificate, defaulting to the MD5 fingerprint
216
            copy: The UUID of an existing TLS certificate
217
            trust: Whether the certificate is trusted.
218
            certificate: The Base64 encoded certificate data (x.509 DER or PEM).
219
220
        Returns:
221
            The response. See :py:meth:`send_command`for details.
222
        """
223
        if not name:
224
            raise RequiredArgument(
225
                argument='name', function=self.create_tls_certificate.__name__
226
            )
227
        if not certificate:
228
            raise RequiredArgument(
229
                argument="certificate",
230
                function=self.create_tls_certificate.__name__,
231
            )
232
233
        cmd = XmlCommand("create_tls_certificate")
234
235
        if comment:
236
            cmd.add_element("comment", comment)
237
238
        if copy:
239
            cmd.add_element("copy", copy)
240
241
        cmd.add_element("name", name)
242
        cmd.add_element("certificate", certificate)
243
244
        if trust:
245
            cmd.add_element("trust", _to_bool(trust))
246
247
        return self._send_xml_command(cmd)
248
249
    def get_tls_certificates(
250
        self,
251
        *,
252
        filter: Optional[str] = None,
253
        filter_id: Optional[str] = None,
254
        include_certificate_data: Optional[bool] = None
255
    ) -> Any:
256
        """Request a list of TLS certificates
257
258
        Arguments:
259
            filter: Filter term to use for the query
260
            filter_id: UUID of an existing filter to use for the query
261
262
        Returns:
263
            The response. See :py:meth:`send_command` for details.
264
        """
265
266
        cmd = XmlCommand("get_tls_certificates")
267
268
        _add_filter(cmd, filter, filter_id)
269
270
        if include_certificate_data is not None:
271
            cmd.set_attribute(
272
                "include_certificate_data", _to_bool(include_certificate_data)
273
            )
274
275
        return self._send_xml_command(cmd)
276
277 View Code Duplication
    def modify_tls_certificate(
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
278
        self,
279
        tls_certificate_id: str,
280
        *,
281
        name: Optional[str] = None,
282
        comment: Optional[str] = None,
283
        trust: Optional[bool] = None
284
    ) -> Any:
285
        """Modifies an existing TLS certificate.
286
287
        Arguments:
288
            tls_certificate_id: UUID of the TLS certificate to be modified.
289
            name: Name of the TLS certificate, defaulting to the MD5 fingerprint
290
            comment: Comment for the TLS certificate.
291
            trust: Whether the certificate is trusted.
292
293
        Returns:
294
            The response. See :py:meth:`send_command` for details.
295
        """
296
        if not tls_certificate_id:
297
            raise RequiredArgument(
298
                argument="tls_certificate_id",
299
                function=self.modify_tls_certificate.__name__,
300
            )
301
302
        cmd = XmlCommand("modify_tls_certificate")
303
        cmd.set_attribute("tls_certificate_id", str(tls_certificate_id))
304
305
        if comment:
306
            cmd.add_element("comment", comment)
307
308
        if name:
309
            cmd.add_element("name", name)
310
311
        if trust:
312
            cmd.add_element("trust", _to_bool(trust))
313
314
        return self._send_xml_command(cmd)
315
316
    def clone_tls_certificate(self, tls_certificate_id: str) -> Any:
317
        """Modifies an existing TLS certificate.
318
319
        Arguments:
320
            tls_certificate_id: The UUID of an existing TLS certificate
321
322
        Returns:
323
            The response. See :py:meth:`send_command` for details.
324
        """
325
        if not tls_certificate_id:
326
            raise RequiredArgument(
327
                argument="tls_certificate_id",
328
                function=self.modify_tls_certificate.__name__,
329
            )
330
331
        cmd = XmlCommand("create_tls_certificate")
332
333
        cmd.add_element("copy", tls_certificate_id)
334
335
        return self._send_xml_command(cmd)
336
337
    def __create_task(
338
        self,
339
        name: str,
340
        config_id: str,
341
        target_id: str,
342
        scanner_id: str,
343
        usage_type: types._UsageType,  # pylint: disable=W0212
344
        function: str,
345
        *,
346
        alterable: Optional[bool] = None,
347
        hosts_ordering: Optional[HostsOrdering] = None,
348
        schedule_id: Optional[str] = None,
349
        alert_ids: Optional[List[str]] = None,
350
        comment: Optional[str] = None,
351
        schedule_periods: Optional[int] = None,
352
        observers: Optional[List[str]] = None,
353
        preferences: Optional[dict] = None
354
    ) -> Any:
355
        if not name:
356
            raise RequiredArgument(
357
                "{} requires a name argument".format(function)
358
            )
359
360
        if not config_id:
361
            raise RequiredArgument(
362
                "{} requires a config_id argument".format(function)
363
            )
364
365
        if not target_id:
366
            raise RequiredArgument(
367
                "{} requires a target_id argument".format(function)
368
            )
369
370
        if not scanner_id:
371
            raise RequiredArgument(
372
                "{} requires a scanner_id argument".format(function)
373
            )
374
375
        # don't allow to create a container task with create_task
376
        if target_id == '0':
377
            raise InvalidArgument(
378
                'Invalid argument {} for target_id'.format(target_id)
379
            )
380
381
        cmd = XmlCommand("create_task")
382
        cmd.add_element("name", name)
383
        cmd.add_element("usage_type", usage_type.value)
384
        cmd.add_element("config", attrs={"id": config_id})
385
        cmd.add_element("target", attrs={"id": target_id})
386
        cmd.add_element("scanner", attrs={"id": scanner_id})
387
388
        if comment:
389
            cmd.add_element("comment", comment)
390
391
        if not alterable is None:
392
            cmd.add_element("alterable", _to_bool(alterable))
393
394
        if hosts_ordering:
395
            if not isinstance(hosts_ordering, HostsOrdering):
396
                raise InvalidArgument(
397
                    function="create_task", argument="hosts_ordering"
398
                )
399
            cmd.add_element("hosts_ordering", hosts_ordering.value)
400
401
        if alert_ids:
402
            if isinstance(alert_ids, str):
403
                deprecation(
404
                    "Please pass a list as alert_ids parameter to {}. "
405
                    "Passing a string is deprecated and will be removed in "
406
                    "future.".format(function)
407
                )
408
409
                # if a single id is given as a string wrap it into a list
410
                alert_ids = [alert_ids]
411
            if _is_list_like(alert_ids):
412
                # parse all given alert id's
413
                for alert in alert_ids:
414
                    cmd.add_element("alert", attrs={"id": str(alert)})
415
416 View Code Duplication
        if schedule_id:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
417
            cmd.add_element("schedule", attrs={"id": schedule_id})
418
419
            if schedule_periods is not None:
420
                if (
421
                    not isinstance(schedule_periods, numbers.Integral)
422
                    or schedule_periods < 0
423
                ):
424
                    raise InvalidArgument(
425
                        "schedule_periods must be an integer greater or equal "
426
                        "than 0"
427
                    )
428
                cmd.add_element("schedule_periods", str(schedule_periods))
429
430
        if observers is not None:
431
            if not _is_list_like(observers):
432
                raise InvalidArgument("obeservers argument must be a list")
433
434
            # gvmd splits by comma and space
435
            # gvmd tries to lookup each value as user name and afterwards as
436
            # user id. So both user name and user id are possible
437
            cmd.add_element("observers", _to_comma_list(observers))
438
439
        if preferences is not None:
440
            if not isinstance(preferences, collections.abc.Mapping):
441
                raise InvalidArgument('preferences argument must be a dict')
442
443
            _xmlprefs = cmd.add_element("preferences")
444
            for pref_name, pref_value in preferences.items():
445
                _xmlpref = _xmlprefs.add_element("preference")
446
                _xmlpref.add_element("scanner_name", pref_name)
447
                _xmlpref.add_element("value", str(pref_value))
448
449
        return self._send_xml_command(cmd)
450
451
    def __create_config(
452
        self,
453
        config_id: str,
454
        name: str,
455
        usage_type: types._UsageType,  # pylint: disable=W0212
456
        function: str,
457
    ) -> Any:
458
        if not name:
459
            raise RequiredArgument("{} requires name argument".format(function))
460
461
        if not config_id:
462
            raise RequiredArgument(
463
                "{} requires config_id argument".format(function)
464
            )
465
466
        cmd = XmlCommand("create_config")
467
        cmd.add_element("copy", config_id)
468
        cmd.add_element("name", name)
469
        cmd.add_element("usage_type", usage_type.value)
470
        return self._send_xml_command(cmd)
471