Passed
Pull Request — master (#314)
by Jaspar
02:00
created

send-targets.create_xml_tree()   A

Complexity

Conditions 4

Size

Total Lines 13
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 11
nop 1
dl 0
loc 13
rs 9.85
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
import sys
20
from gvm.protocols.gmpv9.types import get_alive_test_from_string
21
22
from lxml import etree
23
24
25
def check_args(args):
26
    len_args = len(args.script) - 1
27
    if len_args != 1:
28
        message = """
29
        This script pulls target data from an xml document and feeds it to \
30
    a desired GSM
31
        One parameter after the script name is required.
32
33
        1. <xml_doc>  -- .xml file containing targets
34
35
        Example:
36
            $ gvm-script --gmp-username name --gmp-password pass \
37
    ssh --hostname <gsm> scripts/send-targets.gmp.py example_file.xml
38
        """
39
        print(message)
40
        quit()
41
42
43
def error_and_exit(msg):
44
    print("Error: {}\n".format(msg), file=sys.stderr)
45
    sys.exit(1)
46
47
48
def yes_or_no(question):
49
    reply = str(input(question + ' (y/n): ')).lower().strip()
50
    if reply[0] == ('y'):
51
        return True
52
    if reply[0] == ('n'):
53
        return False
54
    else:
55
        return yes_or_no("Please enter 'y' or 'n'")
56
57
58
def create_xml_tree(xml_doc):
59
    try:
60
        xml_tree = etree.parse(xml_doc)
61
        xml_tree = xml_tree.getroot()
62
    except IOError as err:
63
        error_and_exit("Failed to read xml_file: {} (exit)".format(str(err)))
64
    except etree.Error as err:
65
        error_and_exit("Failed to parse xml_file: {} (exit)".format(str(err)))
66
67
    if len(xml_tree) == 0:
68
        error_and_exit("XML file is empty (exit)")
69
70
    return xml_tree
71
72
73
def parse_send_xml_tree(gmp, xml_tree):
74
    credential_options = [
75
        'ssh_credential',
76
        'smb_credential',
77
        'esxi_credential',
78
        'snmp_credential',
79
    ]
80
    counter = 1
81
82
    for target in xml_tree.xpath('target'):
83
        keywords = {}  # {'make_unique': True}
84
85
        keywords['name'] = target.find('name').text
86
87
        keywords['hosts'] = target.find('hosts').text.split(',')
88
89
        exclude_hosts = target.find('exclude_hosts').text
90
        if exclude_hosts is not None:
91
            keywords['exclude_hosts'] = exclude_hosts.split(',')
92
93
        comment = target.find('comment').text
94
        if comment is not None:
95
            keywords['comment'] = comment
96
97
        credentials = gmp.get_credentials()[0].xpath("//credential/@id")
98
99
        for credential in credential_options:
100
            cred_id = target.find(credential).xpath('@id')[0]
101
            if cred_id == '':
102
                continue
103
            if cred_id not in credentials:
104
                response = yes_or_no(
105
                    "\nThe credential '{}' for 'target {}' could not be "
106
                    "located...\nWould you like to continue?".format(
107
                        credential, counter
108
                    )
109
                )
110
111
                if response is False:
112
                    print("Terminating...\n")
113
                    quit()
114
                else:
115
                    continue
116
117
            key = '{}_id'.format(credential)
118
            keywords[key] = cred_id
119
            elem_path = target.find(credential)
120
            port = elem_path.find('port')
121
            if port is not None and port.text is not None:
122
                port_key = '{}_port'.format(credential)
123
                keywords[port_key] = elem_path.find('port').text
124
125
        alive_test = get_alive_test_from_string(target.find('alive_tests').text)
126
127
        if alive_test is not None:
128
            keywords['alive_test'] = alive_test
129
130
        reverse_lookup_only = target.find('reverse_lookup_only').text
131
        if reverse_lookup_only == '1':
132
            keywords['reverse_lookup_only'] = 1
133
134
        reverse_lookup_unify = target.find('reverse_lookup_unify').text
135
        if reverse_lookup_unify == '1':
136
            keywords['reverse_lookup_unify'] = 1
137
138
        port_range = target.find('port_range')
139
        if port_range is not None:
140
            keywords['port_range'] = port_range.text
141
142
        if target.xpath('port_list/@id') is not None:
143
            port_list = {}
144
            port_list = target.xpath('port_list/@id')[0]
145
            keywords['port_list_id'] = port_list
146
147
        print(keywords)
148
149
        gmp.create_target(**keywords)
150
151
        counter += 1
152
153
154
def main(gmp, args):
155
    # pylint: disable=undefined-variable
156
157
    check_args(args)
158
159
    xml_doc = args.script[1]
160
161
    print('\nSending targets...')
162
163
    xml_tree = create_xml_tree(xml_doc)
164
    parse_send_xml_tree(gmp, xml_tree)
165
166
    print('\n  Target(s) created!\n')
167
168
169
if __name__ == '__gmp__':
170
    main(gmp, args)  # pylint: disable=undefined-variable
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable gmp does not seem to be defined.
Loading history...
Comprehensibility Best Practice introduced by
The variable args does not seem to be defined.
Loading history...
171