1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189
|
# SPDX-FileCopyrightText: 2021-2024 Greenbone AG
#
# SPDX-License-Identifier: AGPL-3.0-or-later
import argparse
import logging
from pathlib import Path
from typing import Any, Dict
from ..__version__ import __version__
from ..config import Config
ParserType = argparse.ArgumentParser
Arguments = argparse.Namespace
logger = logging.getLogger(__name__)
DEFAULT_CONFIG_FILE = "/etc/gvm/notus-scanner.toml"
DEFAULT_USER_CONFIG_FILE = "~/.config/notus-scanner.toml"
def log_level(string: str) -> str:
"""Check if provided string is a valid log level."""
if not hasattr(logging, string.upper()):
raise argparse.ArgumentTypeError(
"log level must be one of {debug,info,warning,error,critical}"
)
return string.upper()
def _to_defaults(values: Dict[str, Any]) -> Dict[str, Any]:
defaults = {}
for key, value in values.items():
defaults[key.replace("-", "_")] = value
return defaults
class CliParser:
def __init__(self) -> None:
"""Create a command-line arguments parser for Notus Scanner."""
parser = argparse.ArgumentParser(
description="Notus Scanner", add_help=False
)
parser.add_argument(
"--version",
help="Print version then exit.",
action="version",
version=f"%(prog)s {__version__}",
)
parser.add_argument(
"-h",
"--help",
help="Show this help message and exit.",
action="store_true",
)
parser.add_argument(
"-c",
"--config",
nargs="?",
help="Configuration file path. If not set %(prog)s "
f"tries to load {DEFAULT_USER_CONFIG_FILE} and "
f"{DEFAULT_CONFIG_FILE}.",
)
parser.add_argument(
"--pid-file",
help="Location of the file for the process ID "
"(default: %(default)s)",
)
parser.add_argument(
"-l",
"--log-file",
nargs="?",
default=None,
help="Log file path (default: syslog)",
)
parser.add_argument(
"-L",
"--log-level",
type=log_level,
help="Wished level of logging (default: %(default)s)",
)
parser.add_argument(
"-f",
"--foreground",
action="store_true",
help="Run in foreground and logs all messages to console.",
)
parser.add_argument(
"--products-directory",
type=Path,
help=(
"Choose a custom directory that contains product advisory "
"files generated by the Notus Generator. (default: %(default)s)"
),
)
parser.add_argument(
"-b",
"--mqtt-broker-address",
type=str,
help="Hostname or IP address of the MQTT broker. "
"(default: %(default)s)",
)
parser.add_argument(
"-p",
"--mqtt-broker-port",
type=int,
help="Port of the MQTT broker. (default: %(default)s)",
)
parser.add_argument(
"--mqtt-broker-username",
default=None,
type=str,
help=(
"Username to connect to MQTT broker for MQTT communication."
"Default %(default)s"
),
)
parser.add_argument(
"--mqtt-broker-password",
default=None,
type=str,
help=(
"PASSWORD to connect to MQTT broker for MQTT communication."
"Default %(default)s"
),
)
parser.add_argument(
"--disable-hashsum-verification",
type=bool,
default=False,
help="Disables hashsum verification (default: %(default)s)",
)
self.parser = parser
def _set_defaults(self, configfilename=None) -> None:
config_data = self._load_config(configfilename)
self.parser.set_defaults(**_to_defaults(config_data))
def _load_config(self, configfile: str) -> Dict[str, Any]:
config = Config()
use_default = configfile is None
configpath = None
if use_default:
for file in [DEFAULT_USER_CONFIG_FILE, DEFAULT_CONFIG_FILE]:
path = Path(file).expanduser().resolve()
if path.exists():
configpath = path
break
else:
logger.debug(
"Ignoring non existing config file %s", configfile
)
if not configpath:
return config.values()
else:
configpath = Path(configfile).expanduser().resolve()
if not configpath.exists():
logger.warning(
"Ignoring non existing config file %s", configfile
)
return config.values()
config.load(configpath)
logger.debug("Loaded config %s", configfile)
return config.values()
def parse_arguments(self, args=None) -> Arguments:
# Parse args to get the config file path passed as option
known_args, _ = self.parser.parse_known_args(args)
# Load the defaults from the config file if it exists.
# This also override what was passed as cmd option.
self._set_defaults(known_args.config)
if known_args.help:
self.parser.print_help()
self.parser.exit(0)
return self.parser.parse_args(args)
|