Skip to content

Commit

Permalink
Merge pull request #52 from freifunkMUC/various_fixes
Browse files Browse the repository at this point in the history
Various fixes
  • Loading branch information
awlx authored Sep 7, 2021
2 parents 547796c + bec9ebf commit 5001f80
Show file tree
Hide file tree
Showing 7 changed files with 74 additions and 100 deletions.
3 changes: 1 addition & 2 deletions wgkex.yaml.example
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,10 @@ domains:
- ffmuc_uml_sued
- ffmuc_uml_west
- ffmuc_welt
pubkeys_file: /var/lib/wgke/public.keys
mqtt:
broker_url: broker.example.com
broker_port: 1883
username: user
password: SECRET
keppalive: 5
keepalive: 5
tls: False
149 changes: 63 additions & 86 deletions wgkex/broker/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,6 @@


WG_PUBKEY_PATTERN = re.compile(r"^[A-Za-z0-9+/]{42}[AEIMQUYcgkosw480]=$")
app = None
mqtt = None


@dataclasses.dataclass
Expand Down Expand Up @@ -46,80 +44,77 @@ def from_dict(cls, msg: dict) -> "KeyExchange":
return cls(public_key=public_key, domain=domain)


def main():
global app, mqtt
app = _fetch_app_config()
mqtt = Mqtt(app)
def _fetch_app_config() -> Flask_app:
"""Creates the Flask app from configuration.
Returns:
A created Flask app.
"""
app = Flask(__name__)
# TODO(ruairi): Refactor load_config to return Dataclass.
mqtt_cfg = config.Config.from_dict(config.load_config()).mqtt
app.config["MQTT_BROKER_URL"] = mqtt_cfg.broker_url
app.config["MQTT_BROKER_PORT"] = mqtt_cfg.broker_port
app.config["MQTT_USERNAME"] = mqtt_cfg.username
app.config["MQTT_PASSWORD"] = mqtt_cfg.password
app.config["MQTT_KEEPALIVE"] = mqtt_cfg.keepalive
app.config["MQTT_TLS_ENABLED"] = mqtt_cfg.tls
return app

@app.route("/", methods=["GET"])
def index() -> None:
"""Returns main page"""
return render_template("index.html")

# Keep to be compatible
@app.route("/wg-public-key/<path:key>", methods=["GET"])
def receive_public_key(key: str) -> Tuple[str, int]:
"""Validates a new key and saves to disk.
app = _fetch_app_config()
mqtt = Mqtt(app)

Arguments:
key: The public key.
Returns:
Status message.
"""
if not is_valid_wg_pubkey(key):
return jsonify({"Message": "Invalid Key"}), 400
# TODO(ruairi): Move to env and static variable.
with open("/var/lib/wgkex/public.keys", "a") as pubkeys:
pubkeys.write("%s\n" % key)
return jsonify({"Message": "OK"}), 200

@app.route("/api/v1/wg/key/exchange", methods=["POST"])
def wg_key_exchange() -> Tuple[str, int]:
"""Retrieves a new key and validates.
@app.route("/", methods=["GET"])
def index() -> None:
"""Returns main page"""
return render_template("index.html")

Returns:
Status message.
"""
try:
data = KeyExchange.from_dict(request.get_json(force=True))
except TypeError as ex:
return abort(400, jsonify({"error": {"message": str(ex)}}))

key = data.public_key
domain = data.domain
# in case we want to decide here later we want to publish it only to dedicated gateways
gateway = "all"
print(f"wg_key_exchange: Domain: {domain}, Key:{key}")

pubkey_cfg_file = config.fetch_from_config("pubkeys_file")
if pubkey_cfg_file:
with open(pubkey_cfg_file, "a") as pubkeys:
pubkeys.write(f"{key} {domain}\n")
mqtt.publish(f"wireguard/{domain}/{gateway}", key)
return jsonify({"Message": "OK"}), 200

app.run()
@app.route("/api/v1/wg/key/exchange", methods=["POST"])
def wg_key_exchange() -> Tuple[str, int]:
"""Retrieves a new key and validates.
@mqtt.on_connect()
def handle_mqtt_connect(
client: Mqtt.Client, userdata: bytes, flags: Any, rc: Any
) -> None:
"""Prints status of connect message."""
# TODO(ruairi): Clarify current usage of this function.
print(
"MQTT connected to {}:{}".format(
app.config["MQTT_BROKER_URL"], app.config["MQTT_BROKER_PORT"]
)
Returns:
Status message.
"""
try:
data = KeyExchange.from_dict(request.get_json(force=True))
except TypeError as ex:
return abort(400, jsonify({"error": {"message": str(ex)}}))

key = data.public_key
domain = data.domain
# in case we want to decide here later we want to publish it only to dedicated gateways
gateway = "all"
print(f"wg_key_exchange: Domain: {domain}, Key:{key}")

mqtt.publish(f"wireguard/{domain}/{gateway}", key)
return jsonify({"Message": "OK"}), 200


@mqtt.on_connect()
def handle_mqtt_connect(
client: mqtt_client.Client, userdata: bytes, flags: Any, rc: Any
) -> None:
"""Prints status of connect message."""
# TODO(ruairi): Clarify current usage of this function.
print(
"MQTT connected to {}:{}".format(
app.config["MQTT_BROKER_URL"], app.config["MQTT_BROKER_PORT"]
)
# mqtt.subscribe("wireguard/#")
)
# mqtt.subscribe("wireguard/#")


@mqtt.on_message()
def handle_mqtt_message(
client: Mqtt.Client, userdata: bytes, message: mqtt_client.MQTTMessage
) -> None:
"""Prints message contents."""
# TODO(ruairi): Clarify current usage of this function.
print(f"MQTT message received on {message.topic}: {message.payload.decode()}")
@mqtt.on_message()
def handle_mqtt_message(
client: mqtt_client.Client, userdata: bytes, message: mqtt_client.MQTTMessage
) -> None:
"""Prints message contents."""
# TODO(ruairi): Clarify current usage of this function.
print(f"MQTT message received on {message.topic}: {message.payload.decode()}")


def is_valid_wg_pubkey(pubkey: str) -> str:
Expand Down Expand Up @@ -160,23 +155,5 @@ def is_valid_domain(domain: str) -> str:
return domain


def _fetch_app_config() -> Flask_app:
"""Creates the Flask app from configuration.
Returns:
A created Flask app.
"""
app = Flask(__name__)
# TODO(ruairi): Refactor load_config to return Dataclass.
mqtt_cfg = config.Config.from_dict(config.load_config()).mqtt
app.config["MQTT_BROKER_URL"] = mqtt_cfg.broker_url
app.config["MQTT_BROKER_PORT"] = mqtt_cfg.broker_port
app.config["MQTT_USERNAME"] = mqtt_cfg.username
app.config["MQTT_PASSWORD"] = mqtt_cfg.password
app.config["MQTT_KEEPALIVE"] = mqtt_cfg.keepalive
app.config["MQTT_TLS_ENABLED"] = mqtt_cfg.tls
return app


if __name__ == "__main__":
main()
app.run()
2 changes: 1 addition & 1 deletion wgkex/broker/app_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import app
import sys

_VALID_CFG = "domains:\n- a\n- b\nmqtt:\n broker_port: 1883\n broker_url: mqtt://broker\n keepalive: 5\n password: pass\n tls: true\n username: user\npubkeys_file: some/file\n"
_VALID_CFG = "domains:\n- a\n- b\nmqtt:\n broker_port: 1883\n broker_url: mqtt://broker\n keepalive: 5\n password: pass\n tls: true\n username: user\n"
_INVALID_CFG = "asdasdasdasd"


Expand Down
4 changes: 2 additions & 2 deletions wgkex/config/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
from wgkex.config.config import CONFIG_SCHEMA, load_config
from wgkex.config.config import load_config

__all__ = ["CONFIG_SCHEMA", "load_config"]
__all__ = ["load_config"]
8 changes: 2 additions & 6 deletions wgkex/config/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ def from_dict(cls, mqtt_cfg: Dict[str, str]) -> "MQTT":
broker_url=mqtt_cfg["broker_url"],
username=mqtt_cfg["username"],
password=mqtt_cfg["password"],
tls=mqtt_cfg["broker_url"] if mqtt_cfg["broker_url"] else None,
tls=mqtt_cfg["tls"] if mqtt_cfg["tls"] else False,
broker_port=mqtt_cfg["broker_port"] if mqtt_cfg["broker_port"] else None,
keepalive=mqtt_cfg["keepalive"] if mqtt_cfg["keepalive"] else None,
)
Expand All @@ -57,12 +57,10 @@ class Config:
Attributes:
domains: The list of domains to listen for.
pubkeys_file: The public keys file to use.
mqtt: The MQTT configuration.
"""

domains: List[str]
pubkeys_file: str
mqtt: MQTT

@classmethod
Expand All @@ -74,9 +72,7 @@ def from_dict(cls, cfg: Dict[str, str]) -> "Config":
A Config object.
"""
mqtt_cfg = MQTT.from_dict(cfg["mqtt"])
return cls(
domains=cfg["domains"], pubkeys_file=cfg["pubkeys_file"], mqtt=mqtt_cfg
)
return cls(domains=cfg["domains"], mqtt=mqtt_cfg)


@lru_cache(maxsize=10)
Expand Down
4 changes: 2 additions & 2 deletions wgkex/config/config_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
import config
import yaml

_VALID_CFG = "domains:\n- a\n- b\nmqtt:\n broker_port: 1883\n broker_url: mqtt://broker\n keepalive: 5\n password: pass\n tls: true\n username: user\npubkeys_file: some/file\n"
_INVALID_LINT = "derpmains:\n- a\n- b\nmqtt:\n broker_port: 1883\n broker_url: mqtt://broker\n keepalive: 5\n password: pass\n tls: true\n username: user\npubkeys_file: some/file\n"
_VALID_CFG = "domains:\n- a\n- b\nmqtt:\n broker_port: 1883\n broker_url: mqtt://broker\n keepalive: 5\n password: pass\n tls: true\n username: user\n"
_INVALID_LINT = "derpmains:\n- a\n- b\nmqtt:\n broker_port: 1883\n broker_url: mqtt://broker\n keepalive: 5\n password: pass\n tls: true\n username: user\n"
_INVALID_CFG = "asdasdasdasd"


Expand Down
4 changes: 3 additions & 1 deletion wgkex/worker/mqtt.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,13 @@ def connect(domains: List[str]) -> None:
domains: The domains to connect to.
"""
broker_address = fetch_from_config("mqtt").get("broker_url")
broker_port = fetch_from_config("mqtt").get("broker_port")
broker_keepalive = fetch_from_config("mqtt").get("keepalive")
# TODO(ruairi): Move the hostname to a global variable.
client = mqtt.Client(socket.gethostname())
client.on_message = on_message
print(f"connecting to broker {broker_address}")
client.connect(broker_address)
client.connect(broker_address, port=broker_port, keepalive=broker_keepalive)
for domain in domains:
topic = f"wireguard/{domain}/+"
print(f"Subscribing to topic {topic}")
Expand Down

0 comments on commit 5001f80

Please sign in to comment.