TargetsMixin.get_target()   A
last analyzed

Complexity

Conditions 3

Size

Total Lines 25
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 10
nop 4
dl 0
loc 25
rs 9.9
c 0
b 0
f 0
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
20
from enum import Enum
21
from typing import Any, List, Optional
22
23
from gvm.errors import RequiredArgument, InvalidArgument, InvalidArgumentType
24
from gvm.utils import add_filter, to_bool, to_comma_list
25
from gvm.xml import XmlCommand
26
27
28
class AliveTest(Enum):
29
    """Enum for choosing an alive test"""
30
31
    SCAN_CONFIG_DEFAULT = 'Scan Config Default'
32
    ICMP_PING = 'ICMP Ping'
33
    TCP_ACK_SERVICE_PING = 'TCP-ACK Service Ping'
34
    TCP_SYN_SERVICE_PING = 'TCP-SYN Service Ping'
35
    ARP_PING = 'ARP Ping'
36
    APR_PING = 'ARP Ping'  # Alias for ARP_PING
37
    ICMP_AND_TCP_ACK_SERVICE_PING = 'ICMP & TCP-ACK Service Ping'
38
    ICMP_AND_ARP_PING = 'ICMP & ARP Ping'
39
    TCP_ACK_SERVICE_AND_ARP_PING = 'TCP-ACK Service & ARP Ping'
40
    ICMP_TCP_ACK_SERVICE_AND_ARP_PING = (  # pylint: disable=invalid-name
41
        'ICMP, TCP-ACK Service & ARP Ping'
42
    )
43
    CONSIDER_ALIVE = 'Consider Alive'
44
45
46
def get_alive_test_from_string(
47
    alive_test: Optional[str],
48
) -> Optional[AliveTest]:
49
    """Convert an alive test string into a AliveTest instance"""
50
    if not alive_test:
51
        return None
52
53
    alive_test = alive_test.lower()
54
55
    try:
56
        return AliveTest[
57
            alive_test.replace(',', '')
58
            .replace(' ', '_')
59
            .replace('-', '_')
60
            .replace('&', 'and')
61
            .upper()
62
        ]
63
    except KeyError:
64
        raise InvalidArgument(
65
            argument='alive_test',
66
            function=get_alive_test_from_string.__name__,
67
        ) from None
68
69
70
class TargetsMixin:
71
    def clone_target(self, target_id: str) -> Any:
72
        """Clone an existing target
73
74
        Arguments:
75
            target_id: UUID of an existing target to clone from
76
77
        Returns:
78
            The response. See :py:meth:`send_command` for details.
79
        """
80
        if not target_id:
81
            raise RequiredArgument(
82
                function=self.clone_target.__name__, argument='target_id'
83
            )
84
85
        cmd = XmlCommand("create_target")
86
        cmd.add_element("copy", target_id)
87
        return self._send_xml_command(cmd)
88
89
    def create_target(
90
        self,
91
        name: str,
92
        *,
93
        asset_hosts_filter: Optional[str] = None,
94
        hosts: Optional[List[str]] = None,
95
        comment: Optional[str] = None,
96
        exclude_hosts: Optional[List[str]] = None,
97
        ssh_credential_id: Optional[str] = None,
98
        ssh_credential_port: Optional[int] = None,
99
        smb_credential_id: Optional[str] = None,
100
        esxi_credential_id: Optional[str] = None,
101
        snmp_credential_id: Optional[str] = None,
102
        alive_test: Optional[AliveTest] = None,
103
        reverse_lookup_only: Optional[bool] = None,
104
        reverse_lookup_unify: Optional[bool] = None,
105
        port_range: Optional[str] = None,
106
        port_list_id: Optional[str] = None,
107
    ) -> Any:
108
        """Create a new target
109
110
        Arguments:
111
            name: Name of the target
112
            asset_hosts_filter: Filter to select target host from assets hosts
113
            hosts: List of hosts addresses to scan
114
            exclude_hosts: List of hosts addresses to exclude from scan
115
            comment: Comment for the target
116
            ssh_credential_id: UUID of a ssh credential to use on target
117
            ssh_credential_port: The port to use for ssh credential
118
            smb_credential_id: UUID of a smb credential to use on target
119
            snmp_credential_id: UUID of a snmp credential to use on target
120
            esxi_credential_id: UUID of a esxi credential to use on target
121
            alive_test: Which alive test to use
122
            reverse_lookup_only: Whether to scan only hosts that have names
123
            reverse_lookup_unify: Whether to scan only one IP when multiple IPs
124
                have the same name.
125
            port_range: Port range for the target
126
            port_list_id: UUID of the port list to use on target
127
128
        Returns:
129
            The response. See :py:meth:`send_command` for details.
130
        """
131
132
        cmd = XmlCommand("create_target")
133
        _xmlname = cmd.add_element("name", name)
134
135
        if not name:
136
            raise RequiredArgument(
137
                function=self.create_target.__name__, argument='name'
138
            )
139
140
        if asset_hosts_filter:
141
            cmd.add_element(
142
                "asset_hosts", attrs={"filter": str(asset_hosts_filter)}
143
            )
144
        elif hosts:
145
            cmd.add_element("hosts", to_comma_list(hosts))
146
        else:
147
            raise RequiredArgument(
148
                function=self.create_target.__name__,
149
                argument='hosts or asset_hosts_filter',
150
            )
151
152
        if comment:
153
            cmd.add_element("comment", comment)
154
155
        if exclude_hosts:
156
            cmd.add_element("exclude_hosts", to_comma_list(exclude_hosts))
157
158
        if ssh_credential_id:
159
            _xmlssh = cmd.add_element(
160
                "ssh_credential", attrs={"id": ssh_credential_id}
161
            )
162
            if ssh_credential_port:
163
                _xmlssh.add_element("port", str(ssh_credential_port))
164
165
        if smb_credential_id:
166
            cmd.add_element("smb_credential", attrs={"id": smb_credential_id})
167
168
        if esxi_credential_id:
169
            cmd.add_element("esxi_credential", attrs={"id": esxi_credential_id})
170
171
        if snmp_credential_id:
172
            cmd.add_element("snmp_credential", attrs={"id": snmp_credential_id})
173
174
        if alive_test:
175
            if not isinstance(alive_test, AliveTest):
176
                raise InvalidArgumentType(
177
                    function=self.create_target.__name__,
178
                    argument='alive_test',
179
                    arg_type=AliveTest.__name__,
180
                )
181
182
            cmd.add_element("alive_tests", alive_test.value)
183
184
        if reverse_lookup_only is not None:
185
            cmd.add_element("reverse_lookup_only", to_bool(reverse_lookup_only))
186
187
        if reverse_lookup_unify is not None:
188
            cmd.add_element(
189
                "reverse_lookup_unify", to_bool(reverse_lookup_unify)
190
            )
191
192
        # since 20.08 one of port_range or port_list_id is required!
193
        if not port_range and not port_list_id:
194
            raise RequiredArgument(
195
                function=self.create_target.__name__,
196
                argument='port_range or port_list_id',
197
            )
198
199
        if port_range:
200
            cmd.add_element("port_range", port_range)
201
202
        if port_list_id:
203
            cmd.add_element("port_list", attrs={"id": port_list_id})
204
205
        return self._send_xml_command(cmd)
206
207
    def delete_target(
208
        self, target_id: str, *, ultimate: Optional[bool] = False
209
    ) -> Any:
210
        """Deletes an existing target
211
212
        Arguments:
213
            target_id: UUID of the target to be deleted.
214
            ultimate: Whether to remove entirely, or to the trashcan.
215
        """
216
        if not target_id:
217
            raise RequiredArgument(
218
                function=self.delete_target.__name__, argument='target_id'
219
            )
220
221
        cmd = XmlCommand("delete_target")
222
        cmd.set_attribute("target_id", target_id)
223
        cmd.set_attribute("ultimate", to_bool(ultimate))
224
225
        return self._send_xml_command(cmd)
226
227
    def get_target(
228
        self, target_id: str, *, tasks: Optional[bool] = None
229
    ) -> Any:
230
        """Request a single target
231
232
        Arguments:
233
            target_id: UUID of an existing target
234
            tasks: Whether to include list of tasks that use the target
235
236
        Returns:
237
            The response. See :py:meth:`send_command` for details.
238
        """
239
        cmd = XmlCommand("get_targets")
240
241
        if not target_id:
242
            raise RequiredArgument(
243
                function=self.get_target.__name__, argument='target_id'
244
            )
245
246
        cmd.set_attribute("target_id", target_id)
247
248
        if tasks is not None:
249
            cmd.set_attribute("tasks", to_bool(tasks))
250
251
        return self._send_xml_command(cmd)
252
253 View Code Duplication
    def get_targets(
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
254
        self,
255
        *,
256
        filter_string: Optional[str] = None,
257
        filter_id: Optional[str] = None,
258
        trash: Optional[bool] = None,
259
        tasks: Optional[bool] = None,
260
    ) -> Any:
261
        """Request a list of targets
262
263
        Arguments:
264
            filter_string: Filter term to use for the query
265
            filter_id: UUID of an existing filter to use for the query
266
            trash: Whether to get the trashcan targets instead
267
            tasks: Whether to include list of tasks that use the target
268
269
        Returns:
270
            The response. See :py:meth:`send_command` for details.
271
        """
272
        cmd = XmlCommand("get_targets")
273
274
        add_filter(cmd, filter_string, filter_id)
275
276
        if trash is not None:
277
            cmd.set_attribute("trash", to_bool(trash))
278
279
        if tasks is not None:
280
            cmd.set_attribute("tasks", to_bool(tasks))
281
282
        return self._send_xml_command(cmd)
283
284
    def modify_target(
285
        self,
286
        target_id: str,
287
        *,
288
        name: Optional[str] = None,
289
        comment: Optional[str] = None,
290
        hosts: Optional[List[str]] = None,
291
        exclude_hosts: Optional[List[str]] = None,
292
        ssh_credential_id: Optional[str] = None,
293
        ssh_credential_port: Optional[bool] = None,
294
        smb_credential_id: Optional[str] = None,
295
        esxi_credential_id: Optional[str] = None,
296
        snmp_credential_id: Optional[str] = None,
297
        alive_test: Optional[AliveTest] = None,
298
        reverse_lookup_only: Optional[bool] = None,
299
        reverse_lookup_unify: Optional[bool] = None,
300
        port_list_id: Optional[str] = None,
301
    ) -> Any:
302
        """Modifies an existing target.
303
304
        Arguments:
305
            target_id: ID of target to modify.
306
            comment: Comment on target.
307
            name: Name of target.
308
            hosts: List of target hosts.
309
            exclude_hosts: A list of hosts to exclude.
310
            ssh_credential_id: UUID of SSH credential to use on target.
311
            ssh_credential_port: The port to use for ssh credential
312
            smb_credential_id: UUID of SMB credential to use on target.
313
            esxi_credential_id: UUID of ESXi credential to use on target.
314
            snmp_credential_id: UUID of SNMP credential to use on target.
315
            port_list_id: UUID of port list describing ports to scan.
316
            alive_test: Which alive tests to use.
317
            reverse_lookup_only: Whether to scan only hosts that have names.
318
            reverse_lookup_unify: Whether to scan only one IP when multiple IPs
319
                have the same name.
320
321
        Returns:
322
            The response. See :py:meth:`send_command` for details.
323
        """
324
        if not target_id:
325
            raise RequiredArgument(
326
                function=self.modify_target.__name__, argument='target_id'
327
            )
328
329
        cmd = XmlCommand("modify_target")
330
        cmd.set_attribute("target_id", target_id)
331
332
        if comment:
333
            cmd.add_element("comment", comment)
334
335
        if name:
336
            cmd.add_element("name", name)
337
338
        if hosts:
339
            cmd.add_element("hosts", to_comma_list(hosts))
340
            if exclude_hosts is None:
341
                exclude_hosts = ['']
342
343
        if exclude_hosts:
344
            cmd.add_element("exclude_hosts", to_comma_list(exclude_hosts))
345
346
        if alive_test:
347
            if not isinstance(alive_test, AliveTest):
348
                raise InvalidArgumentType(
349
                    function=self.modify_target.__name__,
350
                    argument='alive_test',
351
                    arg_type=AliveTest.__name__,
352
                )
353
            cmd.add_element("alive_tests", alive_test.value)
354
355
        if ssh_credential_id:
356
            _xmlssh = cmd.add_element(
357
                "ssh_credential", attrs={"id": ssh_credential_id}
358
            )
359
360
            if ssh_credential_port:
361
                _xmlssh.add_element("port", str(ssh_credential_port))
362
363
        if smb_credential_id:
364
            cmd.add_element("smb_credential", attrs={"id": smb_credential_id})
365
366
        if esxi_credential_id:
367
            cmd.add_element("esxi_credential", attrs={"id": esxi_credential_id})
368
369
        if snmp_credential_id:
370
            cmd.add_element("snmp_credential", attrs={"id": snmp_credential_id})
371
372
        if reverse_lookup_only is not None:
373
            cmd.add_element("reverse_lookup_only", to_bool(reverse_lookup_only))
374
375
        if reverse_lookup_unify is not None:
376
            cmd.add_element(
377
                "reverse_lookup_unify", to_bool(reverse_lookup_unify)
378
            )
379
380
        if port_list_id:
381
            cmd.add_element("port_list", attrs={"id": port_list_id})
382
383
        return self._send_xml_command(cmd)
384