def on_message(client: mqtt.Client, userdata: Any, message: mqtt.MQTTMessage) -> None: """Processes messages from MQTT and forwards them to netlink. Arguments: client: the client instance for this callback. userdata: the private user data. message: The MQTT message. """ # TODO(ruairi): Check bounds and raise exception here. logger.debug("Got message %s from MTQQ", message) domain_prefix = load_config().get("domain_prefix") domain = re.search(r"/.*" + domain_prefix + "(\w+)/", message.topic) if not domain: raise ValueError("Could not find a match for %s on %s", domain_prefix, message.topic) domain = domain.group(1) logger.debug("Found domain %s", domain) client = WireGuardClient( public_key=str(message.payload.decode("utf-8")), domain=domain, remove=False, ) logger.info( f"Received create message for key {client.public_key} on domain {domain} with lladdr {client.lladdr}" ) # TODO(ruairi): Verify return type here. logger.debug(link_handler(client))
def main(): """Starts MQTT listener. Raises: DomainsNotInConfig: If no domains were found in configuration file. """ domains = config.load_config().get("domains") if not domains: raise DomainsNotInConfig("Could not locate domains in configuration.") clean_up_worker(domains) mqtt.connect()
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
def main(): """Starts MQTT listener. Raises: DomainsNotInConfig: If no domains were found in configuration file. """ domains = config.load_config().get("domains") if not domains: raise DomainsNotInConfig("Could not locate domains in configuration.") clean_up_threads = [] for domain in domains: print(f"Scheduling cleanup task for {domain}") thread = threading.Thread(target=clean_up_worker, args=(domain.split("ffmuc_")[1], )) thread.start() clean_up_threads.append(thread) mqtt.connect(domains)
def fetch_from_config(var: str) -> Optional[Union[Dict[str, str], str]]: """Fetches values from configuration file. Arguments: var: The variable to fetch from config. Raises: ValueError: If given key cannot be found in configuration. Returns: The given variable from configuration. """ config = load_config() ret = config.get(var) if not ret: raise ValueError("Failed to get %s from configuration, failing", var) return config.get(var)
def on_connect(client: mqtt.Client, userdata: Any, flags, rc) -> None: """Handles MQTT connect and subscribes to topics on connect Arguments: client: the client instance for this callback. userdata: the private user data. flags: The MQTT flags. rc: The MQTT rc. """ logger.debug("Connected with result code " + str(rc)) domains = load_config().get("domains") # Subscribing in on_connect() means that if we lose the connection and # reconnect then subscriptions will be renewed. for domain in domains: topic = f"wireguard/{domain}/+" logger.info(f"Subscribing to topic {topic}") client.subscribe(topic)
def clean_up_worker(domains: List[Text]) -> None: """Wraps flush_workers in a thread for all given domains. Arguments: domains: list of domains. """ logger.debug("Cleaning up the following domains: %s", domains) prefix = config.load_config().get("domain_prefix") for domain in domains: logger.info("Scheduling cleanup task for %s, ", domain) try: cleaned_domain = domain.split(prefix)[1] except IndexError: logger.error( "Cannot strip domain with prefix %s from passed value %s. Skipping cleanup operation", prefix, domain, ) continue thread = threading.Thread(target=flush_workers, args=(cleaned_domain, )) thread.start()