安全概览
本文档概述了 Apache Druid 的安全功能、配置说明以及确保 Druid 安全的一些最佳实践。
默认情况下,Druid 的安全功能是禁用的,这简化了初始部署体验。但是,在生产部署中必须配置安全功能。这些功能包括 TLS、认证和授权。
最佳实践
以下建议适用于 Druid 集群设置
- 以非特权 Unix 用户身份运行 Druid。请勿以 root 用户身份运行 Druid。
Druid 管理员拥有与运行 Druid 的 Unix 用户账号相同的操作系统权限。请参阅 认证与授权模型。如果 Druid 进程在操作系统 root 用户账号下运行,那么 Druid 管理员可以读取或写入 root 账号有权访问的所有文件,包括像 /etc/passwd 这样的敏感文件。
- 对于生产环境以及其他可被不可信网络访问的环境,请启用 Druid 集群认证。
- 启用授权,并且不要在未启用授权的情况下公开 Web 控制台。如果未启用授权,任何能够访问 Web 控制台的用户都拥有与运行 Web 控制台进程的操作系统用户相同的特权。
- 授予用户执行其功能所需的最小权限。例如,不要允许仅需查询数据的用户写入数据源或查看状态。
- 不要在配置规范中为生产系统提供纯文本密码。例如,敏感属性不应包含在
KafkaSupervisorIngestionSpec的consumerProperties字段中。更多信息请参阅 环境变量动态配置提供程序。 - 禁用 JavaScript,如 JavaScript 指南的 安全部分 所述。
以下建议适用于 Druid 运行所在的网络
- 启用 TLS 以加密集群内的通信。
- 使用 API 网关来:
- 限制来自不可信网络的访问
- 创建用户需要访问的特定 API 的允许列表
- 实施账号锁定和限流功能。
- 尽可能使用防火墙和其他网络层过滤,仅公开您用例中特别需要的 Druid 服务和端口。例如,仅向执行查询的下游应用程序公开 Broker 端口。您可以限制访问特定的 IP 地址或 IP 范围,以进一步加固和增强安全性。
以下建议适用于 Druid 的授权和认证模型
- 仅将
WRITE权限授予DATASOURCE给可信用户。Druid 的信任模型假设这些用户拥有与运行 Web 控制台进程的操作系统用户相同的特权。此外,拥有WRITE权限的用户可以更改数据源,并且有权访问任务和监督器更新 (POST) API,这可能会影响数据摄入。 - 仅将
STATE READ、STATE WRITE、CONFIG WRITE和DATASOURCE WRITE权限授予高度可信的用户。这些权限允许用户代表 Druid 服务器进程访问资源,而不受限于特定数据源。 - 如果您的 Druid 客户端应用程序允许不太可信的用户控制摄入任务的输入源,请验证来自用户的 URL。如果未校验 URL,则可能指向您网络或本地文件系统内的其他位置和资源。
启用 TLS
启用 TLS 可以加密外部客户端与 Druid 集群之间以及集群内服务之间的流量。
生成密钥
在 Druid 中启用 TLS 之前,请先生成 KeyStore 和 TrustStore。当一个 Druid 进程(例如 Broker)联系另一个 Druid 进程(例如 Historical)时,第一个服务作为第二个服务(视为服务器)的客户端。
客户端使用包含客户端信任的证书的 TrustStore。例如,Broker。
服务器使用包含私钥和证书链的 KeyStore,用于安全地标识自身。
以下示例演示了如何使用 Java keytool 生成服务器的 KeyStore,然后为客户端创建信任该密钥的 TrustStore。
- 使用 Java
keytool命令生成 KeyStore
keytool -keystore keystore.jks -alias druid -genkey -keyalg RSA
- 导出公共证书
keytool -export -alias druid -keystore keystore.jks -rfc -file public.cert
- 创建 TrustStore
keytool -import -file public.cert -alias druid -keystore truststore.jks
Druid 使用 Jetty 作为其嵌入式 Web 服务器。请参阅 Jetty 文档中的 配置 SSL/TLS KeyStores。
请勿在生产环境中使用自签名证书。相反,请依赖当前的公钥基础设施来生成和分发受信任的密钥。
更新 Druid TLS 配置
编辑所有节点上所有 Druid 服务的 common.runtime.properties 文件。添加或更新以下 TLS 选项。完成后重启集群。
# Turn on TLS globally
druid.enableTlsPort=true
# Disable non-TLS communicatoins
druid.enablePlaintextPort=false
# For Druid processes acting as a client
# Load simple-client-sslcontext to enable client side TLS
# Add the following to extension load list
druid.extensions.loadList=[......., "simple-client-sslcontext"]
# Setup client side TLS
druid.client.https.protocol=TLSv1.2
druid.client.https.trustStoreType=jks
druid.client.https.trustStorePath=truststore.jks # replace with correct trustStore file
druid.client.https.trustStorePassword=secret123 # replace with your own password
# Setup server side TLS
druid.server.https.keyStoreType=jks
druid.server.https.keyStorePath=my-keystore.jks # replace with correct keyStore file
druid.server.https.keyStorePassword=secret123 # replace with your own password
druid.server.https.certAlias=druid
更多信息,请参阅 TLS 支持 和 Simple SSLContext 提供程序模块。
认证与授权
您可以配置认证和授权以控制对 Druid API 的访问。然后,按照以下部分所述配置用户、角色和权限。在集群中所有 Druid 服务器上的 common.runtime.properties 文件中进行配置更改。
在 Druid 的操作上下文中,认证器(Authenticators)控制用户身份验证的方式。授权器(Authorizers)使用用户角色将已认证的用户与他们被允许访问的数据源关联起来。您可以基于每个数据源设置最细粒度的权限。
下图描述了请求通过认证过程的流程。

启用认证器
要对 Druid 中的请求进行认证,您需要配置一个认证器。针对 HTTP 基本认证、LDAP 和 Kerberos 的认证器扩展已经存在。
以下内容将引导您完成启用基本认证的示例配置步骤:
-
将
druid-basic-security扩展添加到common.runtime.properties中的druid.extensions.loadList。例如,对于快速入门安装,属性文件位于conf/druid/cluster/_common。druid.extensions.loadList=["druid-basic-security", "druid-histogram", "druid-datasketches", "druid-kafka-indexing-service"] -
在同一个 common.runtime.properties 文件中配置基本认证器、授权器和 Escalator 设置。Escalator 定义了 Druid 进程如何相互认证。
一个配置示例
# Druid basic security
druid.auth.authenticatorChain=["MyBasicMetadataAuthenticator"]
druid.auth.authenticator.MyBasicMetadataAuthenticator.type=basic
# Default password for 'admin' user, should be changed for production.
druid.auth.authenticator.MyBasicMetadataAuthenticator.initialAdminPassword=password1
# Default password for internal 'druid_system' user, should be changed for production.
druid.auth.authenticator.MyBasicMetadataAuthenticator.initialInternalClientPassword=password2
# Uses the metadata store for storing users.
# You can use the authentication API to create new users and grant permissions
druid.auth.authenticator.MyBasicMetadataAuthenticator.credentialsValidator.type=metadata
# If true and if the request credential doesn't exist in this credentials store,
# the request will proceed to next Authenticator in the chain.
druid.auth.authenticator.MyBasicMetadataAuthenticator.skipOnFailure=false
druid.auth.authenticator.MyBasicMetadataAuthenticator.authorizerName=MyBasicMetadataAuthorizer
# Escalator
druid.escalator.type=basic
druid.escalator.internalClientUsername=druid_system
druid.escalator.internalClientPassword=password2
druid.escalator.authorizerName=MyBasicMetadataAuthorizer
druid.auth.authorizers=["MyBasicMetadataAuthorizer"]
druid.auth.authorizer.MyBasicMetadataAuthorizer.type=basic -
重启集群。
请参阅以下主题以获取更多信息:
- 认证与授权 以获取关于认证器、Escalator 和授权器的更多信息。
- 基本安全 以获取关于上述示例中所使用扩展的更多信息。
- Kerberos 用于 Kerberos 认证。
- 用户认证与授权 以了解有关权限的详细信息。
- SQL 权限 以了解 SQL 系统表的权限。
启用授权器
启用基本认证扩展后,您可以通过 Druid Coordinator 的 user 端点添加用户、角色和权限。请注意,您不能直接为单个用户分配权限。权限必须通过角色分配。
下图描述了授权模型,以及用户、角色、权限和资源之间的关系。

以下步骤演示了示例设置过程:
默认的 Coordinator API 端口是 8081(用于非 TLS 连接)和 8281(用于安全连接)。
- 通过向
druid-ext/basic-security/authentication/db/MyBasicMetadataAuthenticator/users/<USERNAME>发送 POST 请求来创建用户。将<USERNAME>替换为您要创建的“新”用户名。例如:curl -u admin:password1 -XPOST https://my-coordinator-ip:8281/druid-ext/basic-security/authentication/db/MyBasicMetadataAuthenticator/users/myname
如果您启用了 TLS,请务必相应地调整 curl 命令。例如,如果您的 Druid 服务器使用自签名证书,您可能需要包含 --insecure curl 选项,以便在 curl 命令中跳过证书检查。
-
通过向
druid-ext/basic-security/authentication/db/MyBasicMetadataAuthenticator/users/<USERNAME>/credentials发送 POST 请求来为用户添加凭据。例如:curl -u admin:password1 -H'Content-Type: application/json' -XPOST https://my-coordinator-ip:8281/druid-ext/basic-security/authentication/db/MyBasicMetadataAuthenticator/users/myname/credentials --data-raw '{"password": "my_password"}' -
对于您创建的每个认证器用户,请通过向
druid-ext/basic-security/authorization/db/MyBasicMetadataAuthorizer/users/<USERNAME>发送 POST 请求来创建对应的授权器用户。例如:curl -u admin:password1 -XPOST https://my-coordinator-ip:8281/druid-ext/basic-security/authorization/db/MyBasicMetadataAuthorizer/users/myname -
通过向
druid-ext/basic-security/authorization/db/MyBasicMetadataAuthorizer/roles/<ROLENAME>发送 POST 请求来创建授权器角色以控制权限。例如:curl -u admin:password1 -XPOST https://my-coordinator-ip:8281/druid-ext/basic-security/authorization/db/MyBasicMetadataAuthorizer/roles/myrole -
通过向
druid-ext/basic-security/authorization/db/MyBasicMetadataAuthorizer/users/<USERNAME>/roles/<ROLENAME>发送 POST 请求来将角色分配给用户。例如:curl -u admin:password1 -XPOST https://my-coordinator-ip:8281/druid-ext/basic-security/authorization/db/MyBasicMetadataAuthorizer/users/myname/roles/myrole | jq -
最后,在
druid-ext/basic-security/authorization/db/MyBasicMetadataAuthorizer/roles/<ROLENAME>/permissions为角色附加权限,以控制它们如何与 Druid 交互。例如:curl -u admin:password1 -H'Content-Type: application/json' -XPOST --data-binary @perms.json https://my-coordinator-ip:8281/druid-ext/basic-security/authorization/db/MyBasicMetadataAuthorizer/roles/myrole/permissionsperms.json的负载格式应如下所示:[
{
"resource": {
"type": "DATASOURCE",
"name": "<PATTERN>"
},
"action": "READ"
},
{
"resource": {
"type": "STATE",
"name": "STATE"
},
"action": "READ"
}
]
注意:Druid 将资源名称视为正则表达式 (regex)。您可以使用特定的数据源名称或正则表达式一次性为多个数据源授予权限。
配置 LDAP 认证器
作为使用基本元数据认证器的替代方案,您可以使用 LDAP 来认证用户。有关为 LDAP 和 LDAPS 配置 Druid 的信息,请参阅 配置 LDAP 认证。
Druid 安全信任模型
在 Druid 的信任模型中,用户可以拥有不同的授权级别:
- 拥有资源写入权限的用户被允许执行 Druid 进程可以执行的任何操作。
- 已认证的只读用户可以针对其拥有权限的资源执行查询。
- 没有任务权限的已认证用户被允许执行不需要访问资源即可执行的查询。
此外,Druid 遵循以下原则运作:
从最内层开始:
- Druid 进程拥有与运行该进程的指定系统用户相同的本地文件访问权限。
- Druid 摄入系统可以创建新进程来执行任务。这些任务会继承其父进程的用户权限。这意味着任何被授权提交摄入任务的用户,都可以利用该摄入任务的权限来读取或写入 Druid 进程有权访问的任何本地文件或外部资源。
注意:仅向可信用户授予 DATASOURCE WRITE 权限,因为他们可以像 Druid 进程一样行事。
集群内部:
- Druid 假设其运行在受隔离、受保护的网络中,网络内没有可达 IP 处于敌对控制之下。实施 Druid 时,请务必设置防火墙和其他安全措施来保护入站和出站连接。Druid 假设集群内的网络流量是加密的,包括 API 调用和数据传输。默认的加密实现使用 TLS。
- Druid 假设元数据存储和 ZooKeeper 节点等辅助服务未处于敌对控制之下。
集群到深层存储(Deep Storage):
- Druid 不会对深层存储的安全性做出假设。它遵循系统的原生安全策略来与深层存储进行认证和授权。
- Druid 不会为深层存储加密文件。相反,它依赖存储系统的原生加密功能,以确保跨所有存储类型的加密方案的兼容性。
集群到客户端:
- Druid 基于已配置的认证器与客户端进行认证。
- Druid 仅在授权器授予权限时执行操作。默认配置是
allowAll授权器。
报告安全问题
Apache Druid 团队非常重视安全。如果您在 Druid 中发现潜在的安全问题,例如绕过上述安全机制的方法,请将该问题报告至 security@apache.org。这是一个私有邮件列表。请为报告的每个漏洞发送一封纯文本电子邮件。
漏洞处理
以下列表总结了漏洞处理流程:
- 报告者私下向 security@apache.org 报告漏洞。
- 报告者收到答复,确认 Druid 团队已收到报告并将调查该问题。
- Druid 项目安全团队与报告者私下合作以解决该漏洞。
- Druid 团队通过创建受影响软件包的新版本来发布修复程序。
- Druid 团队公开宣布该漏洞并说明如何应用修复程序。
提交者应阅读 更详细的流程描述。安全漏洞报告者也可能会发现此描述很有用。