MongoDB ACL

For MongoDB ACL, an external MongoDB database is used to store ACL rules, which can store a large amount of data and dynamically manage ACLs for easy integration with external device management systems

Plugin:

  1. emqx_auth_mongo

TIP

The emqx_auth_mongo plugin also includes authentication, which can be disabled via comments

MongoDB connection information

MongoDB basic connection information needs to ensure that all nodes in the cluster can be accessed.

  1. # etc/plugins/emqx_auth_mongo.conf
  2. ## MongoDB Architecture type
  3. ##
  4. ## Value: single | unknown | sharded | rs
  5. auth.mongo.type = single
  6. ## rs mode needs to set rs name
  7. ## auth.mongo.rs_set_name =
  8. ## Server list, separated by comma in cluster mode
  9. ## Examples: 127.0.0.1:27017,127.0.0.2:27017...
  10. auth.mongo.server = 127.0.0.1:27017
  11. auth.mongo.pool = 8
  12. auth.mongo.login =
  13. auth.mongo.password =
  14. ## auth.mongo.auth_source = admin
  15. auth.mongo.database = mqtt
  16. auth.mongo.query_timeout = 5s
  17. ## SSL option
  18. # auth.mongo.ssl = false
  19. ## auth.mongo.ssl_opts.keyfile =
  20. ## auth.mongo.ssl_opts.certfile =
  21. ## auth.mongo.ssl_opts.cacertfile =
  22. ## MongoDB write mode.
  23. ##
  24. ## Value: unsafe | safe
  25. ## auth.mongo.w_mode =
  26. ## Mongo read mode.
  27. ##
  28. ## Value: master | slave_ok
  29. ## auth.mongo.r_mode =
  30. ## MongoDB topology configuration, generally not used, see MongoDB website documentation for details
  31. auth.mongo.topology.pool_size = 1
  32. auth.mongo.topology.max_overflow = 0
  33. ## auth.mongo.topology.overflow_ttl = 1000
  34. ## auth.mongo.topology.overflow_check_period = 1000
  35. ## auth.mongo.topology.local_threshold_ms = 1000
  36. ## auth.mongo.topology.connect_timeout_ms = 20000
  37. ## auth.mongo.topology.socket_timeout_ms = 100
  38. ## auth.mongo.topology.server_selection_timeout_ms = 30000
  39. ## auth.mongo.topology.wait_queue_timeout_ms = 1000
  40. ## auth.mongo.topology.heartbeat_frequency_ms = 10000
  41. ## auth.mongo.topology.min_heartbeat_frequency_ms = 1000

Default data structure

In the default configuration of MongoDB authentication, you need to ensure that the following collections are included in the database:

Authentication / Super Collection

  1. {
  2. username: "user",
  3. password: "password hash",
  4. salt: "password salt",
  5. is_superuser: false,
  6. created: "2020-02-20 12:12:14"
  7. }

Sample data:

  1. use mqtt
  2. db.mqtt_user.insert({
  3. "username": "emqx",
  4. "password": "efa1f375d76194fa51a3556a97e641e61685f914d446979da50a551a4333ffd7",
  5. "is_superuser": false,
  6. "salt": ""
  7. })

ACL rule collection

  1. {
  2. username: "username",
  3. clientid: "clientid",
  4. publish: ["topic1", "topic2", ...],
  5. subscribe: ["subtop1", "subtop2", ...],
  6. pubsub: ["topic/#", "topic1", ...]
  7. }

MongoDB ACL rule defines the publish, subscribe, and publish/subscribe information, and all allow lists are included in the rule.

Rule field description:

  • username: the user name of the connected client
  • clientid: the Client ID of the connected client
  • publish: the number of topics allowed to be published, supports wildcards
  • subscribe: the number of topics allowed to be subscribed to, supports wildcards
  • pubsub: the number of topics allowed to be published and subscribed to, supports wildcards

TIP

Wildcards can be used for topic, and placeholders can be added to the topic to match client information. For example, the topic will be replaced with the client ID of the current client when matching t/%c.

  • %u:user name
  • %c:Client ID

Sample data in the default configuration:

  1. use mqtt
  2. ## All users cannot subscribe and publish system topics
  3. ## Clients are allowed to subscribe to the topic of /smarthome/${clientid}/temperature with their own Client ID
  4. db.mqtt_acl.insert({
  5. username: "$all",
  6. clientid: "$all",
  7. publish: ["#"],
  8. subscribe: ["/smarthome/%c/temperature"]
  9. })

After enabling MongoDB ACL and successfully connecting with the username emqx, the client should have the appropriate topic permissions for the data.

super_query

When performing ACL authentication, EMQX Broker will use the current client information to execute a user-configured superuser query to query whether the client is a superuser. ACL queries are skipped when the client is a superuser.

  1. # etc/plugins/emqx_auth_mongo.conf
  2. ## Enable superuser
  3. auth.mongo.super_query = on
  4. ##collections for super queries
  5. auth.mongo.super_query.collection = mqtt_user
  6. ##Field for super user
  7. auth.mongo.super_query.super_field = is_superuser
  8. ## Superuser query selector, commas can be used to separate multiple conditions
  9. #auth.mongo.super_query.selector = username=%u, clientid=$all
  10. auth.mongo.super_query.selector = username=%u

MongoDB and query is used in the actual query under multiple conditions of the same selector:

  1. db.mqtt_user.find({
  2. "username": "wivwiv"
  3. "clientid": "$all"
  4. })

You can use the following placeholders in your query conditions, and EMQX Broker will automatically populate with client information when executed:

  • %u:user name
  • %c:Client ID

You can adjust the super user query according to business to achieve more business-related functions, such as adding multiple query conditions and using database preprocessing functions. However, in any case, the superuser query needs to meet the following conditions:

  1. The query result must include the is_superuser field, which should be explicitly true

TIP

If superuser functionality is not needed, it can be more efficient when commenting and disabling this option

acl_query

When performing ACL authentication, EMQX Broker will use the current client information to execute the user-configured superuser query. If superuser query is not enabled or the client is not a superuser, ACL query will be used to find out the ACL rules of client in the database.

  1. # etc/plugins/emqx_auth_mongo.conf
  2. auth.mongo.acl_query = on
  3. auth.mongo.acl_query.collection = mqtt_acl
  4. ## Query selector, commas can be used to separate multiple conditions
  5. ## auth.mongo.acl_query.selector = username=%u,clientid=%c
  6. auth.mongo.acl_query.selector = username=%u
  7. ## Using multiple query selectors
  8. ## auth.mongo.acl_query.selector.1 = username=$all
  9. ## auth.mongo.acl_query.selector.2 = username=%u

MongoDB and query is used in the actual query under multiple conditions of the same selector:

  1. db.mqtt_acl.find({
  2. "username": "emqx"
  3. "clientid": "$all"
  4. })

MongoDB or query is used in actual query under multiple selectors:

  1. db.mqtt_acl.find({
  2. "$or": [
  3. {
  4. "username": "$all"
  5. },
  6. {
  7. "username": "emqx"
  8. }
  9. ]
  10. })

You can use the following placeholders in ACL queries, and EMQX Broker will automatically populate with client information when executed:

  • %u:username
  • %c:Client ID

TIP

MongoDB ACL rules need to use the above data structures strictly.

All rules added in MongoDB ACL are allow rules. i.e. a whitelist.

When a client’s rules list is empty, EMQX continues to check the next auth/ACL plugin. Otherwise the check returns immediately without proceeding to the next auth/ACL plugins.

When the rule is non-empty and does not match the corresponding pub/sub permission, an ath/ACL failure will be returned (the corresponding pub/sub behavior will be denied) and the auth/ACL chain will be terminated.

When more than one auth/ACL plugins are in use, it is recommended to position MongoDB ACL after other auth/ACL plugins in the enabled plugins list.