diff --git a/metobsapi/common_config.py b/metobsapi/common_config.py index 63280cba2a64c827befafcdd6771ee990250b861..76603e09442635fa9460889d7611f04ad93dfd16 100644 --- a/metobsapi/common_config.py +++ b/metobsapi/common_config.py @@ -2,7 +2,8 @@ JSONIFY_PRETTYPRINT_REGULAR = False if "SECRET_KEY" not in globals(): # we don't do anything with cookies or sessions, set this somewhere secret in the future - SECRET_KEY = "secret!" + # Security: This is expected to be overwritten either via environment variable or sub-configuration + SECRET_KEY = "secret!" # nosec B105 ARCHIVE_ROOT = "/data1/cache" ARCHIVE_URL = "http://metobs.ssec.wisc.edu/pub/cache" @@ -11,5 +12,6 @@ ARCHIVE_URL = "http://metobs.ssec.wisc.edu/pub/cache" INFLUXDB_HOST = "rain01" INFLUXDB_PORT = 8086 INFLUXDB_USER = "root" -INFLUXDB_PASS = "root" +# Security: This is expected to be overwritten either via environment variable or sub-configuration +INFLUXDB_PASS = "root" # nosec B105 INFLUXDB_DB = "metobs" diff --git a/metobsapi/data_api.py b/metobsapi/data_api.py index a753ebd9413b8ad1b1405687ecf863c31685f1cf..baab959a9bd28878e58b3bc22200bf6565b1d9f9 100644 --- a/metobsapi/data_api.py +++ b/metobsapi/data_api.py @@ -1,6 +1,8 @@ import logging from datetime import datetime, timedelta -from xml.dom.minidom import Document + +# Security: Document is only used for creating an XML document, not parsing one +from xml.dom.minidom import Document # nosec B408 import numpy as np import pandas as pd diff --git a/metobsapi/server.py b/metobsapi/server.py index bbf385437c785dc2b7bb17a39799d3719eceaedf..28ccde9e52dbd38af6b00868fa8522c9b60b5336 100644 --- a/metobsapi/server.py +++ b/metobsapi/server.py @@ -1,6 +1,7 @@ import json as builtin_json import logging import os +import sys from datetime import datetime from enum import Enum from urllib.error import URLError @@ -18,10 +19,10 @@ LOG = logging.getLogger(__name__) app = Flask(__name__) # Load custom configuration file is specified -if os.environ.get("METOBSAPI_SETTINGS") is None: - app.config.from_object("metobsapi.common_config") -else: +app.config.from_object("metobsapi.common_config") +if os.environ.get("METOBSAPI_SETTINGS") is not None: app.config.from_pyfile(os.environ.get("METOBSAPI_SETTINGS")) +app.config.from_prefixed_env(prefix="METOBSAPI") # Load json handler and add custom enum encoder @@ -163,14 +164,16 @@ def get_instrument_status(site, inst=None, fmt=None): json_subpath = os.path.join(site, inst, "status.json") # try to load the JSON file from the archive - if not os.path.exists(app.config.get("ARCHIVE_ROOT")): + if not os.path.isfile(app.config.get("ARCHIVE_ROOT")) and app.config.get("ARCHIVE_ROOT").startswith("http"): LOG.warning("Using URL request for status JSON, not meant for operational use") # we aren't on a system with the archive available, fall back to URL # loads directly to the archive base_url = app.config.get("ARCHIVE_URL") json_url = os.path.join(base_url, json_subpath) try: - json_str = urlopen(json_url).read() + # Security: We check to ensure this is an HTTP URL as a base URL. + # The server configuration is also the one setting what the root URL is. + json_str = urlopen(json_url).read() # nosec B310 except URLError: response["status_message"] = "Could not retrieve configured status: {}".format(json_url) json_str = None @@ -196,4 +199,5 @@ def get_instrument_status(site, inst=None, fmt=None): if __name__ == "__main__": app.debug = True - app.run("0.0.0.0", threaded=True) + bind_addr = "0.0.0.0" if len(sys.argv) <= 1 else sys.argv[0] # nosec B104 + app.run(bind_addr, threaded=True)