Passed
Push — master ( b02297...fb8335 )
by
unknown
02:26 queued 54s
created

gmp.clients.cli   A

Complexity

Total Complexity 17

Size/Duplication

Total Lines 255
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 156
dl 0
loc 255
rs 10
c 0
b 0
f 0
wmc 17

1 Function

Rating   Name   Duplication   Size   Complexity  
F main() 0 181 17
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 configparser
21
import getpass
22
import logging
23
import os.path
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 CheckCommandTransform
34
35
__version__ = get_version()
36
37
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...
38
39
HELP_TEXT = """
40
    gvm-cli {version} (C) 2017 Greenbone Networks GmbH
41
42
    This program is a command line tool to access services via
43
    GMP (Greenbone Management Protocol).
44
45
    Examples:
46
47
    gvm-cli socket --xml "<get_version/>"
48
    gvm-cli socket --xml "<commands><authenticate><credentials><username>myuser</username><password>mypass</password></credentials></authenticate><get_tasks/></commands>"
49
    gvm-cli socket --gmp-username foo --gmp-password foo < myfile.xml
50
51
    Further Information about GMP see here:
52
    http://docs.greenbone.net/index.html#api_documentation
53
    Note: "GMP" was formerly known as "OMP".
54
55
    This program is free software: you can redistribute it and/or modify
56
    it under the terms of the GNU General Public License as published by
57
    the Free Software Foundation, either version 3 of the License, or
58
    (at your option) any later version.
59
60
    This program is distributed in the hope that it will be useful,
61
    but WITHOUT ANY WARRANTY; without even the implied warranty of
62
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
63
    GNU General Public License for more details.
64
65
    You should have received a copy of the GNU General Public License
66
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
67
    """.format(version=__version__)
68
69
70
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 (19/15).
Loading history...
71
72
    parser = argparse.ArgumentParser(
73
        prog='gvm-cli',
74
        description=HELP_TEXT,
75
        formatter_class=argparse.RawTextHelpFormatter,
76
        add_help=False,
77
        epilog="""
78
usage: gvm-cli [-h] [--version] [connection_type] ...
79
   or: gvm-cli connection_type --help""")
80
81
    subparsers = parser.add_subparsers(metavar='[connection_type]')
82
    subparsers.required = True
83
    subparsers.dest = 'connection_type'
84
85
    parser.add_argument(
86
        '-h', '--help', action='help',
87
        help='Show this help message and exit.')
88
89
    parent_parser = argparse.ArgumentParser(add_help=False)
90
    parent_parser.add_argument(
91
        '-c', '--config', nargs='?', const='~/.config/gvm-tools.conf',
92
        help='Configuration file path. Default: ~/.config/gvm-tools.conf')
93
    args, remaining_args = parent_parser.parse_known_args()
94
95
    defaults = {
96
        'gmp_username': '',
97
        'gmp_password': ''
98
    }
99
100
    # Retrieve data from config file
101
    if args.config:
102
        try:
103
            config = configparser.SafeConfigParser()
104
            path = os.path.expanduser(args.config)
105
            config.read(path)
106
            defaults = dict(config.items('Auth'))
107
        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...
108
            print(str(e))
109
110
    parent_parser.set_defaults(**defaults)
111
112
    parent_parser.add_argument(
113
        '--timeout', required=False, default=DEFAULT_TIMEOUT, type=int,
114
        help='Wait <seconds> for response or if value is -1, then wait '
115
             'indefinitely. Default: %(default)s.')
116
    parent_parser.add_argument(
117
        '--log', nargs='?', dest='loglevel', const='INFO',
118
        choices=['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL'],
119
        help='Activates logging. Default level: %(default)s.')
120
    parent_parser.add_argument('--gmp-username', help='GMP username.')
121
    parent_parser.add_argument('--gmp-password', help='GMP password.')
122
    parent_parser.add_argument('-X', '--xml', help='The XML request to send.')
123
    parent_parser.add_argument('-r', '--raw', help='Return raw XML.',
124
                               action='store_true', default=False)
125
    parent_parser.add_argument('infile', nargs='?', type=open,
126
                               default=sys.stdin)
127
    parser_ssh = subparsers.add_parser(
128
        'ssh', help='Use SSH connection for gmp service.',
129
        parents=[parent_parser])
130
    parser_ssh.add_argument('--hostname', required=True,
131
                            help='Hostname or IP-Address.')
132
    parser_ssh.add_argument('--port', required=False,
133
                            default=22, help='Port. Default: %(default)s.')
134
    parser_ssh.add_argument('--ssh-user', default='gmp',
135
                            help='SSH Username. Default: %(default)s.')
136
137
    parser_tls = subparsers.add_parser(
138
        'tls', help='Use TLS secured connection for gmp service.',
139
        parents=[parent_parser])
140
    parser_tls.add_argument('--hostname', required=True,
141
                            help='Hostname or IP-Address.')
142
    parser_tls.add_argument('--port', required=False,
143
                            default=DEFAULT_GVM_PORT,
144
                            help='Port. Default: %(default)s.')
145
    parser_tls.add_argument('--certfile', required=False, default=None,
146
                            help='Path to the certificate file.')
147
    parser_tls.add_argument('--keyfile', required=False, default=None,
148
                            help='Path to key certificate file.')
149
    parser_tls.add_argument('--cafile', required=False, default=None,
150
                            help='Path to CA certificate file.')
151
152
    parser_socket = subparsers.add_parser(
153
        'socket', help='Use UNIX-Socket connection for gmp service.',
154
        parents=[parent_parser])
155
    parser_socket.add_argument(
156
        '--sockpath', nargs='?', default=DEFAULT_UNIX_SOCKET_PATH,
157
        help='Depreacted. Use --socketpath instead')
158
    parser_socket.add_argument(
159
        '--socketpath', nargs='?', default=DEFAULT_UNIX_SOCKET_PATH,
160
        help='UNIX-Socket path. Default: %(default)s.')
161
162
    parser.add_argument(
163
        '-V', '--version', action='version',
164
        version='%(prog)s {version}'.format(version=__version__),
165
        help='Show program\'s version number and exit')
166
167
    args = parser.parse_args(remaining_args)
168
169
    # Sets the logging
170
    if args.loglevel is not None:
171
        level = logging.getLevelName(args.loglevel)
172
        logging.basicConfig(filename='gvm-cli.log', level=level)
173
174
    # If timeout value is -1, then the socket has no timeout for this session
175
    if args.timeout == -1:
176
        args.timeout = None
177
178
    xml = ''
179
180
    if args.xml is not None:
181
        xml = args.xml
182
    else:
183
        # If this returns False, then some data are in sys.stdin
184
        if not args.infile.isatty():
185
            try:
186
                xml = args.infile.read()
187
            except (EOFError, BlockingIOError) 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...
188
                print(e)
189
190
    # If no command was given, program asks for one
191
    if len(xml) == 0:
0 ignored issues
show
Unused Code introduced by
Do not use len(SEQUENCE) as condition value
Loading history...
192
        xml = input()
193
194
    # Remove all newlines if the commands come from file
195
    xml = xml.replace('\n', '').replace('\r', '')
196
197
    # Ask for password if none are given
198
    if args.gmp_username and not args.gmp_password:
199
        args.gmp_password = getpass.getpass('Enter password for ' +
200
                                            args.gmp_username + ': ')
201
202
    # Open the right connection. SSH at last for default
203
    if 'socket' in args.connection_type:
204
        socketpath = args.socketpath
205
        if socketpath is None:
206
            socketpath = args.sockpath
207
208
        connection = UnixSocketConnection(
209
            timeout=args.timeout,
210
            path=socketpath
211
        )
212
    elif 'tls' in args.connection_type:
213
        connection = TLSConnection(
214
            timeout=args.timeout,
215
            hostname=args.hostname,
216
            port=args.port,
217
            certfile=args.certfile,
218
            keyfile=args.keyfile,
219
            cafile=args.cafile,
220
        )
221
    else:
222
        connection = SSHConnection(
223
            timeout=args.timeout,
224
            hostname=args.hostname,
225
            port=args.port,
226
            username=args.ssh_user,
227
            password=args.ssh_password
228
        )
229
230
    if args.raw:
231
        transform = None
232
    else:
233
        transform = CheckCommandTransform()
234
235
    gvm = Gmp(connection, transform=transform)
236
237
    if args.gmp_username:
238
        gvm.authenticate(args.gmp_username, args.gmp_password)
239
240
    try:
241
        result = gvm.send_command(xml)
242
243
        print(result)
244
    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...
245
        print(e)
246
        sys.exit(1)
247
248
    gvm.disconnect()
249
250
    sys.exit(0)
251
252
253
if __name__ == '__main__':
254
    main()
255