From 7fd8ca7da77bf928ccba3cc52a55f042d05a0570 Mon Sep 17 00:00:00 2001 From: lare Date: Sat, 3 Dec 2022 23:26:04 +0100 Subject: [PATCH] add functionality to edit peerings --- .vscode/launch.json | 3 +- web/backend/main.py | 63 ++++++- web/frontend/peerings-edit.html | 296 ++++++++++++++++++++++++++++++++ web/frontend/static/style.css | 8 +- 4 files changed, 360 insertions(+), 10 deletions(-) create mode 100644 web/frontend/peerings-edit.html diff --git a/.vscode/launch.json b/.vscode/launch.json index 6b05b4b..3c079fc 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -5,8 +5,9 @@ "type": "python", "request": "launch", "program": "${file}", + "cwd": "${workspaceFolder}/web/", "console": "integratedTerminal", - "justMyCode": false + "justMyCode": true } ] } diff --git a/web/backend/main.py b/web/backend/main.py index bcca087..73aa493 100644 --- a/web/backend/main.py +++ b/web/backend/main.py @@ -101,11 +101,14 @@ class PeeringManager: except KeyError: return {} - def add_peering(self, mnt, asn, node, wg_key, endpoint=None, ipv6ll=None, ipv4=None, ipv6=None): + def add_peering(self, mnt, asn, node, wg_key, endpoint=None, ipv6ll=None, ipv4=None, ipv6=None, bgp_mp=True, bgp_enh=True): + # check if this MNT already has a/this asn try: if not asn in self.peerings["mnter"][mnt]: + # ... and add it if it hasn't self.peerings[mnt].append(asn) except KeyError: + # ... and cerate it if it doesn't have any yet self.peerings["mnter"][mnt] = [asn] try: if not asn in self.peerings["asn"]: @@ -116,10 +119,34 @@ class PeeringManager: # deny more than one peering per ASN to one node for peering in self.peerings["asn"][asn]: if peering["node"] == node: return False - self.peerings["asn"][asn].append({"MNT":mnt,"ASN":asn, "node": node, "wg_key":wg_key, "endpoint": endpoint,"ipv6ll":ipv6ll,"ipv4":ipv4,"ipv6":ipv6}) + + self.peerings["asn"][asn].append({"MNT":mnt,"ASN":asn, "node": node, "wg_key":wg_key, "endpoint": endpoint,"ipv6ll":ipv6ll,"ipv4":ipv4,"ipv6":ipv6, "bgp_mp":bgp_mp, "bgp_enh":bgp_enh}) self._save_peerings() return True + def update_peering(self, mnt, asn, node, wg_key, endpoint=None, ipv6ll=None, ipv4=None, ipv6=None, bgp_mp=True, bgp_enh=True): + # check if this MNT already has a/this asn + try: + if not asn in self.peerings["mnter"][mnt]: + # ... and add it if it hasn't + self.peerings[mnt].append(asn) + except KeyError: + # ... and cerate it if it doesn't have any yet + self.peerings["mnter"][mnt] = [asn] + try: + if not asn in self.peerings["asn"]: + return False + except KeyError: + return False + + success = False + for pNr in range(len(self.peerings["asn"][asn])): + if self.peerings["asn"][asn][pNr]["node"] == node: + self.peerings["asn"][asn][pNr] = {"MNT":mnt,"ASN":asn, "node": node, "wg_key":wg_key, "endpoint": endpoint,"ipv6ll":ipv6ll,"ipv4":ipv4,"ipv6":ipv6, "bgp_mp":bgp_mp, "bgp_enh":bgp_enh} + success = True + if not success: return False + self._save_peerings() + return True config = Config() @@ -160,7 +187,9 @@ def check_peering_data(form): else: new_peering["peer-v6"] = None new_peering["bgp-mp"] = form["bgp-multi-protocol"] if "bgp-multi-protocol" in form else "off" + new_peering["bgp-mp"] = True if new_peering["bgp-mp"] else False new_peering["bgp-enh"] = form["bgp-extended-next-hop"] if "bgp-extended-next-hop" in form else "off" + new_peering["bgp-enh"] = True if new_peering["bgp-enh"] else False #new_peering[""] = form["peer-wgkey"] except ValueError as e: print(f"error: {e.args}") @@ -332,12 +361,33 @@ def peerings_delete(): def peerings_edit(): print(session) if request.method == "GET": + mnt_peerings = peerings.get_peerings_by_mnt(session["login"]) + # print(mnt_peerings) if "node" in request.args and request.args["node"] in config["nodes"]: - return render_template("peerings-new.html", config=config, selected_node=request.args["node"], peerings=peerings) + selected_peering = None + for p in mnt_peerings: + if p["node"] == request.args["node"] and p["ASN"] == request.args["asn"]: + selected_peering = p + print(p) + break + return render_template("peerings-edit.html", session=session, config=config, mnt_peerings=mnt_peerings, selected_peering=selected_peering) else: - return render_template("peerings-new.html", session=session,config=config, peerings=peerings) + return render_template("peerings-edit.html", session=session, config=config, mnt_peerings=mnt_peerings, selected_peering=None) elif request.method == "POST": + print(request.args) + print(request.form) + if not "node" in request.args or not request.args["node"]: + return render_template("peerings-edit.html", session=session,config=config, peerings=peerings, msg="no node specified, please click one of the buttons above") + peering_valid, peering_or_msg = check_peering_data(request.form) + print(peering_valid) + print(peering_or_msg) + if not peering_valid: + return render_template("peerings-edit.html", session=session,config=config, peerings=peerings, msg=peering_or_msg), 400 + if not peerings.update_peering(session["user-data"]["mnt"], session["user-data"]["asn"], request.args["node"], peering_or_msg["peer-wgkey"], peering_or_msg["peer-endpoint"], peering_or_msg["peer-v6ll"], peering_or_msg["peer-v4"], peering_or_msg["peer-v6"], peering_or_msg["bgp-mp"], peering_or_msg["bgp-enh"]): + return render_template("peerings-edit.html", session=session,config=config, peerings=peerings, msg="such a peering doesn't exist(yet)"), 400 + + return redirect(f"{config['base-dir']}peerings") return f"{request.method} /peerings/edit?{str(request.args)}{str(request.form)}" @app.route("/peerings/new", methods=["GET","POST"]) @auth_required() @@ -358,12 +408,11 @@ def peerings_new(): if not peering_valid: return render_template("peerings-new.html", session=session,config=config, peerings=peerings, msg=peering_or_msg), 400 - if not peerings.add_peering(session["user-data"]["mnt"], session["user-data"]["asn"], request.args["node"], peering_or_msg["peer-wgkey"], peering_or_msg["peer-endpoint"], peering_or_msg["peer-v6ll"], peering_or_msg["peer-v4"], peering_or_msg["peer-v6"]): + if not peerings.add_peering(session["user-data"]["mnt"], session["user-data"]["asn"], request.args["node"], peering_or_msg["peer-wgkey"], peering_or_msg["peer-endpoint"], peering_or_msg["peer-v6ll"], peering_or_msg["peer-v4"], peering_or_msg["peer-v6"], peering_or_msg["bgp-mp"], peering_or_msg["bgp-enh"]): return render_template("peerings-new.html", session=session,config=config, peerings=peerings, msg="this ASN already has a peering with the requested node"), 400 return redirect(f"{config['base-dir']}peerings") - return """
creating peerings is not (yet) implemented
return""" - return f"{request.method} /peerings/new {str(request.args)}{str(request.form)}" + @app.route("/peerings", methods=["GET","POST","DELETE"]) @auth_required() def peerings_view(): diff --git a/web/frontend/peerings-edit.html b/web/frontend/peerings-edit.html new file mode 100644 index 0000000..558be93 --- /dev/null +++ b/web/frontend/peerings-edit.html @@ -0,0 +1,296 @@ +{% extends 'base.html' %} + +{% block content %} + + +
+ {% for peering in mnt_peerings %} + + + {% if selected_node == peering['node'] %} + {% set selected_peering = peering %} + {% endif %} + + {% endfor %} +
+
+
{% if msg %}{{msg}}{%endif%}
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Wireguard

BGP

MultiProtocol
extended next hop
+ + +
+
+ +

wg-quick:

+
+[Interface] 
+PrivateKey = <your private key> +ListenPort = 2{{config["ASN"][-4:]}} +PostUp = ip address add .../32 peer {% if selected_node %}{{config["nodes"][selected_node]["internal-v4"]}} {% else %} ... {% endif %}
PostUp = ip address add .../128 peer {% if selected_node %}{{config["nodes"][selected_node]["internal-v6"]}} {% else %} ... {% endif %}
PostUp = ip address add .../128 peer {% if selected_node %}{{config["nodes"][selected_node]["internal-v6ll"]}} {% else %} ... {% endif %} +Table = off + +[Peer] +PublicKey = {% if selected_node %}{{config["nodes"][selected_node]["wg-key"]}}{% else %} ... {% endif %} +Endpoint = {% if selected_node %}{{config["nodes"][selected_node]["endpoint"]}}{% else %} ... {% endif %}:{% if selected_node %}{% if session["user-data"]["asn"].startswith("AS424242") %}5{{session["user-data"]["asn"][-4:]}}{% else %} ... {% endif %}{% else %} ... {% endif %} +AllowedIPs = {% if selected_node %}{{config["nodes"][selected_node]["internal-v6ll"]}} {% else %} ... {% endif %},172.20.0.0/14,172.31.0.0/16,10.0.0.0/8,fd00::/8 +
+ +

bird config:

+
+protocol bgp dn42_{{config["MNT"][:-4].lower()}} from dnpeers {
+    neighbor {% if selected_node %}{{config["nodes"][selected_node]["internal-v6ll"]}} {% else %} ... {% endif %} as {{config["ASN"]}};
+    interface "dn42_{{config["MNT"][:-4].lower()}}";
+    ipv4 {
+        extended next hop on;
+    };
+    ipv6 {
+        extended next hop on;
+    };
+}
+    
+ +
+protocol bgp dn42_{{config["MNT"][:-4].lower()}}_v4 from dnpeers {
+    neighbor {% if selected_node %}{{config["nodes"][selected_node]["internal-v4"]}} {% else %} ... {% endif %} as {{config["ASN"]}};
+    interface "dn42_{{config["MNT"][:-4].lower()}}";
+    ipv4 {
+        
+    };
+protocol bgp dn42_{{config["MNT"][:-4].lower()}}_v6 from dnpeers {
+    neighbor {% if selected_node %}{{config["nodes"][selected_node]["internal-v6ll"]}} {% else %} ... {% endif %} as {{config["ASN"]}}; 
+    neighbor {% if selected_node %}{{config["nodes"][selected_node]["internal-v6"]}} {% else %} ... {% endif %} as {{config["ASN"]}};
+    interface "dn42_{{config["MNT"][:-4].lower()}}";
+    ipv6 {
+        
+    };
+}
+        
+
+
+ + +{% endblock %} \ No newline at end of file diff --git a/web/frontend/static/style.css b/web/frontend/static/style.css index 5404df0..a95d8cd 100644 --- a/web/frontend/static/style.css +++ b/web/frontend/static/style.css @@ -1,7 +1,8 @@ :root { --bg-color: #aaa; - --text-color: black; --other-background: #444; + --text-color: black; + --text-color-dark: white; /* --accent-color: ; */ } @@ -98,7 +99,10 @@ button { border-width: 5px; padding: 10px; } - +button.button-selected{ + background-color: var(--other-background); + color: var(--text-color-dark); +} .peering>* { width:auto; align-items: center;