基于 LDAP 进行授权
轻量级目录访问协议(LDAP) 是一种用于访问和管理目录信息的协议。EMQX 支持与 LDAP 服务器集成,用于进行授权检查。LDAP 授权器通过将发布/订阅请求与存储在LDAP服务器中的属性列表进行匹配来实施授权检查。
前置准备
- 熟悉 EMQX 认证基本概念。
LDAP 数据结构与查询
LDAP 授权器根据存储在 LDAP 目录中的授权数据检查客户端授权。LDAP 数据格式定义了组织和存储授权数据的结构和规则。LDAP 授权器支持几乎任何 LDAP 数据结构。以下是 OpenLDAP 的一个数据格式示例:
attributetype ( 1.3.6.1.4.1.11.2.53.2.2.3.1.2.3.4.1 NAME ( 'mqttPublishTopic' 'mpt' )
EQUALITY caseIgnoreMatch
SUBSTR caseIgnoreSubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
USAGE userApplications )
attributetype ( 1.3.6.1.4.1.11.2.53.2.2.3.1.2.3.4.2 NAME ( 'mqttSubscriptionTopic' 'mst' )
EQUALITY caseIgnoreMatch
SUBSTR caseIgnoreSubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
USAGE userApplications )
attributetype ( 1.3.6.1.4.1.11.2.53.2.2.3.1.2.3.4.3 NAME ( 'mqttPubSubTopic' 'mpst' )
EQUALITY caseIgnoreMatch
SUBSTR caseIgnoreSubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
USAGE userApplications )
objectclass ( 1.3.6.1.4.1.11.2.53.2.2.3.1.2.3.4 NAME 'mqttUser'
SUP top
STRUCTURAL
MAY ( mqttPublishTopic $ mqttSubscriptionTopic $ mqttPubSubTopic ) )
LDAP 授权器采用允许列表策略。用户需要为每个操作定义一个主题列表(支持通配符)。只有当操作的主题匹配时,操作才会被允许,否则 LDAP 授权器将忽略它。
以下是基于 OpenLDAP 数据格式示例、使用 LDAP 数据交换格式(LDIF) 定义的 LDAP 授权数据示例:
## create organization: emqx.io
dn:dc=emqx,dc=io
objectclass: top
objectclass: dcobject
objectclass: organization
dc:emqx
o:emqx,Inc.
## create organization unit: testdevice.emqx.io
dn:ou=testdevice,dc=emqx,dc=io
objectClass: top
objectclass:organizationalUnit
ou:testdevice
dn:uid=mqttuser0001,ou=testdevice,dc=emqx,dc=io
objectClass: top
objectClass: mqttUser
uid: mqttuser0001
## allows publishing to these 3 topics
mqttPublishTopic: mqttuser0001/pub/1
mqttPublishTopic: mqttuser0001/pub/+
mqttPublishTopic: mqttuser0001/pub/#
## allows subscribe to these 3 topics
mqttSubscriptionTopic: mqttuser0001/sub/1
mqttSubscriptionTopic: mqttuser0001/sub/+
mqttSubscriptionTopic: mqttuser0001/sub/#
## the underneath topics allow both publish or subscribe
mqttPubSubTopic: mqttuser0001/pubsub/1
mqttPubSubTopic: mqttuser0001/pubsub/+
mqttPubSubTopic: mqttuser0001/pubsub/#
dn:uid=mqttuser0002,ou=testdevice,dc=emqx,dc=io
objectClass: top
objectClass: mqttUser
uid: mqttuser0002
mqttPublishTopic: mqttuser0002/pub/#
mqttSubscriptionTopic: mqttuser0002/sub/1
mqttPubSubTopic: mqttuser0002/pubsub/#
所提供的示例为每个操作定义了一个多值属性。每个属性可以根据允许的主题数量重复零次或多次。
编辑 LDAP 配置文件 sladp.conf
,使其包含数据结构和 LDIF 文件。在启动 LDAP 服务器时将引用数据结构。下面是一个示例sladp.conf
文件:
TIP
您可以根据您的业务需求决定如何存储和访问认证信息。
include /usr/local/etc/openldap/schema/core.schema
include /usr/local/etc/openldap/schema/cosine.schema
include /usr/local/etc/openldap/schema/inetorgperson.schema
include /usr/local/etc/openldap/schema/emqx.schema
TLSCACertificateFile /usr/local/etc/openldap/cacert.pem
TLSCertificateFile /usr/local/etc/openldap/cert.pem
TLSCertificateKeyFile /usr/local/etc/openldap/key.pem
database mdb
suffix "dc=emqx,dc=io"
rootdn "cn=root,dc=emqx,dc=io"
rootpw {SSHA}eoF7NhNrejVYYyGHqnt+MdKNBh4r1w3W
directory /usr/local/etc/openldap/data
通过 Dashboard 配置 LDAP 授权器
您可以使用 EMQX Dashboard 配置如何使用 LDAP 进行授权。
在 EMQX Dashboard 页面上点击左侧导航栏的访问控制 -> 客户端授权,进入客户端授权页面。
单击创建,选择 LDAP 作为 数据源。点击下一步进入配置参数页签:
按照以下说明进行配置:
- 连接设置:填写连接到 LDAP 服务器所需的信息。
- 服务器:指定 EMQX 要连接的服务器地址(
主机:端口
)。 - 用户名:指定 LDAP 根用户名称。
- 密码:指定 LDAP 根用户密码。
- 服务器:指定 EMQX 要连接的服务器地址(
TLS 配置:如果要启用TLS,请打开切换按钮。有关启用TLS的更多信息,请参见网络和TLS。
- 连接配置:设置并发连接数和连接超时前的等待时间。
- 连接池大小(可选):输入一个整数值来定义EMQX节点到 LDAP 的并发连接数。默认值:
8
。 - 查询超时(可选):指定 EMQX 在查询超时之前的等待时间。支持的单位包括毫秒、秒、分钟和小时。
- 连接池大小(可选):输入一个整数值来定义EMQX节点到 LDAP 的并发连接数。默认值:
授权配置:填写与授权相关的设置。
基本 DN:相对于要执行搜索的基本对象条目(或可能是根)的名称。有关更多信息,请参见 RFC 4511搜索请求,支持使用占位符。
::: 提示
DN 指的是专有名称。这是每个条目的唯一标识符,它还描述了条目在信息树中的位置。
:::
查询 Filter:LDAP 查询筛选器,定义搜索匹配给定条目必须满足的条件。 过滤器的语法遵循 RFC 4515,也支持占位符。
- 连接设置:填写连接到 LDAP 服务器所需的信息。
点击创建完成设置。
通过配置文件配置 LDAP 授权器
您也可通过配置文件配置 LDAP 授权器。
LDAP 授权通过 type = ldap
进行标识。
配置示例:
{
type = ldap
server = "127.0.0.1:389"
publish_attribute = "mqttPublishTopic"
subscribe_attribute = "mqttSubscriptionTopic"
all_attribute = "mqttPubSubTopic"
query_timeout = "5s"
username = "root"
password = "root password"
pool_size = 8
base_dn = "uid=${username},ou=testdevice,dc=emqx,dc=io"
filter = "(objectClass=mqttUser)"
}