diff --git a/docs/ospd-openvas.8 b/docs/ospd-openvas.8 index ea5fd514..0a11545d 100644 --- a/docs/ospd-openvas.8 +++ b/docs/ospd-openvas.8 @@ -57,7 +57,7 @@ Unix file socket to listen on. Default: /var/run/ospd/ospd.sock .TP .BI "-m " SOCKET_MODE ", --socket-mode "SOCKET_MODE -Unix file socket mode. Default: 0o700 +Unix file socket mode. Default: 0o770 .TP .BI "--pid-file "PID_FILE @@ -87,7 +87,7 @@ Desired level of logging. Default: WARNING .TP .BI "-f, --foreground" -Run in foreground and logs all messages to console. +Run in foreground and log all messages to console. .TP .BI "-l " LOG_FILE ", --log-file "LOG_FILE @@ -147,6 +147,14 @@ nasl-cli. Default: openvas .BI "-x, --signature-check" Enable feed signature check. +.TP +.BI "--notus-feed-dir "DIRECTORY +Directory where notus feed is placed. Default: /var/lib/notus/advisories + +.TP +.BI "--disable-notus-hashsum-verification "BOOLEAN +Disable hashsum verification for notus advisories. Default: false + .TP .BI "--list-commands" Display all protocol commands. @@ -159,48 +167,92 @@ configuration file, .I ~/.config/ospd.conf contains these options under the section [OSPD - openvas]: -.IP log_level -Wished level of logging. +.IP log_config +Log configuration file path. -.IP socket_mode -This option defines the permissions on a socket. -It must be set in octal format. E.g. socket_mode = 0o770 +.IP port +TCP port to listen on. + +.IP address +Address to listen on (this corresponds to --bind-address). .IP unix_socket This option specifies the socket path. +.IP socket_mode +This option defines the permissions on a socket. +It must be set in octal format. E.g. socket_mode = 0o770 + .IP pid_file Location of the file for the process ID. +.IP lock_file_dir +Directory where the feed lock file is placed. + +.IP key_file +Server key file. + +.IP cert_file +Server cert file. + +.IP ca_file +CA cert file. + +.IP log_level +Desired level of logging. + +.IP foreground +Set to true to run in foreground and log all messages to console. + .IP log_file Path to the log file. If no log file is given, the system log facility is used by default. -.IP foreground -If this option is set to yes, the daemon logs to the standard output instead of logging -to a file or syslog. +.IP stream_timeout +Set a timeout on socket operations. Default 10 seconds .IP niceness Start the scan with the given niceness. Default 10 -.IP stream_timeout -Set a timeout on socket operations. Default 10 seconds - .IP scaninfo_store_time Time in hours a scan is stored before being considered forgotten and being delete from the scan table. Default 0, disabled. .IP max_scans -Max. amount of parallel task that can be started. Default 0, disabled. - -.IP min_free_mem_scan_queue -Minimum free memory in MB required to run the scan. If no enough free memory is -available, the scan is queued. Default 0, disabled. +Maximum amount of parallel task that can be started. Default 0, disabled. .IP max_queued_scans Maximum number allowed of queued scans before starting to reject new scans. Default 0, disabled. +.IP min_free_mem_scan_queue +Minimum free memory in MB required to run the scan. If insufficient free memory is +available, the scan is queued. Default 0, disabled. + +.IP mqtt_broker_address +Broker address to connect to for MQTT communication. + +.IP mqtt_broker_port +Broker port to connect to for MQTT communication. + +.IP mqtt_broker_username +Username to connect to MQTT broker for MQTT communication. + +.IP mqtt_broker_password +Password to connect to MQTT broker for MQTT communication. + +.IP feed_updater +Sets the method of updating the feed. + +.IP signature_check +Set to true to enable feed signature check. + +.IP notus_feed_dir +Directory where notus feed is placed. + +.IP disable_notus_hashsum_verification +Set to true to disable hashsum verification for notus advisories. + .SH SEE ALSO \fBopenvas(8)\f1, \fBgsad(8)\f1, \fBgvmd(8)\f1, \fBgreenbone-nvt-sync(8)\f1, diff --git a/ospd/config.py b/ospd/config.py index ac4fcab4..94256fe0 100644 --- a/ospd/config.py +++ b/ospd/config.py @@ -15,6 +15,32 @@ logger = logging.getLogger(__name__) +booleankeys = [ + 'foreground', + 'signature_check', + 'disable_notus_hashsum_verification', +] + + +def strtoboolean(value: str) -> bool: + """Convert string *value* to boolean. + + "True", "yes", "on" and "1" are converted to True. + + "False", "no", "off" and "0" are converted to False. + + Comparison is done case insensitive. + + Other values cause ValueError. + """ + trues = set(element.casefold() for element in ["true", "yes", "on", "1"]) + falses = set(element.casefold() for element in ["false", "no", "off", "0"]) + if value.casefold() in trues: + return True + if value.casefold() in falses: + return False + raise ValueError(f"{value} could not be converted to boolean") + class Config: def __init__(self, section: str = 'main') -> None: @@ -29,7 +55,11 @@ def load(self, filepath: Path, def_section: str = 'main') -> None: with path.open() as f: parser.read_file(f) - self._defaults.update(parser.defaults()) + for key, value in parser.defaults().items(): + if key in booleankeys: + self._defaults[key] = strtoboolean(value) + else: + self._defaults[key] = value for key, value in parser.items(def_section): self._config.setdefault(def_section, dict())[key] = value diff --git a/ospd/parser.py b/ospd/parser.py index fe663600..38f984c3 100644 --- a/ospd/parser.py +++ b/ospd/parser.py @@ -119,7 +119,7 @@ def __init__(self, description: str) -> None: '--log-level', default='INFO', type=self.log_level, - help='Wished level of logging. Default: %(default)s', + help='Desired level of logging. Default: %(default)s', ) parser.add_argument( '-f', @@ -163,7 +163,7 @@ def __init__(self, description: str) -> None: default=DEFAULT_MAX_SCAN, type=int, help=( - 'Max. amount of parallel task that can be started. ' + 'Maximum amount of parallel task that can be started. ' 'Default %(default)s, disabled' ), ) @@ -173,7 +173,7 @@ def __init__(self, description: str) -> None: type=int, help=( 'Minimum free memory in MB required to run the scan. ' - 'If no enough free memory is available, the scan is queued. ' + 'If insufficient free memory is available, the scan is queued. ' 'Default %(default)s, disabled' ), ) @@ -204,7 +204,7 @@ def __init__(self, description: str) -> None: help=( 'Broker port to connect to for MQTT communication.' ' Neccessary to get results from Notus-Scanner.' - 'Default %(default)s' + ' Default %(default)s' ), ) parser.add_argument( @@ -213,7 +213,7 @@ def __init__(self, description: str) -> None: type=str, help=( 'Username to connect to MQTT broker for MQTT communication.' - 'Default %(default)s' + ' Default %(default)s' ), ) parser.add_argument( @@ -221,8 +221,8 @@ def __init__(self, description: str) -> None: default=None, type=str, help=( - 'PASSWORD to connect to MQTT broker for MQTT communication.' - 'Default %(default)s' + 'Password to connect to MQTT broker for MQTT communication.' + ' Default %(default)s' ), ) @@ -241,7 +241,7 @@ def __init__(self, description: str) -> None: '--signature-check', default=False, action='store_true', - help=('Enable feed signature check.' ' Default: %(default)s.'), + help=('Enable feed signature check. Default: %(default)s.'), ) self.parser = parser diff --git a/ospd_openvas/gpg_sha_verifier.py b/ospd_openvas/gpg_sha_verifier.py index 2e2da49f..f95db745 100644 --- a/ospd_openvas/gpg_sha_verifier.py +++ b/ospd_openvas/gpg_sha_verifier.py @@ -31,7 +31,7 @@ def __determine_default_gpg_home() -> Path: def __default_gpg_home() -> GPG: """ - __defaultGpgHome tries to load the variable 'GNUPGHOME' or to guess it + __default_gpg_home tries to load the variable 'GNUPGHOME' or to guess it """ manual = os.getenv("GNUPGHOME") diff --git a/ospd_openvas/notus.py b/ospd_openvas/notus.py index 76020159..92e5cb31 100644 --- a/ospd_openvas/notus.py +++ b/ospd_openvas/notus.py @@ -10,6 +10,7 @@ import json import logging +from ospd.config import strtoboolean from ospd.parser import CliParser from ospd_openvas.messages.result import ResultMessage from ospd_openvas.db import OpenvasDB, MainDB @@ -113,12 +114,12 @@ def __init__( self, path: Path, cache: Cache, - disable_hashsum_verification: bool = False, + disable_notus_hashsum_verification: bool = False, ): self.path = path self.cache = cache self._verifier = None - self.disable_hashsum_verification = disable_hashsum_verification + self.disable_hashsum_verification = disable_notus_hashsum_verification def reload_cache(self): if self.loading: @@ -253,9 +254,9 @@ def __init__(self): self.parser.add_argument( '--disable-notus-hashsum-verification', default=False, - type=bool, + type=strtoboolean, help=( - 'Disables hashsum verification for notus advisories.' + 'Disable hashsum verification for notus advisories.' ' %(default)s' ), ) diff --git a/tests/test_argument_parser.py b/tests/test_argument_parser.py index 1df0f1a7..df2c2f2c 100644 --- a/tests/test_argument_parser.py +++ b/tests/test_argument_parser.py @@ -85,6 +85,12 @@ def test_disable_notus_hashsum_verification(self): ) self.assertEqual(args.disable_notus_hashsum_verification, True) + def test_explicitly_enable_notus_hashsum_verification(self): + args = self.parse_args( + '--disable-notus-hashsum-verification false'.split() + ) + self.assertEqual(args.disable_notus_hashsum_verification, False) + def test_defaults(self): args = self.parse_args([]) @@ -101,6 +107,7 @@ def test_defaults(self): self.assertEqual(args.mqtt_broker_address, DEFAULT_MQTT_BROKER_ADDRESS) self.assertEqual(args.mqtt_broker_port, DEFAULT_MQTT_BROKER_PORT) self.assertEqual(args.disable_notus_hashsum_verification, False) + self.assertEqual(args.signature_check, False) class ArgumentParserConfigTestCase(unittest.TestCase): @@ -114,19 +121,35 @@ def test_using_config(self): config_file = str(here / 'testing.conf') args = self.parse_args(['--config', config_file]) + self.assertEqual(args.config, config_file) + self.assertEqual(args.key_file, '/foo/key.pem') + self.assertEqual(args.cert_file, '/foo/cert.pem') + self.assertEqual(args.ca_file, '/foo/ca.pem') self.assertEqual(args.niceness, 666) self.assertEqual(args.log_level, 'DEBUG') + self.assertEqual(args.log_config, '/foo/ospd-logging.conf') + self.assertEqual(args.log_file, '/foo/ospd-openvas.log') self.assertEqual(args.address, '6.6.6.6') self.assertEqual(args.port, 6666) self.assertEqual(args.scaninfo_store_time, 123) - self.assertEqual(args.config, config_file) self.assertEqual(args.unix_socket, '/foo/ospd-openvas.sock') self.assertEqual(args.pid_file, '/foo/ospd-openvas.pid') self.assertEqual(args.lock_file_dir, '/foo/openvas') self.assertEqual(args.mqtt_broker_address, 'foo.bar.com') self.assertEqual(args.mqtt_broker_port, 1234) + self.assertEqual(args.mqtt_broker_username, 'ospd') + self.assertEqual(args.mqtt_broker_password, 'secret') self.assertEqual(args.notus_feed_dir, '/foo/advisories') + self.assertEqual(args.foreground, True) + self.assertEqual(args.socket_mode, '0o700') + self.assertEqual(args.stream_timeout, 20) + self.assertEqual(args.max_scans, 20) + self.assertEqual(args.max_queued_scans, 5) + self.assertEqual(args.min_free_mem_scan_queue, 200) + self.assertEqual(args.feed_updater, 'nasl-cli') + self.assertEqual(args.disable_notus_hashsum_verification, True) + self.assertEqual(args.signature_check, True) @patch('sys.stderr', new_callable=StringIO) def test_not_existing_config(self, _mock): diff --git a/tests/test_config.py b/tests/test_config.py new file mode 100644 index 00000000..eca78326 --- /dev/null +++ b/tests/test_config.py @@ -0,0 +1,44 @@ +# -*- coding: utf-8 -*- +# SPDX-FileCopyrightText: 2014-2023 Greenbone AG +# +# SPDX-License-Identifier: AGPL-3.0-or-later + +"""Test module for configuration.""" + +import unittest + +from ospd.config import strtoboolean + + +class StrtobooleanTestCase(unittest.TestCase): + def test_trues(self) -> None: + self.assertEqual(True, strtoboolean("true")) + self.assertEqual(True, strtoboolean("True")) + self.assertEqual(True, strtoboolean("TRUE")) + self.assertEqual(True, strtoboolean("yes")) + self.assertEqual(True, strtoboolean("Yes")) + self.assertEqual(True, strtoboolean("YES")) + self.assertEqual(True, strtoboolean("on")) + self.assertEqual(True, strtoboolean("On")) + self.assertEqual(True, strtoboolean("ON")) + self.assertEqual(True, strtoboolean("1")) + + def test_falses(self) -> None: + self.assertEqual(False, strtoboolean("false")) + self.assertEqual(False, strtoboolean("False")) + self.assertEqual(False, strtoboolean("FALSE")) + self.assertEqual(False, strtoboolean("no")) + self.assertEqual(False, strtoboolean("No")) + self.assertEqual(False, strtoboolean("NO")) + self.assertEqual(False, strtoboolean("off")) + self.assertEqual(False, strtoboolean("Off")) + self.assertEqual(False, strtoboolean("OFF")) + self.assertEqual(False, strtoboolean("0")) + + def test_illegals(self) -> None: + with self.assertRaises(ValueError): + strtoboolean("fudge") + with self.assertRaises(ValueError): + strtoboolean("lemon") + with self.assertRaises(ValueError): + strtoboolean("melon") diff --git a/tests/testing.conf b/tests/testing.conf index 475e5ef5..8c762e35 100644 --- a/tests/testing.conf +++ b/tests/testing.conf @@ -1,15 +1,28 @@ [OSPD - openvas] log_level = DEBUG -socket_mode = 0o770 +socket_mode = 0o700 unix_socket = /foo/ospd-openvas.sock pid_file = /foo/ospd-openvas.pid +log_config = /foo/ospd-logging.conf log_file = /foo/ospd-openvas.log lock_file_dir = /foo/openvas niceness = 666 key_file = /foo/key.pem +cert_file = /foo/cert.pem +ca_file = /foo/ca.pem address = 6.6.6.6 port = 6666 mqtt_broker_address = foo.bar.com mqtt_broker_port = 1234 +mqtt_broker_username = ospd +mqtt_broker_password = secret notus_feed_dir = /foo/advisories scaninfo_store_time = 123 +foreground = true +stream_timeout = 20 +max_scans = 20 +max_queued_scans = 5 +min_free_mem_scan_queue = 200 +feed_updater = nasl-cli +disable_notus_hashsum_verification = true +signature_check = true