跳转到主要内容

基础安全

Apache Druid 的基础安全扩展增加了以下功能:

  • 一个身份验证器(Authenticator),支持使用 Druid 元数据存储或 LDAP 作为凭据存储的 HTTP 基本身份验证
  • 一个授权转换器(Escalator),用于确定 Druid 内部进程的身份验证方案。
  • 一个授权器(Authorizer),为 Druid 元数据存储或 LDAP 用户和组实现了基本的基于角色的访问控制。

要加载此扩展,请在 common.runtime.properties 文件中的 druid.extensions.loadList包含 druid-basic-security。例如:

druid.extensions.loadList=["postgresql-metadata-storage", "druid-hdfs-storage", "druid-basic-security"]

要启用基本身份验证,请在 common.runtime.properties 中配置基础身份验证器、授权转换器和授权器。有关 HTTP 基本身份验证的配置示例,请参阅安全概述

访问身份验证与授权,了解更多有关已实现扩展接口的信息及配置示例。

配置

本节中的示例对身份验证器和授权器使用了以下名称:

  • MyBasicMetadataAuthenticator
  • MyBasicLDAPAuthenticator
  • MyBasicMetadataAuthorizer
  • MyBasicLDAPAuthorizer

这些属性并不绑定到特定的身份验证器或授权器实例。

要设置这些配置属性的值,请将它们添加到通用运行时属性文件中。

通用属性

druid.auth.basic.common.pollingPeriod

定义进程轮询 Coordinator 以获取当前 Druid 元数据存储身份验证器/授权器状态的频率(以毫秒为单位)。
         必需:否
         默认值: 60000

druid.auth.basic.common.maxRandomDelay

定义添加到 pollingPeriod 中的随机延迟量(以毫秒为单位),用于将轮询请求分散到不同时间点。
         必需:否
         默认值: 6000

druid.auth.basic.common.maxSyncRetries

确定如果与 Coordinator 的身份验证/授权 Druid 元数据存储状态同步失败时,服务将重试的次数。
         必需:否
         默认值: 10

druid.auth.basic.common.cacheDirectory

如果定义了此路径,基础身份验证器和授权器 Druid 元数据存储缓存的快照将存储在该目录的磁盘上。若定义了此属性,且服务无法通过与 Coordinator 通信来初始化其状态时,服务在启动时将尝试从这些磁盘快照中初始化缓存。
         必需:否
         默认值:null

身份验证器

要使用基础身份验证器,请向 authenticatorChain 添加一个类型为 basic 的身份验证器。默认凭据验证器(credentialsValidator)为 metadata。要使用 LDAP 验证器,请定义一个类型为 'ldap' 的凭据验证器。

使用以下语法配置命名身份验证器:

druid.auth.authenticator.<authenticatorName>.<authenticatorProperty>

使用 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 authentication API to create new users and grant permissions
druid.auth.authenticator.MyBasicMetadataAuthenticator.credentialsValidator.type=metadata

# If true and the request credential doesn't exist in this credentials store, the request proceeds to the next Authenticator in the chain.
druid.auth.authenticator.MyBasicMetadataAuthenticator.skipOnFailure=false
druid.auth.authenticator.MyBasicMetadataAuthenticator.authorizerName=MyBasicMetadataAuthorizer

剩余的身份验证器配置示例均使用 MyBasicMetadataAuthenticatorMyBasicLDAPAuthenticator 作为身份验证器名称。

用于 Druid 元数据存储用户身份验证的属性

druid.auth.authenticator.MyBasicMetadataAuthenticator.initialAdminPassword

为自动创建的默认管理员用户提供的初始密码提供程序。如果未指定密码,则不会创建默认管理员用户。如果默认管理员用户已存在,设置此属性不会影响其密码。
         必需:否
         默认值:null

druid.auth.authenticator.MyBasicMetadataAuthenticator.initialInternalClientPassword

用于内部进程通信的默认内部系统用户的初始密码提供程序。如果未指定密码,则不会创建默认内部系统用户。如果默认内部系统用户已存在,设置此属性不会影响其密码。
         必需:否
         默认值:null

druid.auth.authenticator.MyBasicMetadataAuthenticator.enableCacheNotifications

如果为 true,当此身份验证器的配置发生变化时,Coordinator 将通知 Druid 进程,从而允许它们立即更新状态而无需等待轮询。
         必需:否
         默认值:True

druid.auth.authenticator.MyBasicMetadataAuthenticator.cacheNotificationTimeout

缓存通知的超时时间(以毫秒为单位)。
         必需:否
         默认值: 5000

druid.auth.authenticator.MyBasicMetadataAuthenticator.credentialIterations

用于密码哈希的迭代次数。请参阅凭据迭代次数与 API 性能
         必需:否
         默认值: 10000

druid.auth.authenticator.MyBasicMetadataAuthenticator.credentialsValidator.type

用于验证请求凭据的凭据存储类型(metadata)。
         必需:否
         默认值:metadata

druid.auth.authenticator.MyBasicMetadataAuthenticator.skipOnFailure

如果为 true,且请求凭据不存在或在凭据存储中未完全配置,则请求将继续由链中的下一个身份验证器处理。
         必需:否
         默认值:false

druid.auth.authenticator.MyBasicMetadataAuthenticator.authorizerName

请求应导向的授权器。
         必需:是
         默认值:不适用

凭据迭代次数与 API 性能

如上所述,credentialIterations 的值决定了对密码进行哈希处理的迭代次数。迭代次数越高,安全性越强。默认值 10,000 是刻意设置的高值,以防止攻击者使用暴力破解猜测密码。我们建议不要降低此值。Druid 会缓存过去一小时内使用的多达 1000 个密码的哈希值,以确保大量的迭代次数不会对查询性能产生明显影响。

如果 Druid 使用默认凭据验证器(即 credentialsValidator.type=metadata),更改 credentialIterations 值仅会影响更改后创建的用户,或随后通过 /druid-ext/basic-security/authentication/db/basic/users/{userName}/credentials 端点更新密码的用户。如果 Druid 使用 ldap 验证器,则此更改会在下次登录时应用于任何用户(以及新用户或更新密码的用户)。

用于 LDAP 用户身份验证的属性

druid.auth.authenticator.MyBasicLDAPAuthenticator.initialAdminPassword

为自动创建的默认管理员用户提供的初始密码提供程序。如果未指定密码,则不会创建默认管理员用户。如果默认管理员用户已存在,设置此属性不会影响其密码。
         必需:否
         默认值:null

druid.auth.authenticator.MyBasicLDAPAuthenticator.initialInternalClientPassword

用于内部进程通信的默认内部系统用户的初始密码提供程序。如果未指定密码,则不会创建默认内部系统用户。如果默认内部系统用户已存在,设置此属性不会影响其密码。
         必需:否
         默认值:null

druid.auth.authenticator.MyBasicLDAPAuthenticator.enableCacheNotifications

如果为 true,当此身份验证器的配置发生变化时,Coordinator 将通知 Druid 进程,从而允许它们立即更新状态而无需等待轮询。
         必需:否
         默认值:true

druid.auth.authenticator.MyBasicLDAPAuthenticator.cacheNotificationTimeout

缓存通知的超时时间(以毫秒为单位)。
         必需:否
         默认值: 5000

druid.auth.authenticator.MyBasicLDAPAuthenticator.credentialIterations

用于密码哈希的迭代次数。
         必需:否
         默认值: 10000

druid.auth.authenticator.MyBasicLDAPAuthenticator.credentialsValidator.type

用于验证请求凭据的凭据存储类型(ldap)。
         必需:否
         默认值:metadata

druid.auth.authenticator.MyBasicLDAPAuthenticator.credentialsValidator.url

LDAP 服务器的 URL。
         必需:是
         默认值:null

druid.auth.authenticator.MyBasicLDAPAuthenticator.credentialsValidator.bindUser

LDAP 绑定用户的用户名。
         必需:是
         默认值:null

druid.auth.authenticator.MyBasicLDAPAuthenticator.credentialsValidator.bindPassword

密码提供程序 LDAP 绑定用户密码。
         必需:是
         默认值:null

druid.auth.authenticator.MyBasicLDAPAuthenticator.credentialsValidator.baseDn

LDAP 服务器搜索用户的起始位置。
         必需:是
         默认值:null

druid.auth.authenticator.MyBasicLDAPAuthenticator.credentialsValidator.userSearch

用于搜索的过滤器/表达式。例如,(&(sAMAccountName=%s)(objectClass=user))
         必需:是
         默认值:null

druid.auth.authenticator.MyBasicLDAPAuthenticator.credentialsValidator.userAttribute

用于标识搜索结果中返回的属性的 ID。例如,sAMAccountName。
         必需:是
         默认值:null

druid.auth.authenticator.MyBasicLDAPAuthenticator.credentialsValidator.credentialVerifyDuration

当未请求时,有效凭据在缓存中可被验证的持续时间(以秒为单位)。
         必需:否
         默认值: 600

druid.auth.authenticator.MyBasicLDAPAuthenticator.credentialsValidator.credentialMaxDuration

无论请求频率如何,有效凭据可在缓存中保留的最长持续时间(以秒为单位)。
         必需:否
         默认值: 3600

druid.auth.authenticator.MyBasicLDAPAuthenticator.credentialsValidator.credentialCacheSize

有效凭据缓存的大小。缓存使用 LRU(最近最少使用)策略。
         必需:否
         默认值: 100

druid.auth.authenticator.MyBasicLDAPAuthenticator.skipOnFailure

如果为 true,且请求凭据不存在或在凭据存储中未完全配置,则请求将继续由链中的下一个身份验证器处理。
         必需:否
         默认值:false

druid.auth.authenticator.MyBasicLDAPAuthenticator.authorizerName

请求应导向的授权器。
         必需:是
         默认值:不适用

授权转换器(Escalator)

授权转换器确定用于 Druid 集群内部通信的身份验证方案,例如当 Broker 服务在查询处理过程中与 Historical 服务通信时。

配置示例

# Escalator
druid.escalator.type=basic
druid.escalator.internalClientUsername=druid_system
druid.escalator.internalClientPassword=password2
druid.escalator.authorizerName=MyBasicMetadataAuthorizer

属性

druid.escalator.internalClientUsername

授权转换器将对以内部系统用户身份发出的请求使用此用户名。
         必需:是
         默认值:不适用

druid.escalator.internalClientPassword

授权转换器将对以内部系统用户身份发出的请求使用此密码提供程序
         必需:是
         默认值:不适用

druid.escalator.authorizerName

请求应导向的授权器。
         必需:是
         默认值:不适用

授权器(Authorizer)

要使用基础授权器,请向 authorizers 列表添加一个类型为 basic 的授权器。

使用以下语法配置命名授权器:

druid.auth.authorizer.<authorizerName>.<authorizerProperty>

配置示例

# Authorizer
druid.auth.authorizers=["MyBasicMetadataAuthorizer"]
druid.auth.authorizer.MyBasicMetadataAuthorizer.type=basic

本文档其余部分的示例均使用 MyBasicMetadataAuthorizerMyBasicLDAPAuthorizer 作为授权器名称。

用于 Druid 元数据存储用户授权的属性

druid.auth.authorizer.MyBasicMetadataAuthorizer.enableCacheNotifications

如果为 true,当此授权器的配置发生变化时,Coordinator 将通知 Druid 进程,从而允许它们立即更新状态而无需等待轮询。
         必需:否
         默认值:true

druid.auth.authorizer.MyBasicMetadataAuthorizer.cacheNotificationTimeout

缓存通知的超时时间(以毫秒为单位)。
         必需:否
         默认值: 5000

druid.auth.authorizer.MyBasicMetadataAuthorizer.initialAdminUser

初始管理员用户。如果指定了 initialAdminRole 属性,则为其分配该角色;否则,将分配默认管理员角色。
         必需:否
         默认值:admin

druid.auth.authorizer.MyBasicMetadataAuthorizer.initialAdminRole

如果初始管理员角色不存在,则创建该角色。
         必需:否
         默认值:admin

druid.auth.authorizer.MyBasicMetadataAuthorizer.roleProvider.type

用于授权请求凭据的角色提供程序类型。
         必需:否
         默认值:metadata

用于 LDAP 用户授权的属性

druid.auth.authorizer.MyBasicLDAPAuthorizer.enableCacheNotifications

如果为 true,当此授权器的配置发生变化时,Coordinator 将通知 Druid 进程,从而允许它们立即更新状态而无需等待轮询。
         必需:否
         默认值:true

druid.auth.authorizer.MyBasicLDAPAuthorizer.cacheNotificationTimeout

缓存通知的超时时间(以毫秒为单位)。
         必需:否
         默认值: 5000

druid.auth.authorizer.MyBasicLDAPAuthorizer.initialAdminUser

初始管理员用户。如果指定了 initialAdminRole 属性,则为其分配该角色;否则,将分配默认管理员角色。
         必需:否
         默认值:admin

druid.auth.authorizer.MyBasicLDAPAuthorizer.initialAdminRole

如果初始管理员角色不存在,则创建该角色。
         必需:否
         默认值:admin

druid.auth.authorizer.MyBasicLDAPAuthorizer.initialAdminGroupMapping

初始管理员组映射。如果指定了 initialAdminRole 属性,则为其分配该角色;否则,将分配默认管理员角色。此初始管理员组映射的名称将设为 adminGroupMapping。
         必需:否
         默认值:null

druid.auth.authorizer.MyBasicLDAPAuthorizer.roleProvider.type

用于授权请求凭据的角色提供程序类型(ldap)。
         必需:否
         默认值:metadata

druid.auth.authorizer.MyBasicLDAPAuthorizer.roleProvider.groupFilters

用于过滤从 LDAP 搜索返回的允许组集的 LDAP 组过滤器数组。过滤器可以以 开头,或以 结尾,以提供配置灵活性,从而限制或过滤 LDAP 授权器可用的允许组集。
         必需:否
         默认值:null

只读授权器(ReadOnly Authorizer)

只读授权器允许所有 READ 操作,并拒绝所有其他操作(WRITE、DELETE 等)。

配置示例

druid.auth.authenticatorChain=["basic","anonymous"]

# Basic authenticator for internal user
druid.auth.authenticator.basic.type=basic
druid.auth.authenticator.basic.initialAdminPassword=password
druid.auth.authenticator.basic.initialInternalClientPassword=password
druid.auth.authenticator.basic.credentialsValidator.type=metadata
druid.auth.authenticator.basic.authorizerName=BasicAuthorizer

# Anonymous authenticator for external users
druid.auth.authenticator.anonymous.type=anonymous
druid.auth.authenticator.anonymous.identity=defaultUser
druid.auth.authenticator.anonymous.authorizerName=ReadOnlyAuthorizer

# Escalator with Basic auth for internal communications
druid.escalator.type=basic
druid.escalator.internalClientUsername=druid_system
druid.escalator.internalClientPassword=password
druid.escalator.authorizerName=BasicAuthorizer

# Both authorizers
druid.auth.authorizers=["BasicAuthorizer","ReadOnlyAuthorizer"]

# BasicAuthorizer configuration
druid.auth.authorizer.BasicAuthorizer.type=basic

# ReadOnlyAuthorizer configuration
druid.auth.authorizer.ReadOnlyAuthorizer.type=readOnly

通过此配置:

  • Druid 内部通信使用基本身份验证 → AllowAll 授权器 → 完全访问权限
  • 无身份验证的外部用户 → 匿名身份验证器 → 只读授权器 → 只读访问权限

LDAPS 属性

使用以下属性配置 Druid 的 TLS LDAP 身份验证 (LDAPS)。有关更多信息,请参阅配置 LDAP 身份验证

druid.auth.basic.ssl.protocol

要使用的 SSL 协议。TLS 版本为 1.2。
         必需:是
         默认值:tls

druid.auth.basic.ssl.trustStorePath

信任库(trust store)文件的路径。
         必需:是
         默认值:不适用

druid.auth.basic.ssl.trustStorePassword

访问信任库文件的密码。
         必需:是
         默认值:不适用

druid.auth.basic.ssl.trustStoreType

信任库文件的格式。对于 Java,该格式为 jks。
         必需:否
         默认值:jks

druid.auth.basic.ssl.trustStoreAlgorithm

信任管理器用于验证证书链的算法。
         必需:否
         默认值:不适用

druid.auth.basic.ssl.trustStorePassword

允许访问信任库的密码详细信息。
         必需:否
         默认值:不适用

LDAPS 配置示例:

druid.auth.basic.ssl.protocol=tls
druid.auth.basic.ssl.trustStorePath=/usr/local/druid-path/certs/truststore.jks
druid.auth.basic.ssl.trustStorePassword=xxxxx
druid.auth.basic.ssl.trustStoreType=jks
druid.auth.basic.ssl.trustStoreAlgorithm=PKIX

您可以将 druid.auth.basic.ssl.trustStorePassword 配置为纯文本密码,也可以将密码设置为环境变量。有关更多信息,请参阅密码提供程序

用法

Coordinator 安全 API

要使用这些 API,用户需要对名称为 "security" 的 CONFIG 资源类型拥有读/写权限。

身份验证 API

根路径:/druid-ext/basic-security/authentication

每个 API 端点都包含 {authenticatorName},用于指定正在配置的身份验证器实例。

用户/凭据管理

GET(/druid-ext/basic-security/authentication/db/{authenticatorName}/users)
返回所有用户名列表。

GET(/druid-ext/basic-security/authentication/db/{authenticatorName}/users/{userName})
返回名称为 {userName} 的用户的名称和凭据信息。

POST(/druid-ext/basic-security/authentication/db/{authenticatorName}/users/{userName})
创建一个名为 {userName} 的新用户。

DELETE(/druid-ext/basic-security/authentication/db/{authenticatorName}/users/{userName})
删除名称为 {userName} 的用户。

POST(/druid-ext/basic-security/authentication/db/{authenticatorName}/users/{userName}/credentials)
为 {userName} 分配用于 HTTP 基本身份验证的密码。内容:JSON 密码请求对象。

请求体示例:

{
"password": "helloworld"
}
缓存加载状态

GET(/druid-ext/basic-security/authentication/loadStatus)
返回身份验证 Druid 元数据存储的本地缓存的当前加载状态。

授权 API

根路径:/druid-ext/basic-security/authorization

每个 API 端点都包含 {authorizerName},用于指定正在配置的授权器实例。

用户创建/删除

GET(/druid-ext/basic-security/authorization/db/{authorizerName}/users)
返回所有用户名列表。

GET(/druid-ext/basic-security/authorization/db/{authorizerName}/users/{userName})
返回名称为 {userName} 的用户的名称和角色信息。

输出示例:

{
"name": "druid2",
"roles": [
"druidRole"
]
}

此 API 支持以下标志:

  • ?full:响应还将包含当前分配给用户的每个角色的完整信息。

输出示例:

{
"name": "druid2",
"roles": [
{
"name": "druidRole",
"permissions": [
{
"resourceAction": {
"resource": {
"name": "A",
"type": "DATASOURCE"
},
"action": "READ"
},
"resourceNamePattern": "A"
},
{
"resourceAction": {
"resource": {
"name": "C",
"type": "CONFIG"
},
"action": "WRITE"
},
"resourceNamePattern": "C"
}
]
}
]
}

当指定 ?full 时,此 API 的输出格式已弃用,在以后的版本中将更改为同时设置 ?full?simplifyPermissions 标志时使用的输出格式。

resourceNamePattern 是资源名称正则表达式的编译版本。它是多余的,并且使前端等编辑授权配置的客户端使用此 API 变得复杂,因为该输出中的权限格式与添加到角色时使用的格式不匹配。

  • ?full?simplifyPermissions:当同时设置 ?full?simplifyPermissions 时,输出中的权限将仅包含 resourceAction 对象的列表,而不包含多余的 resourceNamePattern 字段。
{
"name": "druid2",
"roles": [
{
"name": "druidRole",
"users": null,
"permissions": [
{
"resource": {
"name": "A",
"type": "DATASOURCE"
},
"action": "READ"
},
{
"resource": {
"name": "C",
"type": "CONFIG"
},
"action": "WRITE"
}
]
}
]
}

POST(/druid-ext/basic-security/authorization/db/{authorizerName}/users/{userName})
创建一个名为 {userName} 的新用户。

DELETE(/druid-ext/basic-security/authorization/db/{authorizerName}/users/{userName})
删除名称为 {userName} 的用户。

组映射创建/删除

GET(/druid-ext/basic-security/authorization/db/{authorizerName}/groupMappings)
返回所有组映射列表。

GET(/druid-ext/basic-security/authorization/db/{authorizerName}/groupMappings/{groupMappingName})
返回名称为 {groupMappingName} 的组映射的组映射和角色信息。

POST(/druid-ext/basic-security/authorization/db/{authorizerName}/groupMappings/{groupMappingName})
创建一个名为 {groupMappingName} 的新组映射。内容:JSON 组映射对象。请求体示例:

{
"name": "user",
"groupPattern": "CN=aaa,OU=aaa,OU=Groupings,DC=corp,DC=company,DC=com",
"roles": [
"user"
]
}

DELETE(/druid-ext/basic-security/authorization/db/{authorizerName}/groupMappings/{groupMappingName})
删除名为 {groupMappingName} 的组映射。

角色创建/删除

GET(/druid-ext/basic-security/authorization/db/{authorizerName}/roles)
返回所有角色名称列表。

GET(/druid-ext/basic-security/authorization/db/{authorizerName}/roles/{roleName})
返回名为 {roleName} 的角色的名称和权限。

输出示例:

{
"name": "druidRole2",
"permissions": [
{
"resourceAction": {
"resource": {
"name": "E",
"type": "DATASOURCE"
},
"action": "WRITE"
},
"resourceNamePattern": "E"
}
]
}

此 API 的默认输出格式已弃用,在以后的版本中将更改为设置 ?simplifyPermissions 标志时使用的输出格式。resourceNamePattern 是资源名称正则表达式的编译版本。它是多余的,并且使前端等编辑授权配置的客户端使用此 API 变得复杂,因为该输出中的权限格式与添加到角色时使用的格式不匹配。

此 API 支持以下标志:

  • ?full:输出将包含一个额外的 users 列表,其中包含当前拥有此角色的用户。
{"users":["druid"]}
  • ?simplifyPermissions:输出中的权限将仅包含 resourceAction 对象的列表,而不包含多余的 resourceNamePattern 字段。当未指定 ?full 时,users 字段将为 null。

输出示例:

{
"name": "druidRole2",
"users": null,
"permissions": [
{
"resource": {
"name": "E",
"type": "DATASOURCE"
},
"action": "WRITE"
}
]
}

POST(/druid-ext/basic-security/authorization/db/{authorizerName}/roles/{roleName})
创建一个名为 {roleName} 的新角色。内容:用户名字符串。

DELETE(/druid-ext/basic-security/authorization/db/{authorizerName}/roles/{roleName})
删除名为 {roleName} 的角色。

角色分配

POST(/druid-ext/basic-security/authorization/db/{authorizerName}/users/{userName}/roles/{roleName})
将角色 {roleName} 分配给用户 {userName}。

DELETE(/druid-ext/basic-security/authorization/db/{authorizerName}/users/{userName}/roles/{roleName})
从用户 {userName} 取消分配角色 {roleName}。

POST(/druid-ext/basic-security/authorization/db/{authorizerName}/groupMappings/{groupMappingName}/roles/{roleName})
将角色 {roleName} 分配给组映射 {groupMappingName}。

DELETE(/druid-ext/basic-security/authorization/db/{authorizerName}/groupMappings/{groupMappingName}/roles/{roleName})
从组映射 {groupMappingName} 取消分配角色 {roleName}。

权限

POST(/druid-ext/basic-security/authorization/db/{authorizerName}/roles/{roleName}/permissions)
设置 {roleName} 的权限。这将替换该角色上之前的一组权限。

内容:JSON 资源-操作对象列表,例如:

[
{
"resource": {
"name": "wiki.*",
"type": "DATASOURCE"
},
"action": "READ"
},
{
"resource": {
"name": "wikiticker",
"type": "DATASOURCE"
},
"action": "WRITE"
}
]

权限定义中资源的 "name" 字段是正则表达式,用于在授权检查期间匹配资源名称。

请参阅定义权限以获取更多详细信息。

缓存加载状态

GET(/druid-ext/basic-security/authorization/loadStatus)
返回授权 Druid 元数据存储的本地缓存的当前加载状态。