Indian Gooner
Indian Gooner

Reputation: 1

EMQX Mqtt Broker 5.8.0 - How to dynamically add an ACL rule whenever a new client is connected?

I am working with EMQX (version 5.8.0) Mqtt broker for an iot device application. Each device will act as a client and each of them will be publishing or subscribing to topics. But i want to restrict every client to publish and subscribe only on topics starting there own clientId/userName, like, topics would be like,

deviceId1/abc

deviceId2/abc

deviceId3/abc

wherein deviceId1 will be the username of the client

How can I restrict clients to do a pubs only on that particular topic and no one should be able to subscribe to my_device/# and hence receiving all messages.

I tried to add a new rule in the acl.conf file via a script which is triggered by a webhook on a new client connection but it requires restarting the emqx server which is not acceptable for me.

I also tried to handle this via a http server and emqx api but not got issues with the implementation. My server script for this goes like :

from flask import Flask, request, jsonify
import requests
app = Flask(__name__)

EMQX_API_URL = "http://localhost:8080/api/v5/acl/rules"
AUTH = ("admin", "admin_password")

@app.route('/acl', methods=['POST'])
def acl():
    data = request.json
    print(f"Received data: {data}")

    client_id = data['clientid']
    topic = data['topic']
    action = data['action']
   
    # Define ACL rule
    acl_rule = {
        "username": client_id,
        "topic": topic,
        "action": action
    }

    # Check if client_id matches the topic
    if topic.startswith(client_id):
        try:
            response = requests.post(EMQX_API_URL, json=acl_rule, auth=AUTH)
            response.raise_for_status()

            if response.status_code == 200:
                print(f"ACL rule created successfully: {acl_rule}")
                return jsonify({"result": "allow"}), 200
            else:
                print(f"Failed to create ACL rule: {response.status_code}, {response.text}")
                return jsonify({"result": "error", "message": "ACL rule creation failed"}), 500
        except requests.exceptions.RequestException as e:
            print(f"Request failed: {e}")
            return jsonify({"result": "error", "message": "Request failed"}), 500
    else:
        return jsonify({"result": "deny"}), 403

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=8080)`

I am not sure about the api url itself : http://localhost:8080/api/v5/acl/rules. Also, localhost:18083/api-docs does not list any api for acl management. What am I doing wrong? Also, is there better and easier to achieve this?

Upvotes: 0

Views: 150

Answers (0)

Related Questions