MongoDB ACL

    插件:

    提示

    emqx_auth_mongo 插件同时包含认证功能,可通过注释禁用。

    MongoDB 基础连接信息,需要保证集群内所有节点均能访问。

    1. ## MongoDB 部署类型
    2. ##
    3. ## Value: single | unknown | sharded | rs
    4. auth.mongo.type = single
    5. ## 是否启用 SRV 和 TXT 记录解析
    6. auth.mongo.srv_record = false
    7. ## 如果您的 MongoDB 以副本集方式部署,则需要指定相应的副本集名称
    8. ##
    9. ## 如果启用了 SRV 记录,即 auth.mongo.srv_record 设置为 true,
    10. ## 且您的 MongoDB 服务器域名添加了包含 replicaSet 选项的 DNS TXT 记录,
    11. ## 那么可以忽略此配置项
    12. ## auth.mongo.rs_set_name =
    13. ## MongoDB 服务器地址列表
    14. ##
    15. ## 如果你的 URI 具有以下格式:
    16. ## mongodb://[username:password@]host1[:port1][,...hostN[:portN]][/[defaultauthdb][?options]]
    17. ## 请将 auth.mongo.server 配置为 host1[:port1][,...hostN[:portN]]
    18. ##
    19. ## 如果你的 URI 具有以下格式:
    20. ## mongodb+srv://server.example.com
    21. ## 请将 auth.mongo.server 配置为 server.example.com,并将 srv_record
    22. ## 设置为 true,EMQX 将自动查询 SRV 和 TXT 记录以获取服务列表和 replicaSet 等选项
    23. ##
    24. ## 现已支持 IPv6 和域名
    25. auth.mongo.server = 127.0.0.1:27017
    26. auth.mongo.pool = 8
    27. auth.mongo.login =
    28. auth.mongo.password =
    29. ## 指定用于授权的数据库,没有指定时默认为 admin
    30. ##
    31. ## 如果启用了 SRV 记录,即 auth.mongo.srv_record 设置为 true,
    32. ## 且您的 MongoDB 服务器域名添加了包含 authSource 选项的 DNS TXT 记录,
    33. ## 那么可以忽略此配置项
    34. ## auth.mongo.auth_source = admin
    35. auth.mongo.database = mqtt
    36. auth.mongo.query_timeout = 5s
    37. ## SSL 选项
    38. # auth.mongo.ssl = false
    39. ## auth.mongo.ssl_opts.keyfile =
    40. ## auth.mongo.ssl_opts.certfile =
    41. ## auth.mongo.ssl_opts.cacertfile =
    42. ## MongoDB 写模式
    43. ##
    44. ## 可设置为 unsafe 或 safe。设置为 safe 时会等待 MongoDB Server 的响应并返回给调用者。未指定时将使用默认值 unsafe。
    45. ## auth.mongo.w_mode =
    46. ## MongoDB 读模式
    47. ##
    48. ## 可设置为 master 或 slave_ok,设置为 master 时表示每次查询都将从主节点读取最新数据。未指定时将使用默认值 master。
    49. ## auth.mongo.r_mode =
    50. ## MongoDB 拓扑配置,一般情况下用不到,详见 MongoDB 官网文档
    51. auth.mongo.topology.pool_size = 1
    52. auth.mongo.topology.max_overflow = 0
    53. ## auth.mongo.topology.overflow_ttl = 1000
    54. ## auth.mongo.topology.overflow_check_period = 1000
    55. ## auth.mongo.topology.local_threshold_ms = 1000
    56. ## auth.mongo.topology.connect_timeout_ms = 20000
    57. ## auth.mongo.topology.socket_timeout_ms = 100
    58. ## auth.mongo.topology.server_selection_timeout_ms = 30000
    59. ## auth.mongo.topology.wait_queue_timeout_ms = 1000
    60. ## auth.mongo.topology.heartbeat_frequency_ms = 10000
    61. ## auth.mongo.topology.min_heartbeat_frequency_ms = 1000

    MongoDB 认证默认配置下需要确保数据库中有如下集合:

    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. }

    示例数据:

    ACL 规则集合

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

    MongoDB ACL 一条规则中定义了发布、订阅和发布/订阅的信息,在规则中的都是允许列表。

    规则字段说明:

    • username:连接客户端的用户名
    • clientid:连接客户端的 Client ID
    • publish:允许发布的主题数值,支持通配符
    • subscribe:允许订阅的主题数值,支持通配符
    • pubsub:允许发布订阅的主题数值,支持通配符

    主题可以使用通配符,并且可以在主题中加入占位符来匹配客户端信息,例如 t/%c 则在匹配时主题将会替换为当前客户端的 Client ID

    • %u:用户名
    • %c:Client ID

    默认配置下示例数据:

    1. use mqtt
    2. ## 所有用户不可以订阅、发布系统主题
    3. ## 允许客户端订阅包含自身 Client ID 的 /smarthome/${clientid}/temperature 主题
    4. db.mqtt_acl.insert({
    5. username: "$all",
    6. clientid: "$all",
    7. publish: ["#"],
    8. subscribe: ["/smarthome/%c/temperature"]
    9. })

    启用 MongoDB ACL 后并以用户名 emqx 成功连接后,客户端应当具有相应的主题权限。

    进行 ACL 鉴权时,EMQX 将使用当前客户端信息填充并执行用户配置的超级用户查询,查询客户端是否为超级用户。客户端为超级用户时将跳过 ACL 查询。

    同一个选择器的多个条件时实际查询中使用 MongoDB and 查询:

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

    你可以在查询条件中使用以下占位符,执行时 EMQX 将自动填充为客户端信息:

    • %u:用户名
    • %c:Client ID

    你可以根据业务需要调整超级用户查询,如添加多个查询条件、使用数据库预处理函数,以实现更多业务相关的功能。但是任何情况下超级用户查询需要满足以下条件:

    1. 查询结果中必须包含 is_superuser 字段,is_superuser 应该显式的为 true

    提示

    进行 ACL 鉴权时,EMQX 将使用当前客户端信息填充并执行用户配置的超级用户查询,如果没有启用超级用户查询或客户端不是超级用户,则使用 ACL 查询 查询出该客户端在数据库中的 ACL 规则。

    1. # etc/plugins/emqx_auth_mongo.conf
    2. auth.mongo.acl_query = on
    3. auth.mongo.acl_query.collection = mqtt_acl
    4. ## 查询选择器,多个条件时使用逗号分隔
    5. ## auth.mongo.acl_query.selector = username=%u,clientid=%c
    6. auth.mongo.acl_query.selector = username=%u
    7. ## 使用多个查询选择器
    8. ## auth.mongo.acl_query.selector.1 = username=$all
    9. ## auth.mongo.acl_query.selector.2 = username=%u

    同一个选择器的多个条件时实际查询中使用 MongoDB and 查询:

    多个选择器时实际查询中使用 MongoDB or 查询:

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

    你可以在 ACL 查询中使用以下占位符,执行时 EMQX 将自动填充为客户端信息:

    • %u:用户名
    • %c:Client ID

    提示

    MongoDB ACL 规则需严格使用上述数据结构。

    MongoDB ACL 中添加的所有规则都是 允许 规则。即白名单。

    MongoDB 中对应 topic 的规则为空时将交由下一个 acl 插件继续检查,否则将立即终止认证链并返回。 规则非空且未匹配到相应的 pub/sub 权限时,将返回认证失败(拒绝相应的 pub/sub 行为)并终止认证链。