commit 2d1841779388136cd0c7e657ef02ae7d023ae252 Author: Dorian Zedler Date: Wed Aug 18 18:48:17 2021 +0200 Initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3af0ccb --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/data diff --git a/backend/__pycache__/dbHelper.cpython-38.pyc b/backend/__pycache__/dbHelper.cpython-38.pyc new file mode 100644 index 0000000..71bdff4 Binary files /dev/null and b/backend/__pycache__/dbHelper.cpython-38.pyc differ diff --git a/backend/__pycache__/mqttClient.cpython-38.pyc b/backend/__pycache__/mqttClient.cpython-38.pyc new file mode 100644 index 0000000..780374b Binary files /dev/null and b/backend/__pycache__/mqttClient.cpython-38.pyc differ diff --git a/backend/dbHelper.py b/backend/dbHelper.py new file mode 100644 index 0000000..8b05a57 --- /dev/null +++ b/backend/dbHelper.py @@ -0,0 +1,96 @@ +import pymysql +import json + +class MaDbHelper: + def __init__(self): + self.mysqlConn = pymysql.connect(host='localhost', + user='root', + passwd='MlmAccess', + db='MlmAccess', + port=4306) + + self.mysqlCur = self.mysqlConn.cursor() + + def _initDb(self): + """ + Generates required tables and users + """ + + """ + CREATE TABLE vmq_auth_acl + ( + mountpoint VARCHAR(10) NOT NULL, + client_id VARCHAR(128) NOT NULL, + username VARCHAR(128) NOT NULL, + password VARCHAR(128), + publish_acl TEXT, + subscribe_acl TEXT, + CONSTRAINT vmq_auth_acl_primary_key PRIMARY KEY (mountpoint, client_id, username) + ) + """ + + def addUser(self, username, password, publishAclPatterns, subscribeAclPatterns): + + if self.userExists(username): + return False + + query = "INSERT INTO `vmq_auth_acl` (`mountpoint`, `client_id`, `username`, `password`, `publish_acl`, `subscribe_acl`) VALUES (%s, %s, %s, PASSWORD(%s), %s, %s);" + + self.mysqlCur.execute( + query, + ( + "", + username, + username, + password, + self._convertAclPatternList(publishAclPatterns), + self._convertAclPatternList(subscribeAclPatterns) + ) + ) + + self.mysqlConn.commit() + + return True + + def userExists(self, username): + query = "SELECT username FROM `vmq_auth_acl` WHERE username=%s" + + self.mysqlCur.execute( + query, + (username) + ) + + result = self.mysqlCur.fetchone() + return result is not None + + + def updateUser(self, username, password, publishAclPatterns, subscribeAclPatterns): + if self.userExists(username): + return self._updateUser(username, password, publishAclPatterns, subscribeAclPatterns) + else: + return False + + def _updateUser(self, username, password, publishAclPatterns, subscribeAclPatterns): + + query = """ + UPDATE `vmq_auth_acl` + SET `password`=PASSWORD(%s), `publish_acl`=%s, `subscribe_acl`=%s + WHERE `username`=%s; + """ + + self.mysqlCur.execute( + query, + ( + password, + self._convertAclPatternList(publishAclPatterns), + self._convertAclPatternList(subscribeAclPatterns), + username + ) + ) + + self.mysqlConn.commit() + + def _convertAclPatternList(self, patternList): + patternMapLabda = lambda pattern: {"pattern": pattern} + patternList = list(map(patternMapLabda, patternList)) + return json.dumps(patternList) \ No newline at end of file diff --git a/backend/mlmAccess.py b/backend/mlmAccess.py new file mode 100644 index 0000000..a8f93d5 --- /dev/null +++ b/backend/mlmAccess.py @@ -0,0 +1,48 @@ +import paho.mqtt.client as mqtt +from dbHelper import MaDbHelper + +class MlmAccess: + def __init__(self): + self._initDb() + self._initMqtt() + + def _initDb(self): + self.db = MaDbHelper() + initUsers = [ + ("backend", "backend", ["mlmAccess/#"], ["mlmAccess/#"]), + ("pair-actor", "pair-actor", ["mlmAccess/pair/request/actor"], ["mlmAccess/pair/response/actor"]) + ] + + for username, password, publishAclPatterns, subscribeAclPatterns in initUsers: + if not self.db.addUser(username, password, publishAclPatterns, subscribeAclPatterns): + self.db.updateUser(username, password, publishAclPatterns, subscribeAclPatterns) + + def _initMqtt(self): + self.mqtt = client = mqtt.Client(client_id="backend") + self.mqtt.username_pw_set("backend", "backend") + + self.mqtt.on_connect = self._mqttOnConnect + self.mqtt.on_message = self._mqttOnMessage + + print("connecting to broker") + print(self.mqtt.connect("localhost", 1883, 60)) + + self.mqtt.loop_forever() + + def _mqttOnConnect(self, client, userdata, flags, rc): + print("Connected with result code "+str(rc)) + + if rc != 0: + print("") + + print(client.subscribe("mlmAccess/pair/request/actor")) + + def _mqttOnMessage(self, client, userdata, message): + print("message received " ,str(message.payload.decode("utf-8"))) + print("message topic=",message.topic) + print("message qos=",message.qos) + print("message retain flag=",message.retain) + + +if __name__ == "__main__": + MlmAccess() \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..b09ee00 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,45 @@ +services: + broker: + image: vernemq/vernemq:1.11.0 + environment: + - DOCKER_VERNEMQ_ACCEPT_EULA=yes + - DOCKER_VERNEMQ_PLUGINS__VMQ_PASSWD=off + - DOCKER_VERNEMQ_PLUGINS__VMQ_ACL=off + - DOCKER_VERNEMQ_PLUGINS__VMQ_DIVERSITY=on + - DOCKER_VERNEMQ_VMQ_DIVERSITY__AUTH_MYSQL__ENABLED=on + - DOCKER_VERNEMQ_VMQ_DIVERSITY__MYSQL__HOST=mysql-server + - DOCKER_VERNEMQ_VMQ_DIVERSITY__MYSQL__PORT=3306 + - DOCKER_VERNEMQ_VMQ_DIVERSITY__MYSQL__USER=root + - DOCKER_VERNEMQ_VMQ_DIVERSITY__MYSQL__PASSWORD=MlmAccess + - DOCKER_VERNEMQ_VMQ_DIVERSITY__MYSQL__DATABASE=MlmAccess + - DOCKER_VERNEMQ_VMQ_DIVERSITY__MYSQL__PASSWORD_HASH_METHOD=password + ports: + - 1883:1883 + - 8883:8883 + - 8888:8888 + volumes: + - ./data/vernemq/data:/vernemq/data + - ./data/vernemq/log:/vernemq/log + + mysql-server: + image: mariadb + restart: always + command: --default-authentication-plugin=mysql_native_password + environment: + - MYSQL_ROOT_PASSWORD=MlmAccess + - MARIADB_DATABASE=MlmAccess + volumes: + - "./data/mysql:/var/lib/mysql" + ports: + - 4306:3306 + + phpmyadmin: + image: phpmyadmin/phpmyadmin + restart: always + environment: + - PMA_HOST=mysql-server + - PMA_USER=root + - PMA_PASSWORD=MlmAccess + - UPLOAD_LIMIT=512M + ports: + - "4081:80" diff --git a/mock-actor/mock-actor.py b/mock-actor/mock-actor.py new file mode 100644 index 0000000..9f0ac84 --- /dev/null +++ b/mock-actor/mock-actor.py @@ -0,0 +1,28 @@ +import paho.mqtt.client as mqtt + +# The callback for when the client receives a CONNACK response from the server. +def on_connect(client, userdata, flags, rc): + print("Connected with result code "+str(rc)) + # Subscribing in on_connect() means that if we lose the connection and + # reconnect then subscriptions will be renewed. + print("Subscribing to topic","mlmAccess/pair/response/actor") + print(client.subscribe("mlmAccess/pair/response/actor")) + print("Publishing message to topic","mlmAccess/pair/request/actor") + print(client.publish("mlmAccess/pair/request/actor", "101")) + +def on_message(client, userdata, message): + print("message received " ,str(message.payload.decode("utf-8"))) + print("message topic=",message.topic) + print("message qos=",message.qos) + print("message retain flag=",message.retain) + +client = mqtt.Client(client_id="pair-actor") +client.username_pw_set("pair-actor", "pair-actor") + +client.on_connect = on_connect +client.on_message = on_message + +print("connecting to broker") +print(client.connect("localhost", 1883, 60)) + +client.loop_forever() \ No newline at end of file