From 6ed06a53acde735d44a58679eddf8089135938df Mon Sep 17 00:00:00 2001 From: Tobias Date: Fri, 9 Nov 2018 11:57:45 +0100 Subject: [PATCH] Adding --config parameter to provide a path to a configuration file for security reasons (issue #2) --- README.md | 15 ++++++++++++- rspamd-influxdb.py | 54 ++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 62 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 74171ce..b19ac25 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,20 @@ Quick and dirty approach to get stats of rspamd out of the webinterface's API into InfluxDB for visualizing using Grafana. ## Usage -`python3 rspamd-influxdb.py https://example.com:1337/ superSecretPassword` +`python3 rspamd-influxdb.py --url "https://example.com:1337" --password "superSecretPassword"` + +You may provide the URL and password by defining the path to a configuration file in order to prevent other users from reading the password in clear text from the process list. To do so you need to provide the `--config $path` argument, e.g. + +`python3 rspamd-influxdb.py --config "~/config.json"` + +The configuration file needs to contain the fields `url` and `password` as valid JSON. An example file could look like this: + +```json +{ + "url": "https://example.com", + "password": "superSecretPassword" +} +``` ## Utilization Use this script call within InfluxData's Telegraf diff --git a/rspamd-influxdb.py b/rspamd-influxdb.py index 73aea44..8760bcc 100644 --- a/rspamd-influxdb.py +++ b/rspamd-influxdb.py @@ -5,16 +5,58 @@ import json import urllib.request parser = argparse.ArgumentParser(description="rspamd web interface statistic fetcher for InfluxDB usage") -parser.add_argument("url", action="store", help="URL to rspamd web interface installation") -parser.add_argument("password", action="store", help="Password for API authentication (same as for graphical login)") +parser.add_argument("--url", action="store", help="URL to rspamd web interface installation") +parser.add_argument("--password", action="store", help="Password for API authentication (same as for graphical login)") +parser.add_argument("--config", action="store", help="Path to the configuration file for the application to use") args = parser.parse_args() -# Make sure we got the trailing slash at the URL -if str.endswith(args.url, "/"): - fetch_url = args.url + "stat?password=" + urllib.parse.quote_plus(args.password) +# Perform some stupid basic validation on the arguments +if (args.url is None and args.password is None) and args.config is None: + parser.error("Please provide --url and --password arguments or the path to a configuration file using --config") + +if (args.url is None and args.password is not None) or (args.url is not None and args.password is None): + parser.error("Please use --url with the --password argument and way round. You may provide the path to a " + "configuration file by only using the --config argument.") + +if args.url is not None and args.password is not None and args.config is not None: + parser.error("Please provide whether --url and --password arguments *or* --config argument.") + +if args.config is not None and (args.url is not None or args.password is not None): + parser.error("Please provide whether --url and --password arguments *or* --config argument.") + +# Basic variable initialization +url = None +password = None + +# Read variables from file if necessary +if args.config is not None: + data = None + + try: + fh = open(args.config, "r") + data = json.load(fh) + except IOError as e: + parser.error("Could not read JSON config from file. Received IOError: " + str(e)) + + if data is not None and ("url" not in data or "password" not in data): + parser.error("Could not read URL and password from JSON configuration. Please see documentation for correct " + "configuration file formatting.") + elif data is None: + parser.error("Something went wrong during parsing of JSON configuration file. Please check your configuration!") + else: + url = data['url'] + password = data['password'] else: - fetch_url = args.url + "/stat?password=" + urllib.parse.quote_plus(args.password) + # Read variable from args + url = args.url + password = args.password + +# Make sure we got the trailing slash at the URL +if str.endswith(url, "/"): + fetch_url = url + "stat?password=" + urllib.parse.quote_plus(password) +else: + fetch_url = url + "/stat?password=" + urllib.parse.quote_plus(password) try: resp = urllib.request.urlopen(fetch_url)