配置 LDAP 身份验证
你可以使用 轻量级目录访问协议 (LDAP) 来保护对 Apache Druid 的访问。本主题介绍了如何设置带有 LDAP 和基于 TLS 的 LDAP (LDAPS) 的 Druid 身份验证和授权。本页面中的示例展示了针对 Active Directory LDAP 系统的配置。
第一步是为 Druid 启用 LDAP 身份验证和授权。然后,你需要将 LDAP 组映射到 Druid 角色,并将权限分配给这些角色。完成此配置后,你可以选择启用 LDAPS,以使 LDAP 流量机密且安全。
先决条件
在开始为 Druid 配置 LDAP 之前,请先测试你的 LDAP 连接并执行一次示例搜索。
检查 LDAP 连接
测试你的 LDAP 连接以验证它是否可以使用用户凭据正常工作。在流程的后续步骤中,你将使用此用户作为 bindUser 来配置 Druid 的 LDAP 身份验证。
以下示例命令用于测试用户 myuser@example.com 的连接。请输入你的 LDAP 服务器 IP 地址。如果你的 LDAP 实例监听的端口不是 389,请修改端口号。
ldapwhoami -vv -H ldap://ip_address:389 -D "myuser@example.com" -W
当系统提示时,输入该用户的密码并验证命令是否成功执行。如果失败,请检查以下内容:
- 确保你为 LDAP 实例使用了正确的端口。
- 检查网络防火墙是否阻止了对 LDAP 端口的连接。
- 查看你的 LDAP 实现细节,看看是否需要专门在 LDAP 服务器上允许 LDAP 客户端。如果是,请将 Druid Coordinator 服务器添加到允许列表中。
测试 LDAP 搜索
一旦 LDAP 连接正常工作,就可以搜索用户。例如,以下命令在 Active Directory 系统中搜索用户 myuser。sAMAccountName 属性是 Active Directory 特有的,包含已验证的用户身份。
ldapsearch -x -W -H ldap://ip_address:389 -D "cn=admin,dc=example,dc=com" -b "dc=example,dc=com" "(sAMAccountName=myuser)" +
结果中的 memberOf 属性显示了该用户所属的组。例如,以下响应显示该用户是 mygroup 组的成员。
memberOf: cn=mygroup,ou=groups,dc=example,dc=com
在随后的步骤中,你将使用此信息将 LDAP 组映射到 Druid 角色。
Druid 使用 memberOf 属性通过 LDAP 来确定组成员身份。如果你的 LDAP 服务器实现不包含此属性,则在将 LDAP 组映射到 Druid 角色时,必须完成一些额外的步骤。
配置 Druid 进行 LDAP 身份验证
要配置 Druid 使用 LDAP 身份验证,请按照下列步骤操作。有关配置文件的位置,请参阅配置参考。
-
在你的 LDAP 系统中创建一个用户,你将同时将其用于与 Druid 的内部通信以及作为 LDAP 初始管理员用户。更多信息请参阅安全概览。在下例中,LDAP 用户为
internal@example.com。 -
在
common.runtime.properties文件中启用druid-basic-security扩展。 -
在
common.runtime.properties文件中,添加以下 LDAP 属性行,并根据你自己的值进行替换。有关这些属性的详细信息,请参阅Druid 基础安全。druid.auth.authenticatorChain=["ldap"]
druid.auth.authenticator.ldap.type=basic
druid.auth.authenticator.ldap.enableCacheNotifications=true
druid.auth.authenticator.ldap.credentialsValidator.type=ldap
druid.auth.authenticator.ldap.credentialsValidator.url=ldap://ip_address:port
druid.auth.authenticator.ldap.credentialsValidator.bindUser=administrator@example.com
druid.auth.authenticator.ldap.credentialsValidator.bindPassword=adminpassword
druid.auth.authenticator.ldap.credentialsValidator.baseDn=dc=example,dc=com
druid.auth.authenticator.ldap.credentialsValidator.userSearch=(&(sAMAccountName=%s)(objectClass=user))
druid.auth.authenticator.ldap.credentialsValidator.userAttribute=sAMAccountName
druid.auth.authenticator.ldap.authorizerName=ldapauth
druid.escalator.type=basic
druid.escalator.internalClientUsername=internal@example.com
druid.escalator.internalClientPassword=internaluserpassword
druid.escalator.authorizerName=ldapauth
druid.auth.authorizers=["ldapauth"]
druid.auth.authorizer.ldapauth.type=basic
druid.auth.authorizer.ldapauth.initialAdminUser=internal@example.com
druid.auth.authorizer.ldapauth.initialAdminRole=admin
druid.auth.authorizer.ldapauth.roleProvider.type=ldap注意以下事项:
bindUser:用于连接 LDAP 的用户。这应该与你用于测试 LDAP 搜索的用户相同。userSearch:你的 LDAP 搜索语法。userAttribute:用户搜索属性。internal@example.com是你在第 1 步中创建的 LDAP 用户。在该示例中,它既作为内部客户端用户,也作为初始管理员用户。
在上面的示例中,Druid 提权器 (Escalator) 和 LDAP 初始管理员用户设置为同一用户——internal@example.com。如果提权器设置为其他用户,你必须遵循第 4 步和第 5 步来创建组映射并分配初始角色,然后集群的其余部分才能正常运行。
-
将你的组映射保存到 JSON 文件中。示例文件
groupmap.json如下所示:{
"name": "mygroupmap",
"groupPattern": "CN=mygroup,CN=Users,DC=example,DC=com",
"roles": [
"readRole"
]
}在该示例中,LDAP 组
mygroup映射到 Druid 角色readRole,映射名称为mygroupmap。 -
使用 Druid API 根据你的 JSON 文件创建组映射并分配初始角色。以下示例使用 curl 为 LDAP 组
mygroup创建groupmap.json中定义的映射:curl -i -v -H "Content-Type: application/json" -u internal -X POST -d @groupmap.json https://:8081/druid-ext/basic-security/authorization/db/ldapauth/groupMappings/mygroupmap -
检查组映射是否创建成功。以下示例请求列出了所有组映射:
curl -i -v -H "Content-Type: application/json" -u internal -X GET https://:8081/druid-ext/basic-security/authorization/db/ldapauth/groupMappings
将 LDAP 组映射到 Druid 角色
一旦完成了初始设置和映射,就可以将更多的 LDAP 组映射到 Druid 角色。LDAP 组的成员将获得相应 Druid 角色的权限。
创建 Druid 角色
要创建 Druid 角色,你可以通过 Druid REST API 向 Coordinator 进程提交 POST 请求,或者使用 Druid 控制台。
以下示例使用 localhost 作为 Coordinator 主机,8081 作为端口。请根据你的部署细节修改这些属性。
创建名为 readRole 的角色的示例请求:
curl -i -v -H "Content-Type: application/json" -u internal -X POST https://:8081/druid-ext/basic-security/authorization/db/ldapauth/roles/readRole
检查 Druid 是否成功创建了该角色。以下示例请求列出了所有角色:
curl -i -v -H "Content-Type: application/json" -u internal -X GET https://:8081/druid-ext/basic-security/authorization/db/ldapauth/roles
向 Druid 角色添加权限
拥有 Druid 角色后,你可以向其添加权限。以下示例为 wikipedia 数据源添加只读访问权限。
假设名为 perm.json 的文件中包含以下 JSON:
[
{ "resource": { "name": "wikipedia", "type": "DATASOURCE" }, "action": "READ" },
{ "resource": { "name": ".*", "type": "STATE" }, "action": "READ" },
{ "resource": {"name": ".*", "type": "CONFIG"}, "action": "READ"}
]
以下请求将 JSON 文件中的权限与 readRole 角色关联:
curl -i -v -H "Content-Type: application/json" -u internal -X POST -d@perm.json https://:8081/druid-ext/basic-security/authorization/db/ldapauth/roles/readRole/permissions
Druid 用户需要 STATE 和 CONFIG 权限才能在 Druid 控制台中查看数据源。如果你只想分配查询权限,则只需应用 perm.json 文件第一行中的 READ 权限即可。
你也可以以正则表达式的形式提供数据源名称。例如,要授予对所有以 wiki 开头的数据源的访问权限,你可以将数据源名称指定为 { "name": "wiki.*" }。
创建组映射
你现在可以将 LDAP 组映射到 Druid 角色。以下示例请求创建了一个名为 mygroupmap 的映射。它假设目录中存在名为 mygroup 的组。
{
"name": "mygroupmap",
"groupPattern": "CN=mygroup,CN=Users,DC=example,DC=com",
"roles": [
"readRole"
]
}
以下示例请求配置映射——角色映射位于 groupmap.json 文件中。有关示例文件的内容,请参阅配置 Druid 进行 LDAP 身份验证。
curl -i -v -H "Content-Type: application/json" -u internal -X POST -d @groupmap.json https://:8081/druid-ext/basic-security/authorization/db/ldapauth/groupMappings/mygroupmap
要检查组映射是否创建成功,以下请求会列出所有组映射:
curl -i -v -H "Content-Type: application/json" -u internal -X GET https://:8081/druid-ext/basic-security/authorization/db/ldapauth/groupMappings
以下示例请求返回 mygroupmap 组的详细信息:
curl -i -v -H "Content-Type: application/json" -u internal -X GET https://:8081/druid-ext/basic-security/authorization/db/ldapauth/groupMappings/mygroupmap
以下示例请求将 queryRole 角色添加到 mygroupmap 映射:
curl -i -v -H "Content-Type: application/json" -u internal -X POST https://:8081/druid-ext/basic-security/authorization/db/ldapauth/groupMappings/mygroup/roles/queryrole
将 LDAP 用户添加到 Druid 并分配角色
只有在以下情况下才需要完成此步骤:
- 你的 LDAP 用户不属于任何 LDAP 组,或者
- 你希望为用户配置额外的 Druid 角色,而这些角色并未映射到该用户所属的 LDAP 组。
将 LDAP 用户 myuser 添加到 Druid 的示例请求:
curl -i -v -H "Content-Type: application/json" -u internal -X POST https://:8081/druid-ext/basic-security/authorization/db/ldapauth/users/myuser
将 myuser 用户分配给 queryRole 角色的示例请求:
curl -i -v -H "Content-Type: application/json" -u internal -X POST https://:8081/druid-ext/basic-security/authorization/db/ldapauth/users/myuser/roles/queryRole
启用基于 TLS 的 LDAP (LDAPS)
在 Druid 中配置 LDAP 身份验证后,你可以选择使用传输层安全性 (TLS)(以前称为安全套接字层 (SSL))技术使 LDAP 流量机密且安全。
配置 LDAPS 可在 Druid 和 LDAP 服务器之间建立信任。
先决条件
在开始于 Druid 中设置 LDAPS 之前,必须先配置 Druid 进行 LDAP 身份验证。你还需要:
- 由公共证书颁发机构 (CA) 颁发的证书或由内部 CA 签名的自签名证书。
- 用于签署 LDAP 服务器证书的 CA 的根证书。如果你使用的是通用的公共 CA,则该证书可能已存在于 Java 信任存储 (truststore) 中。否则,你需要导入 CA 的证书。
为 LDAPS 配置 Druid
完成以下步骤为 Druid 设置 LDAPS。有关配置文件的位置,请参阅配置参考。
-
将 LDAP 服务器的 CA 或自签名证书导入到一个新创建的 LDAP 信任存储中,或者导入到
common.runtime.properties文件中druid.client.https.trustStorePath属性指定的信任存储中。下面的示例说明了为 HTTPS 客户端和 LDAP 客户端共用一个密钥存储库的选项,但如果你愿意,也可以为 LDAP 使用单独的专用信任存储。
keytool -import -trustcacerts -keystore path/to/cacerts -storepass truststorepassword -alias aliasName -file path/to/certificate.cer
将 path/to/cacerts 替换为你的信任存储路径,将 truststorepassword 替换为你的信任存储密码,将 aliasName 替换为密钥存储库的别名,将 path/to/certificate.cer 替换为证书的位置和名称。例如:
keytool -import -trustcacerts -keystore /Library/Java/JavaVirtualMachines/adoptopenjdk-8.jdk/Contents/Home/jre/lib/security/cacerts -storepass mypassword -alias myAlias -file /etc/ssl/certs/my-certificate.cer
-
如果 CA 的根证书尚不在 Java 信任存储中,请将其导入:
keytool -importcert -keystore path/to/cacerts -storepass truststorepassword -alias aliasName -file path/to/certificate.cer将
path/to/cacerts替换为你的信任存储路径,将truststorepassword替换为你的信任存储密码,将aliasName替换为密钥存储库的别名,将path/to/certificate.cer替换为证书的位置和名称。例如:keytool -importcert -keystore /Library/Java/JavaVirtualMachines/adoptopenjdk-8.jdk/Contents/Home/jre/lib/security/cacerts -storepass mypassword -alias myAlias -file /etc/ssl/certs/my-certificate.cer -
在
common.runtime.properties文件中,将以下各行添加到 LDAP 配置部分,并替换为你自己的信任存储路径和密码。请注意,指向信任存储的属性是druid.auth.basic.ssl.trustStorePath而不是druid.client.https.trustStorePath。无论你是为 HTTPS 客户端和 LDAP 使用相同的信任存储,还是使用单独的 LDAP 信任存储,请确保正确的属性指向导入了 LDAP 证书的信任存储。druid.auth.basic.ssl.trustStorePath=/Library/Java/JavaVirtualMachines/adoptopenjdk-8.jdk/Contents/Home/jre/lib/security/cacerts
druid.auth.basic.ssl.protocol=TLS
druid.auth.basic.ssl.trustStorePassword=xxxxxx有关这些属性的详细信息,请参阅Druid 基础安全。
-
你可以选择在
common.runtime.properties文件中配置其他 LDAPS 属性。有关更多信息,请参阅Druid 基础安全。 -
重启 Druid。
故障排除提示
以下是一些有助于解决 LDAP 和 LDAPS 相关问题的思路。
检查 Coordinator 日志
如果 LDAP 连接无法正常工作,请检查 Coordinator 日志。详细信息请参阅日志记录。
检查 Druid 提权器配置
如果 Coordinator 工作正常但集群的其他部分不正常,请检查提权器配置。详细信息请参阅配置参考。你也可以检查其他服务日志,查看为什么这些服务无法从 Coordinator 获取授权详细信息。
检查 LDAP 服务器响应时间
如果用户可以登录 Druid 控制台,但登录页面显示 401 错误,请检查你的 LDAP 服务器响应时间。在拥有大量 LDAP 用户的大型组织中,LDAP 的响应可能会很慢,这可能导致连接超时。