summaryrefslogtreecommitdiffstats
path: root/remote-https-runner/runner.py
blob: c5505552661b7f3baecdd1d90d77fefd73006a2a (plain)
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
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("/<key>", 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]
    auth_header = request.headers.get('Authorization')
    protocol = request.url.split("://")[0]
    logging.info("User uses protocol {}".format(protocol))
    #if protocol != "https":
    #  return Response("HTTP requests not allowed! Use HTTPS!", status=400)

    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=401)

    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)

    start = time.time()
    output = subprocess.check_output(cmd, shell=True)
    end = time.time()

    output = output.decode("utf-8") if type(output) == bytes else output
    duration = "{:.2f}".format(end - start)

    logging.info("Command output:")
    logging.info(output)
    logging.info("Command duration: {}".format(duration))

    return jsonify({
      "command": cmd,
      "output": str(output),
      "duration": duration
    })

@app.route("/")
def hello():
    return "Welcome to remote HTTPS runner API!"