Completed
Push — master ( 2f0167...0bd58c )
by
unknown
15s queued 12s
created

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

Complexity

Conditions 2

Size

Total Lines 20
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

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