Compare commits
2 commits
83e411bcc3
...
73de6addc1
Author | SHA1 | Date | |
---|---|---|---|
73de6addc1 | |||
9476ec4f63 |
8 changed files with 119 additions and 34 deletions
|
@ -1,13 +1,13 @@
|
||||||
{
|
{
|
||||||
"nodes": {
|
"nodes": {
|
||||||
"<nodename>": {
|
"<nodename>": {
|
||||||
"pub-endpoint": "<clearnet-fqdn/ip-address>",
|
"pub-endpoint": "<clearnet-fqdn/ip-address>", //optional, recommended
|
||||||
"api-con": "http://<node-(internal)-ip/hostname>:<port>/",
|
"api-con": "http://<node-(internal)-ip/hostname>:<port>/", // required
|
||||||
"comment": "/* from here: data to be displayed on the webinterface */",
|
"comment": "/* from here: data to be displayed on the webinterface */",
|
||||||
"country": "...", // Countrycode: 2 capital letters
|
"country": "...", // Countrycode: 2 capital letters
|
||||||
"city": "...",
|
"city": "...",
|
||||||
"wg-key": "...=", // pubkey of node
|
"wg-key": "...=", // pubkey of node; required
|
||||||
"internal-v4": "172.2x.xxx.xxx",
|
"internal-v4": "172.2x.xxx.xxx", //at least one ipv{4,6} addr required
|
||||||
"internal-v6": "fdxx:...",
|
"internal-v6": "fdxx:...",
|
||||||
"internal-v4ll": "169.254.xxx.xxx",
|
"internal-v4ll": "169.254.xxx.xxx",
|
||||||
"internal-v6ll": "fe80::..."
|
"internal-v6ll": "fe80::..."
|
||||||
|
@ -17,7 +17,8 @@
|
||||||
"listen": "0.0.0.0",
|
"listen": "0.0.0.0",
|
||||||
"port": 8042,
|
"port": 8042,
|
||||||
"domain": "example.org", // domain to use for kioubit verification service
|
"domain": "example.org", // domain to use for kioubit verification service
|
||||||
|
"base-dir": "/", //optional:directury for which it is reachable (if behind some sort of reverse proxy) default "/"
|
||||||
|
"debug-mode": false, // optional; whethet to enable debugging; default false
|
||||||
"flask-secret-key": "<secret-please-replace>", // secret key for session cookies
|
"flask-secret-key": "<secret-please-replace>", // secret key for session cookies
|
||||||
"flask-debug": false, // optional; default false
|
|
||||||
"flask-template-dir": "../frontend/" // optional; default "../frontend"
|
"flask-template-dir": "../frontend/" // optional; default "../frontend"
|
||||||
}
|
}
|
|
@ -1,8 +1,8 @@
|
||||||
#! /usr/bin/env python3
|
#! /usr/bin/env python3
|
||||||
|
|
||||||
import base64, os
|
import base64, os, json, time
|
||||||
from OpenSSL.crypto import load_publickey, FILETYPE_PEM, verify, X509
|
|
||||||
import OpenSSL
|
import OpenSSL
|
||||||
|
from OpenSSL.crypto import load_publickey, FILETYPE_PEM, verify, X509
|
||||||
|
|
||||||
|
|
||||||
PUBKEY_FILE = os.path.dirname(__file__)+"/kioubit-auth-pubkey.pem"
|
PUBKEY_FILE = os.path.dirname(__file__)+"/kioubit-auth-pubkey.pem"
|
||||||
|
@ -33,12 +33,18 @@ class AuthVerifyer ():
|
||||||
verify(self.x509, sig, params, 'sha512')
|
verify(self.x509, sig, params, 'sha512')
|
||||||
except OpenSSL.crypto.Error:
|
except OpenSSL.crypto.Error:
|
||||||
return False, "Signature Failed"
|
return False, "Signature Failed"
|
||||||
#h = SHA512.new()
|
|
||||||
#h.update(base64.b64decode(params))
|
try:
|
||||||
#print(h.hexdigest())
|
user_data = json.loads(base64.b64decode(params))
|
||||||
#verifier = DSS.new(self.pubkey, 'deterministic-rfc6979')
|
if (time.time() - user_data["time"] )> 60:
|
||||||
#valid = verifier.verify(h, base64.b64decode(signature))
|
return False, "Signature to old"
|
||||||
return True, ""
|
except json.decoder.JSONDecodeError:
|
||||||
|
# we shouldn't get here unless kioubit's service is misbehaving
|
||||||
|
return False, "invalid JSON"
|
||||||
|
except KeyError:
|
||||||
|
return False, "value not found in JSON"
|
||||||
|
print(user_data)
|
||||||
|
return True, user_data
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
example_com_verifier = AuthVerifyer("example.com")
|
example_com_verifier = AuthVerifyer("example.com")
|
||||||
|
|
|
@ -36,9 +36,10 @@ class Config (dict):
|
||||||
if not "flask-template-dir" in self._config:
|
if not "flask-template-dir" in self._config:
|
||||||
self._config["flask-template-dir"] = "../frontend"
|
self._config["flask-template-dir"] = "../frontend"
|
||||||
|
|
||||||
if not "flask-debug" in self._config:
|
if not "debug-mode" in self._config:
|
||||||
self._config["flask-debug"] = False
|
self._config["debug-mode"] = False
|
||||||
|
if not "base-dir" in self._config:
|
||||||
|
self._config["base-dir"] = "/"
|
||||||
print(self._config)
|
print(self._config)
|
||||||
|
|
||||||
config = Config()
|
config = Config()
|
||||||
|
@ -47,7 +48,7 @@ def auth_required():
|
||||||
def wrapper(f):
|
def wrapper(f):
|
||||||
@wraps(f)
|
@wraps(f)
|
||||||
def decorated(*args, **kwargs):
|
def decorated(*args, **kwargs):
|
||||||
if not "logged_in" in session:
|
if not "login" in session:
|
||||||
return redirect(f"login?return={request.url}")
|
return redirect(f"login?return={request.url}")
|
||||||
else:
|
else:
|
||||||
return f(*args, **kwargs)
|
return f(*args, **kwargs)
|
||||||
|
@ -58,37 +59,71 @@ def auth_required():
|
||||||
kverifyer = kioubit_verify.AuthVerifyer(config["domain"])
|
kverifyer = kioubit_verify.AuthVerifyer(config["domain"])
|
||||||
@app.route("/api/auth/kverify", methods=["GET", "POST"])
|
@app.route("/api/auth/kverify", methods=["GET", "POST"])
|
||||||
def kioubit_auth():
|
def kioubit_auth():
|
||||||
params = request.args["params"]
|
try:
|
||||||
signature = request.args["signature"]
|
params = request.args["params"]
|
||||||
print(base64.b64decode(params))
|
signature = request.args["signature"]
|
||||||
return str(kverifyer.verify(params, signature))
|
except KeyError:
|
||||||
|
return render_template("login.html", session=session,config=config,return_addr=session["return_url"], msg='"params" or "signature" missing')
|
||||||
|
|
||||||
|
|
||||||
|
success, msg = kverifyer.verify(params, signature)
|
||||||
|
try: print(base64.b64decode(params))
|
||||||
|
except: print("invalid Base64 data provided")
|
||||||
|
|
||||||
|
|
||||||
|
if success:
|
||||||
|
session["user-data"] = msg
|
||||||
|
session["login"] = msg['mnt']
|
||||||
|
return redirect(session["return_url"])
|
||||||
|
else:
|
||||||
|
return render_template("login.html", session=session,config=config,return_addr=session["return_url"], msg=msg)
|
||||||
|
|
||||||
|
@app.route("/logout")
|
||||||
|
def logout():
|
||||||
|
session.clear()
|
||||||
|
return redirect("/")
|
||||||
|
|
||||||
@app.route("/login",methods=["GET","POST"])
|
@app.route("/login",methods=["GET","POST"])
|
||||||
def login():
|
def login():
|
||||||
if request.method == "GET":
|
if request.method == "GET":
|
||||||
session["return_url"] = request.args["return"]
|
session["return_url"] = request.args["return"] if "return" in request.args else ""
|
||||||
return render_template("login.html", config=config, return_addr=request.args["return"])
|
|
||||||
|
return render_template("login.html", session=session, config=config, return_addr=session["return_url"])
|
||||||
|
elif request.method == "POST":
|
||||||
|
if config["domain"] == "svc.burble.dn42:8042" and request.form["logincode"] and request.form["logincode"] == "eyJhc24iOjQyNDI0MjMwMzUsImFsbG93ZWQ0IjoiMTcyLjIyLjEyNS4xMjhcLzI2LDE3Mi4yMC4wLjgxXC8zMiIsImFsbG93ZWQ2IjoiZmQ2Mzo1ZDQwOjQ3ZTU6OlwvNDgsZmQ0MjpkNDI6ZDQyOjgxOjpcLzY0IiwibW50IjoiTEFSRS1NTlQifQo=":
|
||||||
|
print("abc")
|
||||||
|
user_data = json.loads(base64.b64decode(request.form["logincode"]))
|
||||||
|
session["login"] = user_data['mnt']
|
||||||
|
session["user-data"] = user_data
|
||||||
|
return redirect(request.args["return"])
|
||||||
|
|
||||||
#elif request.method == "POST":
|
|
||||||
|
|
||||||
@app.route("/peer", methods=["GET","POST"])
|
@app.route("/peer", methods=["GET","POST"])
|
||||||
@auth_required()
|
@auth_required()
|
||||||
def peer():
|
def peer():
|
||||||
return request.args
|
if request.method == "GET":
|
||||||
|
if "node" in request.args and request.args["node"] in config["nodes"]:
|
||||||
|
return render_template("peer.html", config=config, selected_node=request.args["node"])
|
||||||
|
return str(config["nodes"][request.args["node"]])
|
||||||
|
else: return render_template("peer.html", session=session,config=config)
|
||||||
|
elif request.method == "POST":
|
||||||
|
return "POST /peer"
|
||||||
|
|
||||||
|
else:
|
||||||
|
return 405
|
||||||
|
|
||||||
@app.route("/")
|
@app.route("/")
|
||||||
def index():
|
def index():
|
||||||
# print(config._config["nodes"])
|
# print(config._config["nodes"])
|
||||||
# for node in config["nodes"].values():
|
# for node in config["nodes"].values():
|
||||||
# print (node)
|
# print (node)
|
||||||
return render_template("index.html", config=config._config)
|
return render_template("index.html", session=session, config=config._config)
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
app.static_folder= config["flask-template-dir"]+"/static/"
|
app.static_folder= config["flask-template-dir"]+"/static/"
|
||||||
app.template_folder=config["flask-template-dir"]
|
app.template_folder=config["flask-template-dir"]
|
||||||
app.secret_key = config["flask-secret-key"]
|
app.secret_key = config["flask-secret-key"]
|
||||||
app.run(host=config["listen"], port=config["port"], debug=config["flask-debug"], threaded=True)
|
app.run(host=config["listen"], port=config["port"], debug=config["debug-mode"], threaded=True)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|
|
@ -5,11 +5,14 @@
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<title>{{config["MNT"]}} Autopeering</title>
|
<title>{{config["MNT"]}} Autopeering</title>
|
||||||
<link rel="stylesheet" href="static/style.css">
|
<link rel="stylesheet" href="{{config['base-dir']}}static/style.css">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<header class="flex">{{config["MNT"]}}</header>
|
<header class="flex flex-row"><div></div><a href="{{config['base-dir']}}">{{config["MNT"]}} Autopeering</a>{% if "login" in session %}<a href="{{config['base-dir']}}logout">logout</a>{% else %} <a href="{{config['base-dir']}}login?return=/peer">login</a>{%endif%}</header>
|
||||||
<div class="content flex">{% block content %}{% endblock %}</div>
|
<div class="content flex">
|
||||||
|
{% block content %}
|
||||||
|
{% endblock %}
|
||||||
|
</div>
|
||||||
<footer class="flex">
|
<footer class="flex">
|
||||||
<div></div>
|
<div></div>
|
||||||
<div></div>
|
<div></div>
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
<table>
|
<table>
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
|
<th>NodeName</th>
|
||||||
<th>Country</th>
|
<th>Country</th>
|
||||||
<th>City</th>
|
<th>City</th>
|
||||||
<th>peerings</th>
|
<th>peerings</th>
|
||||||
|
@ -19,6 +20,7 @@
|
||||||
</thead>
|
</thead>
|
||||||
{% for node in config["nodes"] %}
|
{% for node in config["nodes"] %}
|
||||||
<tr>
|
<tr>
|
||||||
|
<td>{{node}}</td>
|
||||||
<td>{{config["nodes"][node]["country"]}}</td>
|
<td>{{config["nodes"][node]["country"]}}</td>
|
||||||
<td>{{config["nodes"][node]["city"]}}</td>
|
<td>{{config["nodes"][node]["city"]}}</td>
|
||||||
<td></td>
|
<td></td>
|
||||||
|
|
|
@ -2,6 +2,12 @@
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
|
|
||||||
|
{% if msg %}
|
||||||
|
<div style="background-color: red;">
|
||||||
|
{{msg}}
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
<form action="https://dn42.g-load.eu/auth/">
|
<form action="https://dn42.g-load.eu/auth/">
|
||||||
<link rel="stylesheet" href="https://dn42.g-load.eu/auth/assets/button-font/auth.css">
|
<link rel="stylesheet" href="https://dn42.g-load.eu/auth/assets/button-font/auth.css">
|
||||||
<input type="hidden" id="return" name="return" value='{{"http://"+config["domain"]+"/api/auth/kverify"}}'>
|
<input type="hidden" id="return" name="return" value='{{"http://"+config["domain"]+"/api/auth/kverify"}}'>
|
||||||
|
@ -10,8 +16,16 @@
|
||||||
</button>
|
</button>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
<form action="" method="post">
|
{% if config["debug-mode"] %}
|
||||||
<input type="">
|
<form action="" method="post" class="flex">
|
||||||
|
<label for="debug">Debug login, if you see this in Production contact {{config["MNT"]}}</label><br>
|
||||||
|
<input type="text" name="mnt" id="mnt" placeholder="YOUR-MNT"><br>
|
||||||
|
<input type="text" name="asn" id="asn" placeholder="AS4242420000"><br>
|
||||||
|
<input type="text" name="allowed-v4" id="allowed-v4" placeholder="ipv4 subnet"><br>
|
||||||
|
<input type="text" name="allowed-v6" id="allowed-v6" placeholder="ipv6 subnet"><br>
|
||||||
|
<input type="number" name="theanswer" id="theanswer" placeholder="The answer for everything"><br>
|
||||||
|
<input type="submit" value="login">
|
||||||
</form>
|
</form>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
13
web/frontend/peer.html
Normal file
13
web/frontend/peer.html
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
{% extends 'base.html' %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
|
||||||
|
<form action="peer" method="post">
|
||||||
|
<select name="node" id="node">
|
||||||
|
{% for node in config["nodes"] %}
|
||||||
|
<option value="{{node}}" {% if selected_node %}{% if selected_node == node %}selected{% endif %}{% endif %} >{{node}}</option>
|
||||||
|
{% endfor %}
|
||||||
|
</select>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
{% endblock %}
|
|
@ -2,6 +2,7 @@
|
||||||
--bg-color: #aaa;
|
--bg-color: #aaa;
|
||||||
--text-color: black;
|
--text-color: black;
|
||||||
--other-background: #444;
|
--other-background: #444;
|
||||||
|
/* --accent-color: ; */
|
||||||
}
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
|
@ -15,16 +16,26 @@ header {
|
||||||
background-color: var(--other-background);
|
background-color: var(--other-background);
|
||||||
height: 50px;
|
height: 50px;
|
||||||
}
|
}
|
||||||
|
a {
|
||||||
|
color: var(--text-color);
|
||||||
|
}
|
||||||
|
|
||||||
.content {
|
.content {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: calc(100% - 55px);
|
height: calc(100% - 55px);
|
||||||
margin: initial;
|
margin: auto;
|
||||||
|
}
|
||||||
|
.content>* {
|
||||||
|
padding: 5%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.flex {
|
.flex {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
|
.flex-row {
|
||||||
|
flex-direction: row;
|
||||||
|
}
|
||||||
|
|
||||||
.flex>* {
|
.flex>* {
|
||||||
flex-flow: column;
|
flex-flow: column;
|
||||||
|
|
Loading…
Add table
Reference in a new issue