import os import sys import subprocess import time from flask import Flask, Response, request, jsonify app = Flask(__name__) import logging logging.basicConfig(format='%(asctime)s %(levelname)s - %(message)s', level=logging.INFO) from yaml import load, dump if "CONFIG_PATH" in os.environ: filename = os.environ["CONFIG_PATH"] else: filename = "config.yaml" try: with open(filename) as f: text = f.read() config = load(text) except: print("Could not open file {}".format(filename)) sys.exit(1) config_keys = config.keys() @app.route("/", methods=["POST"]) def key(key): logging.info("User requested route \"{}\"".format(key)) if not key in config_keys: logging.warning("Route \"{}\" does not exist!".format(key)) return Response("", status=404) options = config[key] protocol = request.url.split("://")[0] logging.info("User uses protocol {}".format(protocol)) if protocol != "https": logging.error("Using plain HTTP is strongly discouraged! Please upgrade to HTTPS.") # return Response("HTTP requests not allowed! Use HTTPS!", status=400) auth_header = request.headers.get('Authorization') auth = options["auth"] if auth != auth_header: logging.warning("User request rejected due to incorrect Authorization header!") return Response("", status=401) if request.content_type != "application/json": logging.warning("User request rejected due to incorrect content type (must be application/json)!") return Response("", status=400) content = request.json cmd = options["command"] for content_key in content: cmd = cmd.replace("${" + str(content_key) + "}", content[content_key]) logging.info("User runs command:") logging.info(cmd) success = True start = time.time() try: output = subprocess.check_output(cmd, shell=True) except Exception as e: success = False output = str(e) end = time.time() duration = "{:.2f}".format(end - start) output = output.decode("utf-8") if type(output) == bytes else output output = output.encode("unicode_escape").decode("utf-8") logging.info("Command output:") logging.info(output) logging.info("Command duration: {}".format(duration)) return jsonify({ "command": cmd, "output": str(output), "duration": duration, "success": success }) @app.route("/") def hello(): return "Welcome to remote HTTPS runner API!"