Passed
Pull Request — master (#117)
by
unknown
02:05
created

gmp.clients.pyshell.get_globals_dict()   A

Complexity

Conditions 1

Size

Total Lines 5
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 5
nop 2
dl 0
loc 5
rs 10
c 0
b 0
f 0
1
# -*- coding: utf-8 -*-
0 ignored issues
show
Coding Style introduced by
This module should have a docstring.

The coding style of this project requires that you add a docstring to this code element. Below, you find an example for methods:

class SomeClass:
    def some_method(self):
        """Do x and return foo."""

If you would like to know more about docstrings, we recommend to read PEP-257: Docstring Conventions.

Loading history...
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
import argparse
20
import code
21
import configparser
22
import logging
23
import os
24
import sys
25
26
from gmp import Gmp, get_version
27
from gmp.connection import (SSHConnection,
28
                            TLSConnection,
29
                            UnixSocketConnection,
30
                            DEFAULT_UNIX_SOCKET_PATH,
31
                            DEFAULT_TIMEOUT,
32
                            DEFAULT_GVM_PORT)
33
from gmp.transform import EtreeCheckCommandTransform
34
35
36
__version__ = get_version()
37
38
logger = logging.getLogger(__name__)
0 ignored issues
show
Coding Style Naming introduced by
The name logger does not conform to the constant naming conventions ((([A-Z_][A-Z0-9_]*)|(__.*__))$).

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
39
40
HELP_TEXT = """
41
    gvm-pyshell {version} (C) 2017 Greenbone Networks GmbH
42
43
    This program is a command line tool to access services
44
    via GMP(Greenbone Management Protocol) and
45
    OSP(Open Scanner Protocol).
46
    It is possible to start a shell like the python interactive
47
    mode where you could type things like "tasks = gmp.get_task".
48
49
    At the moment only these commands are support in the interactive shell:
50
51
    gmp.get_version()
52
    gmp.authenticate([username], [password])
53
    gmp.get_tasks()
54
    gmp.get_reports()
55
    gmp.get_results()
56
    gmp.get_assets()
57
    gmp.get_port_lists()
58
59
    Example:
60
        gmp.authenticate('admin', 'admin')
61
        tasks = gmp.get_tasks()
62
63
        list = tasks.xpath('task')
64
65
        taskid = list[0].attrib
66
67
        load('my_commands.gmp')
68
69
    Good introduction in working with XPath is well described here:
70
    https://www.w3schools.com/xml/xpath_syntax.asp
71
72
    To get out of the shell enter:
73
        Ctrl + D on Linux  or
74
        Ctrl + Z on Windows
75
76
    Further Information about the GMP Protocol can be found at:
77
    http://docs.greenbone.net/index.html#api_documentation
78
    Note: "GMP" was formerly known as "OMP".
79
80
    This program is free software: you can redistribute it and/or modify
81
    it under the terms of the GNU General Public License as published by
82
    the Free Software Foundation, either version 3 of the License, or
83
    (at your option) any later version.
84
85
    This program is distributed in the hope that it will be useful,
86
    but WITHOUT ANY WARRANTY; without even the implied warranty of
87
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
88
    GNU General Public License for more details.
89
90
    You should have received a copy of the GNU General Public License
91
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
92
    """.format(version=__version__)
93
94
95
class Help(object):
0 ignored issues
show
Unused Code introduced by
The variable __class__ seems to be unused.
Loading history...
96
    """Help class to overwrite the help function from python itself.
97
    """
98
99
    def __repr__(self):
100
        # do pwd command
101
        return HELP_TEXT
102
103
104
def main():
0 ignored issues
show
Coding Style introduced by
This function should have a docstring.

The coding style of this project requires that you add a docstring to this code element. Below, you find an example for methods:

class SomeClass:
    def some_method(self):
        """Do x and return foo."""

If you would like to know more about docstrings, we recommend to read PEP-257: Docstring Conventions.

Loading history...
Comprehensibility introduced by
This function exceeds the maximum number of variables (24/15).
Loading history...
105
    parser = argparse.ArgumentParser(
106
        prog='gvm-pyshell',
107
        description=HELP_TEXT,
108
        formatter_class=argparse.RawTextHelpFormatter,
109
        add_help=False,
110
        epilog="""
111
usage: gvm-pyshell [-h] [--version] [connection_type] ...
112
   or: gvm-pyshell connection_type --help""")
113
    subparsers = parser.add_subparsers(metavar='[connection_type]')
114
    subparsers.required = True
115
    subparsers.dest = 'connection_type'
116
117
    parser.add_argument(
118
        '-h', '--help', action='help',
119
        help='Show this help message and exit.')
120
121
    parent_parser = argparse.ArgumentParser(add_help=False)
122
123
    parent_parser.add_argument(
124
        '-c', '--config', nargs='?', const='~/.config/gvm-tools.conf',
125
        help='Configuration file path. Default: ~/.config/gvm-tools.conf')
126
    args_before, remaining_args = parent_parser.parse_known_args()
127
128
    defaults = {
129
        'gmp_username': '',
130
        'gmp_password': ''
131
    }
132
133
    # Retrieve data from config file
134
    if args_before.config:
135
        try:
136
            config = configparser.SafeConfigParser()
137
            path = os.path.expanduser(args_before.config)
138
            config.read(path)
139
            defaults = dict(config.items('Auth'))
140
        except Exception as e: # pylint: disable=broad-except
0 ignored issues
show
Coding Style Naming introduced by
The name e does not conform to the variable naming conventions ((([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$).

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
141
            print(str(e), file=sys.stderr)
142
143
    parent_parser.set_defaults(**defaults)
144
145
    parent_parser.add_argument(
146
        '--timeout', required=False, default=DEFAULT_TIMEOUT, type=int,
147
        help='Wait <seconds> for response or if value -1, then wait '
148
             'continuously. Default: %(default)s')
149
    parent_parser.add_argument(
150
        '--log', nargs='?', dest='loglevel', const='INFO',
151
        choices=['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL'],
152
        help='Activates logging. Default level: INFO.')
153
    parent_parser.add_argument(
154
        '-i', '--interactive', action='store_true', default=False,
155
        help='Start an interactive Python shell.')
156
    parent_parser.add_argument('--gmp-username', help='GMP username.')
157
    parent_parser.add_argument('--gmp-password', help='GMP password.')
158
    parent_parser.add_argument(
159
        'script', nargs='*',
160
        help='Preload gmp script. Example: myscript.gmp.')
161
162
    parser_ssh = subparsers.add_parser(
163
        'ssh', help='Use SSH connection for gmp service.',
164
        parents=[parent_parser])
165
    parser_ssh.add_argument('--hostname', required=True,
166
                            help='Hostname or IP-Address.')
167
    parser_ssh.add_argument('--port', required=False,
168
                            default=22, help='Port. Default: %(default)s.')
169
    parser_ssh.add_argument('--ssh-user', default='gmp',
170
                            help='SSH Username. Default: %(default)s.')
171
172
    parser_tls = subparsers.add_parser(
173
        'tls', help='Use TLS secured connection for gmp service.',
174
        parents=[parent_parser])
175
    parser_tls.add_argument('--hostname', required=True,
176
                            help='Hostname or IP-Address.')
177
    parser_tls.add_argument('--port', required=False,
178
                            default=DEFAULT_GVM_PORT,
179
                            help='Port. Default: %(default)s.')
180
    parser_tls.add_argument('--certfile', required=False, default=None,
181
                            help='Path to the client certificate file.')
182
    parser_tls.add_argument('--keyfile', required=False, default=None,
183
                            help='Path to key certificate file.')
184
    parser_tls.add_argument('--cafile', required=False, default=None,
185
                            help='Path to CA certificate file.')
186
    parser_tls.add_argument('--no-credentials', required=False, default=False,
187
                            help='Use only certificates.')
188
189
    parser_socket = subparsers.add_parser(
190
        'socket', help='Use UNIX-Socket connection for gmp service.',
191
        parents=[parent_parser])
192
    parser_socket.add_argument(
193
        '--sockpath', nargs='?',
194
        help='Depreacted. Use --socketpath instead')
195
    parser_socket.add_argument(
196
        '--socketpath', nargs='?', default=DEFAULT_UNIX_SOCKET_PATH,
197
        help='UNIX-Socket path. Default: %(default)s.')
198
199
    parser.add_argument(
200
        '-V', '--version', action='version',
201
        version='%(prog)s {version}'.format(version=__version__),
202
        help='Show program\'s version number and exit')
203
204
    args = parser.parse_args(remaining_args)
205
206
    # Sets the logging
207
    if args.loglevel is not None:
208
        level = logging.getLevelName(args.loglevel)
209
        logging.basicConfig(filename='gvm-pyshell.log', level=level)
210
211
    # If timeout value is -1, then the socket has no timeout for this session
212
    if args.timeout == -1:
213
        args.timeout = None
214
215
    # Open the right connection. SSH at last for default
216 View Code Duplication
    if 'socket' in args.connection_type:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
217
        socketpath = args.sockpath
218
        if socketpath is None:
219
            socketpath = args.socketpath
220
        else:
221
            print('The --sockpath parameter has been deprecated. Please use '
222
                  '--socketpath instead', file=sys.stderr)
223
224
        connection = UnixSocketConnection(path=socketpath,
225
                                          timeout=args.timeout)
226
    elif 'tls' in args.connection_type:
227
        connection = TLSConnection(
228
            timeout=args.timeout,
229
            hostname=args.hostname,
230
            port=args.port,
231
            certfile=args.certfile,
232
            keyfile=args.keyfile,
233
            cafile=args.cafile,
234
        )
235
    else:
236
        connection = SSHConnection(hostname=args.hostname, port=args.port,
237
                                   timeout=args.timeout, username=args.ssh_user,
238
                                   password='')
239
240
    gmp = Gmp(connection, transform=EtreeCheckCommandTransform())
241
242
    with_script = args.script and len(args.script) > 0
243
    no_script_no_interactive = not args.interactive and not with_script
244
    script_and_interactive = args.interactive and with_script
245
    only_interactive = not with_script and args.interactive
246
    only_script = not args.interactive and with_script
247
248
    global_vars = get_globals_dict(gmp, args)
249
250
    if only_interactive or no_script_no_interactive:
251
        enter_interactive_mode(global_vars)
252
253
    if script_and_interactive or only_script:
254
        script_name = args.script[0]
255
        load(script_name, global_vars)
256
257
    if not only_script:
258
        enter_interactive_mode(global_vars)
259
260
    gmp.disconnect()
261
262
263
def get_globals_dict(gmp, args):
0 ignored issues
show
Coding Style introduced by
This function should have a docstring.

The coding style of this project requires that you add a docstring to this code element. Below, you find an example for methods:

class SomeClass:
    def some_method(self):
        """Do x and return foo."""

If you would like to know more about docstrings, we recommend to read PEP-257: Docstring Conventions.

Loading history...
264
    return {
265
        'gmp': gmp,
266
        'help': Help(),
267
        'args': args,
268
    }
269
270
def enter_interactive_mode(global_vars):
0 ignored issues
show
Coding Style introduced by
This function should have a docstring.

The coding style of this project requires that you add a docstring to this code element. Below, you find an example for methods:

class SomeClass:
    def some_method(self):
        """Do x and return foo."""

If you would like to know more about docstrings, we recommend to read PEP-257: Docstring Conventions.

Loading history...
271
    code.interact(
272
        banner='GVM Interactive Console. Type "help" to get information \
273
about functionality.',
274
        local=dict(global_vars, **locals()))
275
276
277
def load(path, global_vars):
278
    """Loads a file into the interactive console
279
280
    Loads a file into the interactive console and execute it.
281
    TODO: Needs some security checks.
282
283
    Arguments:
284
        path {str} -- Path of file
285
    """
286
    try:
287
        file = open(path, 'r', newline='').read()
288
289
        exec(file, global_vars) # pylint: disable=exec-used
290
    except OSError as e:
0 ignored issues
show
Coding Style Naming introduced by
The name e does not conform to the variable naming conventions ((([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$).

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
291
        print(str(e))
292
293
294
if __name__ == '__main__':
295
    main()
296