Passed
Pull Request — master (#122)
by Juan José
02:21 queued 59s
created

ospd.parser.CliParser.__init__()   B

Complexity

Conditions 1

Size

Total Lines 80
Code Lines 63

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 63
nop 2
dl 0
loc 80
rs 8.2109
c 0
b 0
f 0

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
# Copyright (C) 2019 Greenbone Networks GmbH
2
#
3
# SPDX-License-Identifier: GPL-2.0-or-later
4
#
5
# This program is free software; you can redistribute it and/or
6
# modify it under the terms of the GNU General Public License
7
# as published by the Free Software Foundation; either version 2
8
# of the License, or (at your option) any later version.
9
#
10
# This program is distributed in the hope that it will be useful,
11
# but WITHOUT ANY WARRANTY; without even the implied warranty of
12
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
# GNU General Public License for more details.
14
#
15
# You should have received a copy of the GNU General Public License
16
# along with this program; if not, write to the Free Software
17
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18
19
import argparse
20
import logging
21
from pathlib import Path
22
23
from ospd.config import Config
24
25
# Default file locations as used by a OpenVAS default installation
26
DEFAULT_KEY_FILE = "/usr/var/lib/gvm/private/CA/serverkey.pem"
27
DEFAULT_CERT_FILE = "/usr/var/lib/gvm/CA/servercert.pem"
28
DEFAULT_CA_FILE = "/usr/var/lib/gvm/CA/cacert.pem"
29
30
DEFAULT_PORT = 1234
31
DEFAULT_ADDRESS = "0.0.0.0"
32
DEFAULT_NICENESS = 10
33
34
DEFAULT_CONFIG_PATH = '~/.config/ospd.conf'
35
DEFAULT_UNIX_SOCKET_PATH = "/tmp/ospd-openvas.sock"
36
37
ParserType = argparse.ArgumentParser
38
Arguments = argparse.Namespace
39
40
logger = logging.getLogger(__name__)
41
42
class CliParser:
43
44
    def __init__(self, description):
45
        """ Create a command-line arguments parser for OSPD. """
46
        self._name = description
47
        parser = argparse.ArgumentParser(description=description)
48
49
        parser.add_argument(
50
            '--version', action='store_true', help='Print version then exit.'
51
        )
52
53
        parser.add_argument(
54
            '-s',
55
            '--config',
56
            nargs='?',
57
            default=DEFAULT_CONFIG_PATH,
58
            help='Configuration file path (default: %(default)s)',
59
        )
60
61
        parser.add_argument(
62
            '-p',
63
            '--port',
64
            default=DEFAULT_PORT,
65
            type=self.network_port,
66
            help='TCP Port to listen on. Default: %(default)s',
67
        )
68
        parser.add_argument(
69
            '-b',
70
            '--bind-address',
71
            default=DEFAULT_ADDRESS,
72
            dest='address',
73
            help='Address to listen on. Default: %(default)s',
74
        )
75
        parser.add_argument(
76
            '-u',
77
            '--unix-socket',
78
            default=DEFAULT_UNIX_SOCKET_PATH,
79
            help='Unix file socket to listen on.'
80
        )
81
        parser.add_argument(
82
            '-k',
83
            '--key-file',
84
            default=DEFAULT_KEY_FILE,
85
            help='Server key file. Default: {0}'.format(DEFAULT_KEY_FILE),
86
        )
87
        parser.add_argument(
88
            '-c',
89
            '--cert-file',
90
            default=DEFAULT_CERT_FILE,
91
            help='Server cert file. Default: %(default)s',
92
        )
93
        parser.add_argument(
94
            '--ca-file',
95
            help='CA cert file. Default: %(default)s',
96
            default=DEFAULT_CA_FILE,
97
        )
98
        parser.add_argument(
99
            '-L',
100
            '--log-level',
101
            default='WARNING',
102
            type=self.log_level,
103
            help='Wished level of logging. Default: %(default)s',
104
        )
105
        parser.add_argument(
106
            '-f',
107
            '--foreground',
108
            action='store_true',
109
            help='Run in foreground and logs all messages to console.',
110
        )
111
        parser.add_argument(
112
            '-l',
113
            '--log-file',
114
            help='Path to the logging file.',
115
        )
116
        parser.add_argument(
117
            '--niceness',
118
            default=DEFAULT_NICENESS,
119
            type=int,
120
            help='Start the scan with the given niceness. Default %(default)s',
121
        )
122
123
        self.parser = parser
124
125
    def network_port(self, string):
126
        """ Check if provided string is a valid network port. """
127
128
        value = int(string)
129
        if not 0 < value <= 65535:
130
            raise argparse.ArgumentTypeError(
131
                'port must be in ]0,65535] interval'
132
            )
133
        return value
134
135
    def log_level(self, string):
136
        """ Check if provided string is a valid log level. """
137
138
        value = getattr(logging, string.upper(), None)
139
        if not isinstance(value, int):
140
            raise argparse.ArgumentTypeError(
141
                'log level must be one of {debug,info,warning,error,critical}'
142
            )
143
        return value
144
145
    def _set_defaults(self, configfilename=None):
146
        self._config = self._load_config(configfilename)
147
        self.parser.set_defaults(**self._config.defaults())
148
149
    def _load_config(self, configfile):
150
        config = Config()
151
152
        if not configfile:
153
            return config
154
155
        configpath = Path(configfile)
156
157
        try:
158
            if not configpath.expanduser().resolve().exists():
159
                logger.debug('Ignoring non existing config file %s', configfile)
160
                return config
161
        except FileNotFoundError:
162
            # we are on python 3.5 and Path.resolve raised a FileNotFoundError
163
            logger.debug('Ignoring non existing config file %s', configfile)
164
            return config
165
166
        try:
167
            config.load(configpath, def_section=self._name)
168
            logger.debug('Loaded config %s', configfile)
169
        except Exception as e:  # pylint: disable=broad-except
170
            raise RuntimeError(
171
                'Error while parsing config file {config}. Error was '
172
                '{message}'.format(config=configfile, message=e)
173
            )
174
175
        return config
176
177
    def parse_arguments(self, args=None):
178
        # Parse args to get the config file path passed as option
179
        _args, _ = self.parser.parse_known_args(args)
180
181
        # Load the defaults from the config file if it exists.
182
        # This override also what it was passed as cmd option.
183
        self._set_defaults(_args.config)
184
        args, _ = self.parser.parse_known_args(args)
185
186
        return args
187
188
def create_parser(description):
189
    return CliParser(description)
190