用户认证
edit用户认证
edit身份验证用于识别个人。为了访问受限资源,用户必须通过密码、凭证或其他方式(通常称为身份验证令牌)证明其身份。
Elastic Stack 通过识别请求到达集群的用户并验证他们是否是他们所声称的人来进行用户认证。认证过程由一个或多个称为领域的认证服务处理。
您可以使用本机支持来管理和验证用户,或与外部用户管理系统(如LDAP和Active Directory)集成。
Elastic Stack 安全功能提供了内置的领域,如 native
、ldap
、
active_directory
、pki
、file
、saml
、kerberos
、oidc
和 jwt
。如果
这些内置领域都不符合您的需求,您还可以构建自己的
自定义领域并将其插入到 Elastic Stack 中。
当启用安全功能时,根据您配置的领域,您必须将用户凭据附加到发送给Elasticsearch的请求中。例如,当使用支持用户名和密码的领域时,您可以简单地将基本认证头附加到请求中。
安全功能提供两种服务:令牌服务和API密钥服务。您可以使用这些服务将当前的身份验证交换为令牌或密钥。然后,此令牌或密钥可以用作身份验证新请求的凭据。 API密钥服务默认启用。 当为HTTP启用TLS/SSL时,令牌服务默认启用。
内置用户
editElastic Stack 安全功能提供了内置的用户凭证,以帮助您快速启动和运行。这些用户具有固定的权限集,并且在设置密码之前无法进行身份验证。elastic
用户可以用于 设置所有内置用户的密码。
在 Elastic Cloud 上,操作员权限 已启用。 这些权限限制了一些基础设施功能,即使某个角色 原本允许用户完成管理任务。
-
elastic
-
一个内置的超级用户。
任何可以以
elastic
用户身份登录的人都有直接的只读访问权限,可以访问受限的索引,例如.security
。此用户还具有管理安全性和创建具有无限权限的角色的能力。 -
kibana_system
- Kibana 用于连接和与 Elasticsearch 通信的用户。
-
logstash_system
- 存储监控信息到Elasticsearch时Logstash使用的用户。
-
beats_system
- 在将监控信息存储到Elasticsearch时,Beats使用的用户。
-
apm_system
- 当APM服务器将监控信息存储在Elasticsearch中时使用的用户。
-
remote_monitoring_user
-
收集和存储监控信息到Elasticsearch时,Metricbeat使用的用户。它具有内置的
remote_monitoring_agent
和remote_monitoring_collector
角色。
内置用户的工作原理
edit这些内置用户存储在一个特殊的 .security
索引中,该索引由 Elasticsearch 管理。如果内置用户被禁用或其密码更改,更改会自动反映在集群中的每个节点上。然而,如果你的 .security
索引被删除或从快照中恢复,你应用的任何更改都将丢失。
尽管它们共享相同的API,内置用户与由本地领域管理的用户是分开且不同的。禁用本地领域不会对内置用户产生任何影响。可以使用禁用用户API单独禁用内置用户。
Elastic 引导密码
edit当您安装 Elasticsearch 时,如果 elastic
用户还没有密码,
它会使用默认的引导密码。引导密码是一个临时的
密码,使您能够运行设置所有内置用户密码的工具。
默认情况下,引导密码是从一个随机化的 keystore.seed
设置中派生的,该设置在安装期间被添加到密钥库中。您不需要知道或更改此引导密码。如果您在密钥库中定义了 bootstrap.password
设置,则将使用该值。有关与密钥库交互的更多信息,请参阅 安全设置。
在您为内置用户设置密码,特别是为elastic
用户设置密码后,引导密码将不再有进一步的用途。
设置内置用户密码
edit您必须为所有内置用户设置密码。
使用 elasticsearch-setup-passwords
工具是为内置用户首次设置密码的最简单方法。它使用 elastic
用户的引导密码来运行用户管理 API 请求。例如,您可以在“交互”模式下运行该命令,该模式会提示您为 elastic
、kibana_system
、logstash_system
、beats_system
、apm_system
和 remote_monitoring_user
用户输入新密码:
bin/elasticsearch-setup-passwords interactive
有关命令选项的更多信息,请参阅 elasticsearch-setup-passwords。
为elastic
用户设置密码后,引导密码将不再有效;您无法再次运行elasticsearch-setup-passwords
命令。
或者,您可以通过使用Kibana中的管理 > 用户页面或更改密码 API来设置内置用户的初始密码。这些方法更为复杂。您必须提供elastic
用户及其引导密码才能登录Kibana或运行API。这意味着您不能使用从keystore.seed
设置派生的默认引导密码。相反,您必须在启动Elasticsearch之前在密钥库中显式设置bootstrap.password
设置。例如,以下命令会提示您输入新的引导密码:
bin/elasticsearch-keystore add "bootstrap.password"
然后,您可以启动 Elasticsearch 和 Kibana,并使用 elastic
用户和引导密码登录 Kibana 并更改密码。或者,您可以为每个内置用户提交更改密码 API 请求。这些方法更适合在初始设置完成后更改密码,因为在那时引导密码不再需要。
将内置用户密码添加到 Kibana
edit在设置了kibana_system
用户密码后,您需要通过在kibana.yml
配置文件中设置elasticsearch.password
来更新Kibana服务器的新密码:
elasticsearch.password: kibanapassword
请参阅在Kibana中配置安全性。
将内置用户密码添加到 Logstash
edit当为 Logstash 启用监控时,logstash_system
用户在 Logstash 内部使用。
要在 Logstash 中启用此功能,您需要通过在 logstash.yml
配置文件中设置 xpack.monitoring.elasticsearch.password
来更新 Logstash 配置以使用新密码:
xpack.monitoring.elasticsearch.password: logstashpassword
如果你从旧版本的 Elasticsearch 升级,出于安全原因,logstash_system
用户可能默认被设置为 禁用。一旦密码被更改,你可以通过以下 API 调用来启用该用户:
PUT _security/user/logstash_system/_enable
请参阅配置Logstash监控的凭据。
将内置用户密码添加到 Beats
edit当为 Beats 启用监控时,beats_system
用户在 Beats 内部使用。
要在 Beats 中启用此功能,您需要更新每个 Beats 的配置,以引用正确的用户名和密码。例如:
xpack.monitoring.elasticsearch.username: beats_system xpack.monitoring.elasticsearch.password: beatspassword
例如,请参见监控 Metricbeat。
当 Metricbeat 收集并存储 Elastic Stack 的监控数据时,会使用 remote_monitoring_user
。请参阅 生产环境中的监控。
如果你从旧版本的 Elasticsearch 升级,那么你可能没有为 beats_system
或 remote_monitoring_user
用户设置密码。如果是这种情况,那么你应该使用 Kibana 中的 管理 > 用户 页面或 更改密码 API 为这些用户设置密码。
将内置用户密码添加到APM
edit当监控启用时,apm_system
用户在 APM 内部使用。
要在APM中启用此功能,您需要更新apm-server.yml
配置文件,以引用正确的用户名和密码。例如:
xpack.monitoring.elasticsearch.username: apm_system xpack.monitoring.elasticsearch.password: apmserverpassword
如果你从旧版本的 Elasticsearch 升级,那么你可能没有为 apm_system
用户设置密码。如果是这种情况,那么你应该使用 Kibana 中的 管理 > 用户 页面或 更改密码 API 为这些用户设置密码。
禁用默认密码功能
edit此设置已被弃用。elastic 用户不再有默认密码。 在使用该用户之前,必须设置密码。 请参阅 The Elastic bootstrap password。
服务账户
editElastic Stack 安全功能提供了专门用于与连接到 Elasticsearch 的外部服务(如 Fleet 服务器)集成的服务账户。服务账户具有固定的权限集,并且在您为其创建服务账户令牌之前无法进行身份验证。此外,服务账户在代码中预定义,并且始终启用。
服务帐户对应于特定的外部服务。您为服务帐户创建服务帐户令牌。然后,服务可以使用该令牌进行身份验证并执行相关操作。例如,Fleet 服务器可以使用其服务令牌向 Elasticsearch 进行身份验证,然后管理其自己的 API 密钥。
您可以为同一个服务帐户创建多个服务令牌,这可以防止同一外部服务的多个实例之间共享凭证。每个实例可以使用自己的唯一服务令牌进行身份验证,同时保持相同的身份。
服务账户比内置用户提供了更大的灵活性,因为它们:
-
不要依赖内部
native
领域,并且不一定需要依赖.security
索引 - 使用以服务账户主体命名的角色描述符,而不是传统的角色
- 通过服务账户令牌支持多种凭证
服务账户不包含在 获取用户API的响应中。要检索服务账户,请使用 获取服务账户API。使用 获取服务账户凭证API 来检索服务账户的所有服务凭证。
服务账户使用
edit服务账户有一个
唯一的principal,其格式为
,其中namespace
是服务账户的顶级分组,而service
是服务的名称,并且在其命名空间内必须是唯一的。
服务账户在代码中预定义。以下服务账户可用:
-
elastic/fleet-server
- 用于Fleet服务器与Elasticsearch通信的服务账户。
-
elastic/kibana
- Kibana用于与Elasticsearch通信的服务帐户。
-
elastic/enterprise-search-server
- 用于企业搜索与Elasticsearch通信的服务帐户。
不要尝试使用服务账户来验证单个用户。服务账户只能通过服务令牌进行身份验证,这些令牌不适用于普通用户。
服务账户令牌
edit服务账户令牌,或服务令牌,是一个唯一的字符串,服务使用它来与Elasticsearch进行身份验证。对于给定的服务账户,每个令牌必须有一个唯一的名称。因为令牌包含访问凭证,所以无论哪个客户端在使用它们,都应该始终保持其机密性。
服务令牌可以由 .security
索引(推荐)或 service_tokens
文件支持。您可以为一个服务帐户创建多个服务令牌,这使得同一服务的多个实例能够使用不同的凭证运行。
您必须创建一个服务令牌以使用服务帐户。您可以使用以下任一方式创建服务令牌:
-
创建服务账户令牌API,
该API将新的服务令牌保存在
.security
索引中,并在HTTP响应中返回承载令牌。 -
elasticsearch-service-tokens命令行工具,该工具
将新的服务令牌保存在
$ES_HOME/config/service_tokens
文件中,并将承载令牌输出到您的终端。
我们建议您通过REST API而不是CLI创建服务令牌。API将服务令牌存储在.security
索引中,这意味着令牌可用于所有节点上的身份验证,并将备份在集群快照中。CLI的使用适用于存在外部编排过程(如Elastic Cloud Enterprise或Elastic Cloud on Kubernetes)的情况,这些过程将管理service_tokens
文件的创建和分发。
这两种方法(API 和 CLI)都会创建一个服务令牌,其秘密字符串长度保证为 22
。
服务令牌的秘密字符串的最小可接受长度为 10
。
如果秘密字符串不满足此最小长度,与 Elasticsearch 的认证将失败,甚至不会检查服务令牌的值。
服务令牌永不过期。如果不再需要它们,您必须主动删除它们。
使用服务令牌进行身份验证
edit服务账户目前不支持基本身份验证。
要使用服务账户令牌,请在请求中包含生成的令牌值,并使用Authorization: Bearer
头:
curl -H "Authorization: Bearer AAEAAWVsYXN0aWM...vZmxlZXQtc2VydmVyL3Rva2VuMTo3TFdaSDZ" http://localhost:9200/_security/_authenticate
成功的身份验证响应包括一个token
字段,其中包含一个name
字段用于服务令牌的名称和一个type
字段用于服务令牌的类型:
{ "username": "elastic/fleet-server", "roles": [], "full_name": "Service account - elastic/fleet-server", "email": null, "token": { "name": "token1", "type": "_service_account_index" }, "metadata": { "_elastic_service_account": true }, "enabled": true, "authentication_realm": { "name": "_service_account", "type": "_service_account" }, "lookup_realm": { "name": "_service_account", "type": "_service_account" }, "authentication_type": "token" }
内部用户
edit这些用户仅用于 Elasticsearch 的内部使用。不支持使用这些用户进行身份验证。
Elastic Stack 安全功能使用八个内部用户(_system
、_xpack
、
_xpack_security
、_async_search
、_security_profile
、_data_stream_lifecycle
、_synonyms
和 _storage
),
这些用户负责在 Elasticsearch 集群内部进行的操作。
这些用户仅用于源自集群内部的请求。因此,它们不能用于对API进行身份验证,并且没有需要管理或重置的密码。
偶尔你可能会在你的日志中看到这些用户之一的引用,包括审计日志。
基于令牌的身份验证服务
editElastic Stack 安全功能通过使用领域和一种或多种基于令牌的身份验证服务来验证用户。基于令牌的身份验证服务用于验证和管理令牌。您可以将这些令牌附加到发送到 Elasticsearch 的请求中,并将其用作凭证。当 Elasticsearch 收到需要身份验证的请求时,它会首先咨询基于令牌的身份验证服务,然后是领域链。
安全功能提供了以下内置的基于令牌的身份验证服务,这些服务按照它们被咨询的顺序列出:
- service-accounts
-
服务帐户使用服务帐户创建服务帐户令牌API或elasticsearch-service-tokens CLI工具生成服务帐户令牌。
要使用服务账户令牌,请在请求中包含生成的令牌值,并使用
Authorization: Bearer
头:curl -H "Authorization: Bearer AAEAAWVsYXN0aWMvZ...mXQtc2VydmMTpyNXdkYmRib1FTZTl2R09Ld2FKR0F3" http://localhost:9200/_cluster/health
不要尝试使用服务账户来验证单个用户。服务账户只能通过服务令牌进行身份验证,这些令牌不适用于普通用户。
- token-service
-
令牌服务使用获取令牌 API根据OAuth2规范生成访问令牌和刷新令牌。 访问令牌是短期的。默认情况下,它在20分钟后过期,但可以配置为最长持续1小时。它可以通过使用有效期为24小时的刷新令牌来刷新。访问令牌是持有者令牌。您可以通过发送带有
Authorization
标头的请求来使用它,该标头的值以“Bearer ”为前缀,后跟访问令牌的值。例如:curl -H "Authorization: Bearer dGhpcyBpcyBub3Qx5...F0YS4gZG8gbm90IHRyeSB0byByZWFkIHRva2VuIQ==" http://localhost:9200/_cluster/health
- api-key-service
-
API 密钥服务使用 创建 API 密钥 API 来生成 API 密钥。 默认情况下,API 密钥不会过期。当您发出创建 API 密钥的请求时,您可以指定过期时间和 API 密钥的权限。权限受限于已认证用户的权限。您可以通过发送带有
Authorization
标头的请求来使用 API 密钥,该标头的值以 "ApiKey " 为前缀,后跟凭据。凭据是 API 密钥 ID 和 API 密钥通过冒号连接后的 base64 编码。例如:curl -H "Authorization: ApiKey VnVhQ2ZHY0JDZGJrU...W0tZTVhT3g6dWkybHAyYXhUTm1zeWFrd0dk5udw==" http://localhost:9200/_cluster/health
根据您的使用场景,您可能需要决定这些服务生成的令牌的生命周期。然后,您可以使用此信息来决定使用哪个服务来生成和管理令牌。非过期的API密钥可能看起来是一个简单的选择,但您必须考虑与非过期密钥相关的安全影响。token-service和api-key-service都允许您使令牌失效。请参阅使令牌失效API和使API密钥失效API。
Elasticsearch 8.2 中引入了对 JWT 承载令牌的身份验证支持,通过 JWT 身份验证,该功能无法通过令牌身份验证服务启用。领域提供了灵活的顺序和配置,可以有零个、一个或多个 JWT 领域。
用户资料
edit用户配置文件功能仅设计用于 Kibana 和 Elastic 的可观测性、企业搜索及 Elastic 安全解决方案。个人用户和外部应用程序不应直接调用此 API。Elastic 保留在未来的版本中更改或移除此功能而无需事先通知的权利。
因为 Elastic Stack 支持外部管理的用户(例如通过 SAML 进行身份验证的用户,或存储在 LDAP 目录中的用户),所以 用户 和他们的 配置文件 之间存在区别。
用户指的是向Elastic Stack进行请求认证的实体。 每个用户都有一个用户名和一组权限(由角色表示), 这些权限决定了他们可以发出哪种类型的请求。用户可以是短暂的; 他们可能仅在向Elasticsearch API发出请求期间或Kibana会话的生命周期内存在。这些用户在会话结束后无法被检索, 并且无法在会话之间存储偏好设置。
用户档案提供了用户持久且稳定的表示。 即使用户处于离线状态,用户档案仍然存在,因此他们的档案会在会话之间持续存在。 分配给每个档案的唯一标识符在整个部署期间不会改变,提供了一种稳定的引用关联用户的方式。每个档案都有一个唯一标识符,可以被搜索,并且可以存储用户数据,如格式和通知偏好。
无论用户是否处于活跃在线状态,能够唯一地引用用户是一项关键功能,它支撑着Kibana中个性化和协作等重要功能。
Kibana 中的用户配置文件
edit用户配置文件是 Elastic Stack 为每个向 Kibana 进行身份验证的交互用户存储的持久记录。
当用户登录到 Kibana 时,会自动为用户创建一个配置文件,或者更新现有配置文件以反映用户的活动会话。通过使用用户配置文件的唯一 ID,Kibana 可以为每个用户单独存储用户级别的数据,例如偏好设置,这是实现细粒度定制的关键。Kibana 使用此唯一 ID 将消息和通知路由到特定用户,无论他们是否已登录。
创建和管理用户档案
edit要创建新用户配置文件或更新现有配置文件,请使用激活用户配置文件API。当您提交请求时,Elasticsearch会尝试为指定用户查找现有的配置文件文档。如果不存在,Elasticsearch会创建一个新的配置文件文档。
无论哪种情况,配置文件文档都会捕获用户的full_name
、email
、
roles
和realms
,还包括配置文件的唯一ID和操作的时间戳。您可以通过包含配置文件的唯一ID(uid
)来使用
获取用户配置文件 API检索用户配置文件。
除了用户的基本信息外,您还可以使用更新用户资料 API向用户资料文档添加数据。例如,您可以将用户特定的偏好作为资料数据的一部分添加。
使用suggest user profile API来检索符合给定条件的用户档案。此API旨在支持用户建议,并与Kibana等功能的特性协作。然而,suggest user profile API并不旨在提供一个通用的搜索API。
最后,您可以使用用户配置文件的has privileges API通过指定其配置文件的唯一ID来检查多个用户的权限。 这可以与suggest user profile API结合使用,以便仅将建议限制为具有在上下文中实际执行操作所需权限的用户。
限制
edit-
创建新的用户配置文件需要用户的身份验证详细信息
(
username
和password
或其 OAuth2访问令牌)。 这意味着用户必须至少进行一次身份验证才能创建用户配置文件。从未向Kibana (或其他支持配置文件的应用程序)进行身份验证的用户将没有用户配置文件,并且 建议用户配置文件API 不会为这些用户返回任何结果。 -
用户配置文件适用于交互式用户,例如与Kibana交互的人类用户。因此,用户配置文件不支持API密钥或服务账户。
OAuth2令牌表示交互式最终用户是受支持的。
领域
editElastic Stack 安全功能通过使用领域和一个或多个 基于令牌的身份验证服务来验证用户。
一个领域用于根据身份验证令牌解析和验证用户。安全功能提供了以下内置领域:
- native
- 一个内部领域,用户存储在专用的 Elasticsearch 索引中。 此领域支持以用户名和密码形式的身份验证令牌, 并且在未明确配置领域时默认可用。用户 通过 用户管理 API 进行管理。 参见 本地用户身份验证。
- ldap
- 使用外部LDAP服务器进行用户身份验证的领域。此领域支持以用户名和密码形式的身份验证令牌,并且需要显式配置才能使用。请参阅 LDAP用户身份验证。
- active_directory
- 使用外部Active Directory服务器进行用户身份验证的领域。通过此领域,用户通过用户名和密码进行身份验证。 参见Active Directory用户身份验证。
- pki
- 使用公钥基础设施(PKI)进行用户身份验证的领域。此领域与SSL/TLS结合使用,并通过客户端X.509证书的专有名称(DN)来识别用户。请参阅PKI用户身份验证。
- file
- 一个内部领域,用户定义在存储在Elasticsearch集群中每个节点上的文件中。此领域支持以用户名和密码形式的身份验证令牌,并且始终可用。请参阅基于文件的用户认证。
- saml
- 一个使用SAML 2.0 Web SSO协议进行身份验证的领域。 此领域旨在通过Kibana支持身份验证,并不适用于REST API。请参阅SAML身份验证。
- kerberos
- 一个使用Kerberos认证来验证用户的领域。用户基于Kerberos票据进行认证。参见Kerberos认证。
- oidc
- 一个使用OpenID Connect进行身份验证的领域。它使Elasticsearch能够作为OpenID Connect依赖方(RP),并在Kibana中提供单点登录(SSO)支持。请参阅使用OpenID Connect配置Elastic Stack的单点登录。
- jwt
- 一个使用JWT身份令牌作为认证承载令牌的领域。 兼容的令牌包括OpenID Connect ID令牌或包含相同声明的自定义JWT。 参见JWT认证。
安全功能还支持自定义领域。如果您需要与其他身份验证系统集成,可以构建一个自定义领域插件。有关更多信息,请参阅与其他身份验证系统集成。
内部和外部领域
edit领域类型大致可以分为两类:
- Internal
-
Elasticsearch 内部使用的领域,不需要与外部方进行任何通信。它们完全由 Elastic Stack 的安全功能管理。每个内部领域类型最多只能配置一个领域。安全功能提供了两种内部领域类型:
native
和file
。 - External
-
需要与Elasticsearch外部的各方/组件进行交互的领域,通常与企业级身份管理系统进行交互。与内部领域不同,可以有任意数量的外部领域 - 每个领域都有其独特的名称和配置。安全功能提供了以下外部领域类型:
ldap
、active_directory
、saml
、kerberos
和pki
。
领域链
edit领域存在于一个领域链中。它本质上是一个配置领域的优先级列表(通常是各种类型的领域)。领域按照升序进行咨询(也就是说,具有最低order
值的领域首先被咨询)。你必须确保每个配置的领域都有一个独特的order
设置。如果两个或多个领域具有相同的order
,节点将无法启动。
在认证过程中,Elastic Stack 安全功能会依次咨询并尝试在每个领域中认证请求。一旦其中一个领域成功认证了请求,认证就被认为是成功的。认证的用户与请求相关联,然后请求进入授权阶段。如果一个领域无法认证请求,链中的下一个领域将被咨询。如果链中的所有领域都无法认证请求,认证就被认为是不成功的,并返回一个认证错误(作为 HTTP 状态码 401
)。
某些系统(例如 Active Directory)在连续多次登录失败后会有一个临时锁定期。如果同一用户名存在于多个领域,可能会导致无意的账户锁定。更多信息,请参见 用户频繁被锁定在 Active Directory 中。
默认的领域链包含file
和native
领域。要显式配置领域链,您可以在elasticsearch.yml
文件中指定链。如果您的领域链不包含file
或native
领域,或者没有显式禁用它们,file
和native
领域将按此顺序自动添加到领域链的开头。要选择退出自动行为,您可以使用order
和enabled
设置显式配置file
和native
领域。
以下代码片段配置了一个领域链,启用了文件
领域以及两个LDAP领域和一个Active Directory领域,但禁用了本地
领域。
xpack.security.authc.realms: file.file1: order: 0 ldap.ldap1: order: 1 enabled: false url: 'url_to_ldap1' ... ldap.ldap2: order: 2 url: 'url_to_ldap2' ... active_directory.ad1: order: 3 url: 'url_to_ad' native.native1: enabled: false
如上所示,每个领域都有一个唯一的名称来标识它。每种类型的领域都有其自己的一组必需和可选设置。也就是说,存在适用于所有领域的设置。
将授权委托给另一个领域
edit一些领域具有内部执行认证的能力,但将角色(即授权)的查找和分配委托给另一个领域。
例如,您可能希望使用PKI领域通过TLS客户端证书来验证您的用户,然后在LDAP领域中查找该用户,并使用他们的LDAP组分配来确定他们在Elasticsearch中的角色。
任何支持检索用户(无需其凭据)的领域都可以用作授权领域(即,其名称可以作为authorization_realms
列表中的一个值出现)。有关哪些领域支持此功能的进一步解释,请参阅无需身份验证查找用户。
对于支持此功能的领域,可以通过在认证领域配置authorization_realms
设置来启用它。查看每个领域的支持的设置列表,以了解它们是否支持authorization_realms
设置。
如果为领域启用了委派授权,它将以标准方式(包括相关缓存)对用户进行身份验证,然后在配置的授权领域列表中查找该用户。它按照authorization_realms
设置中指定的顺序尝试每个领域。用户通过主体检索 - 用户在身份验证和授权领域中的用户名必须相同。如果用户在任何授权领域中都找不到,身份验证将失败。
有关更多详细信息,请参阅配置授权委托。
委托授权要求您拥有一个包含自定义身份验证和授权领域的订阅。
安全域
edit安全域是一种将多个领域归类到同一个域下的方法,以便Elastic Stack能够识别当单个用户使用这些领域进行身份验证时的情况。用户可以使用域组中的任何领域进行身份验证,并且无论他们使用哪个领域进行身份验证,都可以访问相同的资源集。
例如,一个单一的用户配置文件与用户关联, 使得偏好设置、通知和其他用户数据能够在各个领域之间共享。用户可以查看来自异步搜索请求或跨领域的滚动搜索的结果。如果用户具有必要的权限,他们还可以查看和管理跨领域的API密钥。
跨域资源共享
editElasticsearch 中某些类型的资源归单个用户所有,例如 异步搜索上下文、API 密钥 和 用户配置文件。当用户创建资源时,Elasticsearch 会捕获用户的用户名和领域信息作为资源元数据的一部分。同样,如果用户更新资源(例如 API 密钥), Elasticsearch 会自动重新捕获用户的当前领域信息。
当用户稍后尝试访问资源时,Elasticsearch 会将捕获的用户名和领域信息与访问用户的用户名和领域信息进行比较。除非领域和用户名都匹配,否则 Elasticsearch 将拒绝访问。如果 Elasticsearch 检测到来自两个不同领域的用户名尝试访问资源,Elasticsearch 会假设这些用户是不同的,并且不允许这些用户之间共享资源。
然而,有些情况下,同一个用户可以通过多个领域进行身份验证,并且需要在不同领域之间共享同一组资源。例如,LDAP领域和SAML领域可以由同一个目录服务支持。此外,授权委托允许一个领域将授权委托给另一个领域。如果两个领域都使用相同的用户名对用户进行身份验证,那么从资源所有权的角度来看,将这些用户视为同一个用户是合理的。
安全域通过将这些领域分组在同一域下,使得跨领域的资源共享成为可能。Elasticsearch始终强制执行与当前认证用户相关的权限,这在使用安全域时仍然适用。当资源共享需要时,安全域不会绕过用户授权。例如,用户需要manage_own_api_key
权限来管理他们自己的API密钥。如果该用户在通过一个领域认证时没有此权限,他们在通过另一个领域认证时将无法管理API密钥。
配置安全域
edit安全域必须在集群中的所有节点上一致配置。 配置不一致可能导致以下问题:
- 重复的用户配置文件
- 根据认证节点的配置,资源的所有权不同
配置安全域:
-
在
elasticsearch.yml
文件的xpack.security.authc.domains
命名空间中添加安全域配置:指定的 realms 必须在
elasticsearch.yml
中定义,但不需要启用。基于文件的用户认证和本地用户认证会分别自动启用为
default_file
和default_native
,无需任何显式配置。即使它们未在elasticsearch.yml
中显式定义,您也可以在域下列出这些领域。 -
重启 Elasticsearch。
如果域配置无效,Elasticsearch 可能无法启动,例如:
- 同一个领域在多个域下配置。
- 任何未定义的领域、合成领域或保留领域被配置为在域下。
-
在执行与安全域相关的操作之前,请在集群中的所有节点上应用相同的配置,包括创建和管理资源,如用户配置文件、API密钥和异步搜索。
在向安全域添加领域时,避免在更改完全应用到所有节点之前使用新添加的领域进行身份验证。
从安全域中移除领域
edit从安全域中移除领域可能会导致意外行为,因此不建议这样做。 在移除之前创建或更新的资源可能由不同用户拥有,具体取决于资源类型:
与其删除领域,不如考虑禁用它们并将它们作为安全域的一部分保留。 在任何情况下,跨领域资源共享仅在用户使用相同用户名时才可能实现。
Active Directory 用户身份验证
edit您可以配置 Elastic Stack 安全功能以与 Active Directory 通信以验证用户。请参阅 配置 Active Directory 领域。
安全功能使用 LDAP 与 Active Directory 进行通信,因此
active_directory
领域类似于 ldap
领域。与 LDAP 目录类似,Active Directory 以层次结构存储用户和组。目录的层次结构由容器构建,例如 组织单位(ou
)、组织(o
)和 域组件(dc
)。
条目的路径是一个专有名称(DN),用于唯一标识用户或组。用户和组名通常具有诸如通用名称(cn
)或唯一ID(uid
)等属性。DN被指定为一个字符串,例如"cn=admin,dc=example,dc=com"
(空格被忽略)。
安全功能仅支持Active Directory安全组。您不能将通讯组映射到角色。
当您使用 Active Directory 进行身份验证时,用户输入的用户名应与 sAMAccountName
或 userPrincipalName
匹配,而不是通用名称。
Active Directory 领域使用 LDAP 绑定请求来验证用户。在验证用户后,领域会在 Active Directory 中搜索以找到用户的条目。一旦找到用户,Active Directory 领域就会从用户条目中的 tokenGroups
属性中检索用户的组成员身份。
配置Active Directory领域
edit要与Active Directory集成,您需要配置一个active_directory
领域,并将Active Directory用户和组映射到角色映射文件中的角色。
-
在
elasticsearch.yml
文件的xpack.security.authc.realms.active_directory
命名空间下添加一个类型为active_directory
的领域配置。 至少,您必须指定 Active Directory 的domain_name
和order
。请参阅Active Directory realm settings以了解您可以为
active_directory
realm设置的所有选项。如果域名未在DNS中映射,绑定到Active Directory会失败。 如果DNS不是由Windows DNS服务器提供的,请在本地
/etc/hosts
文件中添加域名的映射。例如,以下领域配置将Elasticsearch配置为连接到
ldaps://example.com:636
,以通过Active Directory验证用户:xpack: security: authc: realms: active_directory: my_ad: order: 0 domain_name: ad.example.com url: ldaps://ad.example.com:636
当您在
elasticsearch.yml
中配置领域时,仅使用您指定的领域进行身份验证。如果您还想使用native
或file
领域,则必须将它们包含在领域链中。 -
如果您在林中的多个域中进行用户身份验证,则需要额外的步骤。配置和用户身份验证的方式有一些细微的差异。
将
domain_name
设置为林根域名。您还必须设置
url
设置,因为您必须对全局目录进行身份验证,全局目录使用不同的端口,并且可能不会在每个域控制器上运行。例如,以下领域配置将Elasticsearch配置为连接到全局目录端口上的特定域控制器,并将域名设置为森林根:
xpack: security: authc: realms: active_directory: my_ad: order: 0 domain_name: example.com url: ldaps://dc1.ad.example.com:3269, ldaps://dc2.ad.example.com:3269 load_balance: type: "round_robin"
将
domain_name
设置为林中根域的名称。此示例中使用的
url
值包含两个不同域控制器的URL,这些域控制器同时也是全局编录服务器。端口3268是与全局编录进行未加密通信的默认端口;端口3269是用于SSL连接的默认端口。只要连接到的服务器也是全局编录服务器,它们可以位于林中的任何域中。提供了一个负载均衡设置,用于指示在选择要连接的服务器时的期望行为。
在此配置中,用户需要使用其完整的用户主体名称(UPN)或其下级登录名称。UPN通常是用户名与
@
的组合,例如 johndoe@ad.example.com
。下级登录名称是NetBIOS域名,后跟一个\
和用户名,例如AD\johndoe
。使用下级登录名称需要连接到常规LDAP端口(389或636),以便查询配置容器以从NetBIOS名称中检索域名。 -
(可选) 配置 Elasticsearch 如何与多个 Active Directory 服务器交互。
可以在领域级别使用
load_balance.type
设置。支持两种操作模式:故障转移和负载均衡。请参阅Active Directory realm settings。 - (可选) 为了保护密码, 加密 Elasticsearch 和 Active Directory 服务器之间的通信。
- 重启 Elasticsearch。
-
(可选) 配置一个绑定用户。
Active Directory 领域使用 LDAP 绑定请求来验证用户。默认情况下,所有 LDAP 操作都由 Elasticsearch 正在验证的用户执行。在某些情况下,普通用户可能无法访问 Active Directory 中的所有必要项目,因此需要一个 绑定用户。可以配置绑定用户,并用于执行除 LDAP 绑定请求之外的所有操作,该请求是验证用户提供的凭据所必需的。
使用绑定用户可以启用 run as 功能与 Active Directory 领域一起使用,并能够维护一组与 Active Directory 的池化连接。这些池化连接减少了每次用户认证时必须创建和销毁的资源数量。
以下示例展示了通过使用
bind_dn
和secure_bind_password
设置来配置绑定用户:xpack: security: authc: realms: active_directory: my_ad: order: 0 domain_name: ad.example.com url: ldaps://ad.example.com:636 bind_dn: es_svc_user@ad.example.com
应通过将适当的
secure_bind_password
设置添加到 Elasticsearch 密钥库来配置bind_dn
用户的密码。例如,以下命令为上述示例领域添加密码:bin/elasticsearch-keystore add \ xpack.security.authc.realms.active_directory.my_ad.secure_bind_password
当配置了绑定用户时,默认情况下会启用连接池。 可以使用
user_search.pool.enabled
设置来禁用连接池。 -
将Active Directory用户和组映射到角色。
领域认证过程中的一个重要部分是解析与已认证用户相关的角色。角色定义了用户在集群中的权限。
由于使用
active_directory
领域时,用户在外部的 Active Directory 服务器上进行管理,因此期望他们的角色也在那里进行管理。事实上,Active Directory 支持组的概念,这些组通常代表组织中不同系统的用户角色。通过
active_directory
领域,您可以将 Active Directory 用户映射到角色,通过他们的 Active Directory 组或其他元数据。这种角色映射可以通过 角色映射 API 或通过存储在每个节点上的文件进行配置。当用户针对 Active Directory 领域进行身份验证时,该用户的权限是用户映射到的所有角色定义的权限的并集。在映射定义中,您可以使用其专有名称指定组。例如,以下映射配置将Active Directory的
admins
组映射到monitoring
和user
角色,将users
组映射到user
角色,并将John Doe
用户映射到user
角色。通过角色映射 API 配置:
PUT /_security/role_mapping/admins { "roles" : [ "monitoring" , "user" ], "rules" : { "field" : { "groups" : "cn=admins,dc=example,dc=com" } }, "enabled": true }
PUT /_security/role_mapping/basic_users { "roles" : [ "user" ], "rules" : { "any": [ { "field" : { "groups" : "cn=users,dc=example,dc=com" } }, { "field" : { "dn" : "cn=John Doe,cn=contractors,dc=example,dc=com" } } ] }, "enabled": true }
或者,也可以通过角色映射文件进行配置:
Active Directory 领域中的用户元数据
edit当用户通过Active Directory领域进行身份验证时,用户的元数据中会填充以下属性:
字段 |
描述 |
|
用户的唯一标识名称。 |
|
为该用户解析的每个组的专有名称(无论这些组是否映射到角色)。 |
此元数据在authenticate API中返回,并且可以与角色中的模板化查询一起使用。
可以通过在Active Directory领域配置metadata
设置来从Active Directory服务器提取额外的元数据。
负载均衡和故障转移
edit设置 load_balance.type
可以在领域级别用于配置安全功能应如何与多个 Active Directory 服务器交互。
支持两种操作模式:故障转移和负载均衡。
参见 负载均衡和故障转移。
加密 Elasticsearch 与 Active Directory 之间的通信
edit为了保护用于身份验证的用户凭据,强烈建议加密Elasticsearch与Active Directory服务器之间的通信。通过SSL/TLS连接可以确保在Elasticsearch传输用户凭据之前对Active Directory服务器的身份进行验证,并且用户名和密码在传输过程中是加密的。
通过SSL/TLS连接到Active Directory服务器的客户端和节点需要在它们的密钥库或信任库中安装Active Directory服务器的证书或服务器的根CA证书。
-
在
elasticsearch.yml
文件中为xpack.security.authc.realms
命名空间创建领域配置。请参阅配置Active Directory领域。 -
在领域配置中设置
url
属性,以指定LDAPS协议和安全端口号。例如,url: ldaps://ad.example.com:636
。 -
配置每个节点以信任由签署您的Active Directory服务器证书的证书颁发机构(CA)签署的证书。
以下示例演示了如何信任位于配置目录中的CA证书(
cacert.pem
):xpack: security: authc: realms: active_directory: ad_realm: order: 0 domain_name: ad.example.com url: ldaps://ad.example.com:636 ssl: certificate_authorities: [ "ES_PATH_CONF/cacert.pem" ]
CA证书必须是PEM编码的证书。
有关这些设置的更多信息,请参阅Active Directory领域设置。
- 重启Elasticsearch。
默认情况下,当您配置 Elasticsearch 以使用 SSL/TLS 连接到 Active Directory 时,它会尝试验证证书中的主机名或 IP 地址与 realm 配置中 url
属性指定的值是否匹配。如果证书中的值与 realm 配置中的值不匹配,Elasticsearch 将不允许连接到 Active Directory 服务器。这是为了防止中间人攻击。如果需要,您可以通过将 ssl.verification_mode
属性设置为 certificate
来禁用此行为。
基于文件的用户认证
edit您可以使用内置的 file
领域来管理和认证用户。
通过 file
领域,用户在集群中的每个节点上的本地文件中定义。
作为集群的管理员,您的责任是确保在集群的每个节点上定义相同的用户。Elastic Stack 的安全功能并不提供任何机制来保证这一点。您还应该注意,无法通过 用户 API 在 file
领域中添加或管理用户,也无法在 Kibana 的 管理 / 安全 / 用户 页面上添加或管理它们。
文件领域(file
realm)非常有用,可以作为备用或恢复领域。例如,在集群无响应或安全索引不可用的情况下,或者当你忘记了管理用户的密码时。在这种情况下,文件领域是一个方便的解决方案——你可以在文件领域中定义一个新的管理用户(admin
),并使用它登录以重置所有其他用户的凭证。
要定义用户,安全功能提供了 users 命令行工具。该工具使您能够添加 和删除用户、分配用户角色以及管理用户密码。
配置文件领域
edit您不需要显式配置file
领域。默认情况下,file
和native
领域会自动添加到领域链中。除非另有配置,否则file
领域会首先添加,然后是native
领域。
虽然可以定义其他领域的多个实例,但每个节点只能定义一个 文件
领域。
关于file
领域中所有用户的数据存储在集群中每个节点的两个文件中:users
和users_roles
。这两个文件都位于ES_PATH_CONF
中,并在启动时读取。
文件users
和users_roles
由节点在本地管理,并且不由集群全局管理。这意味着在典型的多节点集群中,需要在集群中的每个节点上应用完全相同的更改。
一个更安全的方法是在其中一个节点上应用更改,并将文件分发或复制到集群中的所有其他节点(无论是手动操作还是使用Puppet或Chef等配置管理系统)。
-
(可选) 在
elasticsearch.yml
文件的xpack.security.authc.realms.file
命名空间下添加一个领域配置。至少,您必须设置领域的order
属性。例如,以下代码片段展示了一个
file
领域配置,将order
设置为零,以便首先检查该领域:xpack: security: authc: realms: file: file1: order: 0
您只能在 Elasticsearch 节点上配置一个文件领域。
- 重启 Elasticsearch。
-
将用户信息添加到集群中每个节点上的
ES_PATH_CONF/users
文件中。The
users
文件存储了所有用户及其密码。文件中的每一行代表一个用户条目,包含用户名和哈希并加盐的密码。rdeniro:$2a$10$BBJ/ILiyJ1eBTYoRKxkqbuDEdYECplvxnqQ47uiowE7yGqvCEgj9W alpacino:$2a$10$cNwHnElYiMYZ/T3K4PvzGeJ1KbpXZp2PfoQD.gfaVdImnHOwIuBKS jacknich:{PBKDF2}50000$z1CLJt0MEFjkIK5iEfgvfnA6xq7lF25uasspsTKSo5Q=$XxCVLbaKDimOdyWgLCLJiyoiWpA/XDMe/xtVgn1r5Sg=
为了限制凭证盗窃的风险并减轻凭证泄露的影响,文件领域根据安全最佳实践存储密码并缓存用户凭证。默认情况下,用户凭证的哈希版本使用加盐的
sha-256
哈希算法存储在内存中,并且密码的哈希版本使用加盐和bcrypt
哈希算法存储在磁盘上。要使用不同的哈希算法,请参阅 用户缓存和密码哈希算法。虽然可以使用任何标准文本编辑器直接修改
用户
文件,但我们强烈建议使用elasticsearch-users工具来应用所需的更改。作为集群的管理员,您的责任是确保在集群的每个节点上定义相同的用户。Elasticsearch 安全功能不提供任何机制来保证这一点。
-
在集群中的每个节点上,将角色信息添加到
ES_PATH_CONF/users_roles
文件中。The
users_roles
文件存储与用户关联的角色。例如:admin:rdeniro power_user:alpacino,jacknich user:jacknich
每一行将一个角色映射到一个逗号分隔的与该角色关联的所有用户的列表。
您可以使用elasticsearch-users工具来更新此文件。您必须确保在集群中的每个节点上都进行相同的更改。
-
(可选) 更改检查
users
和users_roles
文件的频率。默认情况下,Elasticsearch 每 5 秒检查这些文件的更改。您可以通过更改
elasticsearch.yml
文件中的resource.reload.interval.high
设置来改变此默认行为(由于这是 Elasticsearch 中的一个常见设置,更改其值可能会影响系统中的其他调度)。
LDAP 用户认证
edit您可以配置 Elastic Stack 安全功能,以便与轻量级目录访问协议 (LDAP) 服务器通信以进行用户身份验证。请参阅 配置 LDAP 领域。
LDAP 以分层方式存储用户和组,类似于文件系统中文件夹的分组方式。LDAP 目录的层次结构由容器构建,例如组织单元(ou
)、组织(o
)和域组件(dc
)。
条目的路径是一个专有名称(DN),用于唯一标识用户或组。用户和组名通常具有诸如通用名称(cn
)或唯一ID(uid
)等属性。DN被指定为一个字符串,例如"cn=admin,dc=example,dc=com"
(空格被忽略)。
The ldap
realm 支持两种操作模式,一种是用户搜索模式,另一种是使用特定模板的用户DN模式。
将LDAP组映射到角色
edit领域认证过程中的一个重要部分是解析与已认证用户相关的角色。角色定义了用户在集群中的权限。
由于使用 ldap
领域时,用户是在 LDAP 服务器中外部管理的,因此期望他们的角色也在那里进行管理。事实上,LDAP 支持组的概念,这些组通常代表组织中不同系统的用户角色。
通过 ldap
领域,您可以将 LDAP 用户通过其 LDAP 组或其他元数据映射到角色。此角色映射可以通过 添加角色映射 API 或通过存储在每个节点上的文件进行配置。当用户通过 LDAP 进行身份验证时,该用户的权限是用户所映射到的所有角色定义的权限的并集。
配置LDAP领域
edit要与 LDAP 集成,您需要配置一个 ldap
领域并将 LDAP 组映射到用户角色。
-
确定您要使用的模式。
ldap
领域支持两种操作模式,一种是用户搜索模式,另一种是具有特定用户DN模板的模式。LDAP 用户搜索是最常见的操作模式。在这种模式下,使用一个具有搜索 LDAP 目录权限的特定用户来根据提供的用户名和 LDAP 属性搜索认证用户的 DN。一旦找到,用户将通过尝试使用找到的 DN 和提供的密码绑定到 LDAP 服务器来进行认证。
如果您的 LDAP 环境使用一些特定的标准命名条件来标识用户,您可以使用用户 DN 模板来配置领域。这种方法的优点是无需执行搜索即可找到用户 DN。然而,可能需要多次绑定操作才能找到正确的用户 DN。
-
配置一个使用用户搜索的
ldap
领域:-
在
elasticsearch.yml
文件的xpack.security.authc.realms.ldap
命名空间下添加一个领域配置。至少,您必须指定 LDAP 服务器的url
和order
,并将user_search.base_dn
设置为用户搜索的容器 DN。 请参阅 LDAP 领域设置 以了解您可以为ldap
领域设置的所有选项。例如,以下代码片段展示了一个配置了用户搜索的LDAP领域:
xpack: security: authc: realms: ldap: ldap1: order: 0 url: "ldaps://ldap.example.com:636" bind_dn: "cn=ldapuser, ou=users, o=services, dc=example, dc=com" user_search: base_dn: "dc=example,dc=com" filter: "(cn={0})" group_search: base_dn: "dc=example,dc=com" files: role_mapping: "ES_PATH_CONF/role_mapping.yml" unmapped_groups_as_roles: false
应通过将适当的
secure_bind_password
设置添加到Elasticsearch密钥库来配置bind_dn
用户的密码。 例如,以下命令为上述示例领域添加密码:bin/elasticsearch-keystore add \ xpack.security.authc.realms.ldap.ldap1.secure_bind_password
当您在
elasticsearch.yml
中配置领域时,仅使用您指定的领域进行身份验证。如果您还想使用native
或file
领域,则必须将它们包含在领域链中。
-
-
要使用用户DN模板配置
ldap
领域:-
在
elasticsearch.yml
文件的xpack.security.authc.realms.ldap
命名空间中添加一个领域配置。至少,您必须指定 LDAP 服务器的url
和order
,并使用user_dn_templates
选项指定至少一个模板。有关为ldap
领域设置的所有选项,请参阅 LDAP 领域设置。例如,以下代码片段展示了一个配置了用户DN模板的LDAP领域:
xpack: security: authc: realms: ldap: ldap1: order: 0 url: "ldaps://ldap.example.com:636" user_dn_templates: - "cn={0}, ou=users, o=marketing, dc=example, dc=com" - "cn={0}, ou=users, o=engineering, dc=example, dc=com" group_search: base_dn: "dc=example,dc=com" files: role_mapping: "/mnt/elasticsearch/group_to_role_mapping.yml" unmapped_groups_as_roles: false
在模板模式下,不使用
bind_dn
设置。 所有LDAP操作都以认证用户身份运行。
-
-
(可选) 配置安全功能如何与多个 LDAP 服务器交互。
可以在领域级别使用
load_balance.type
设置。Elasticsearch的安全功能支持故障转移和负载均衡操作模式。 请参阅LDAP领域设置。 - (可选) 为了保护密码, 加密 Elasticsearch 和 LDAP 服务器之间的通信。
- 重启 Elasticsearch。
-
将 LDAP 组映射到角色。
通过
ldap
领域,您可以将 LDAP 用户通过其 LDAP 组或其他元数据映射到角色。此角色映射可以通过 添加角色映射 API 或通过存储在每个节点上的文件进行配置。当用户使用 LDAP 进行身份验证时,该用户的权限是用户所映射的所有角色定义的权限的并集。在映射定义中,您可以使用其专有名称指定组。例如,以下映射配置将 LDAP
admins
组映射到monitoring
和user
角色,并将users
组映射到user
角色。通过角色映射 API 配置:
PUT /_security/role_mapping/admins { "roles" : [ "monitoring" , "user" ], "rules" : { "field" : { "groups" : "cn=admins,dc=example,dc=com" } }, "enabled": true }
PUT /_security/role_mapping/basic_users { "roles" : [ "user" ], "rules" : { "field" : { "groups" : "cn=users,dc=example,dc=com" } }, "enabled": true }
或者,也可以通过角色映射文件进行配置:
monitoring: - "cn=admins,dc=example,dc=com" user: - "cn=users,dc=example,dc=com" - "cn=admins,dc=example,dc=com"
更多信息,请参阅 映射 LDAP 组到角色 和 映射用户和组到角色。
LDAP 领域支持 授权领域作为角色映射的替代方案。
-
(可选) 在 LDAP 领域配置
metadata
设置,以在用户的元数据中包含额外字段。默认情况下,用户的元数据中会填充
ldap_dn
和ldap_groups
。 有关更多信息,请参阅 LDAP 领域中的用户元数据。下面的示例在用户的元数据中包含了用户的常用名称(
cn
)作为附加字段。xpack: security: authc: realms: ldap: ldap1: order: 0 metadata: cn
- 设置 SSL 以加密 Elasticsearch 和 LDAP 之间的通信。请参阅 加密 Elasticsearch 和 LDAP 之间的通信。
LDAP 领域中的用户元数据
edit当用户通过LDAP领域进行身份验证时,用户的元数据中会填充以下属性:
字段 |
描述 |
|
用户的唯一标识名称。 |
|
为该用户解析的每个组的专有名称(无论这些组是否映射到角色)。 |
此元数据在 authenticate API中返回,并且可以与角色中的 模板化查询一起使用。
可以通过在LDAP领域配置metadata
设置来在用户元数据中包含其他字段。此元数据可用于角色映射API或在模板化角色查询中使用。
负载均衡和故障转移
edit在领域级别可以使用load_balance.type
设置来配置安全功能如何与多个LDAP服务器交互。安全功能支持故障转移和负载均衡两种操作模式。
参见 负载均衡和故障转移。
加密 Elasticsearch 与 LDAP 之间的通信
edit为了保护在LDAP领域中用于身份验证的用户凭据,强烈建议加密Elasticsearch与LDAP服务器之间的通信。通过SSL/TLS连接可以确保在Elasticsearch传输用户凭据之前对LDAP服务器的身份进行认证,并且连接内容被加密。通过TLS连接到LDAP服务器的客户端和节点需要在它们的密钥库或信任库中安装LDAP服务器的证书或服务器的根CA证书。
更多信息,请参阅LDAP用户认证。
-
在每个节点上配置域的TLS设置,以信任由签署LDAP服务器证书的CA签署的证书。以下示例演示了如何信任位于Elasticsearch 配置目录中的CA证书
cacert.pem
:xpack: security: authc: realms: ldap: ldap1: order: 0 url: "ldaps://ldap.example.com:636" ssl: certificate_authorities: [ "cacert.pem" ]
在上面的示例中,CA证书必须是PEM编码的。
PKCS#12 和 JKS 文件也受支持 - 请参阅 LDAP realm settings 中关于
ssl.truststore.path
的描述。您也可以指定单个服务器证书而不是CA证书,但这仅在您拥有单个LDAP服务器或证书是自签名的情况下才推荐使用。
-
设置域配置中的
url
属性以指定LDAPS协议和安全端口号。例如,url: ldaps://ldap.example.com:636
。 - 重启Elasticsearch。
默认情况下,当您配置 Elasticsearch 以使用 SSL/TLS 连接到 LDAP 服务器时,它会尝试验证证书中的主机名或 IP 地址与领域配置中 url
属性指定的值是否匹配。如果证书中的值与领域配置中的值不匹配,Elasticsearch 将不允许连接到 LDAP 服务器。这是为了防止中间人攻击。如果需要,您可以通过将 ssl.verification_mode
属性设置为 certificate
来禁用此行为。
本地用户认证
edit管理和认证用户的最佳方式是使用内置的native
领域。您可以使用REST API或Kibana来添加和删除用户、分配用户角色以及管理用户密码。
配置原生领域
edit原生领域默认情况下是可用且启用的。你可以使用以下代码片段显式禁用它。
xpack.security.authc.realms.native.native1: enabled: false
您可以在 elasticsearch.yml
文件的 xpack.security.authc.realms.native
命名空间中配置一个 native
领域。
显式配置一个 native 领域使您能够设置它在领域链中的顺序,临时禁用该领域,并控制其缓存选项。
-
在
elasticsearch.yml
文件的xpack.security.authc.realms.native
命名空间下添加一个领域配置。建议您明确设置领域的order
属性。您只能在Elasticsearch节点上配置一个原生领域。
查看 Native realm settings 以了解您可以为
native
realm 设置的所有选项。 例如,以下代码片段展示了一个native
realm 配置, 将order
设置为零,以便首先检查该 realm:xpack.security.authc.realms.native.native1: order: 0
为了限制凭证盗窃的风险并减轻凭证泄露的影响, 原生领域根据安全最佳实践存储密码并缓存用户凭证。默认情况下,用户凭证的哈希版本 存储在内存中,使用加盐的
sha-256
哈希算法,并且密码的哈希版本 存储在磁盘上,使用加盐和bcrypt
哈希算法进行哈希处理。要使用不同的哈希算法,请参阅 用户缓存和密码哈希算法。 - 重启Elasticsearch。
OpenID Connect 认证
editOpenID Connect 领域使 Elasticsearch 能够作为 OpenID Connect 依赖方 (RP) 并提供 Kibana 中的单点登录 (SSO) 支持。
它专门设计用于通过交互式网页浏览器支持身份验证,因此它不作为标准身份验证领域运行。相反,Kibana 和 Elasticsearch 安全功能协同工作,以启用交互式 OpenID Connect 会话。
这意味着 OpenID Connect 领域不适合标准 REST 客户端使用。如果您在 Kibana 中配置了 OpenID Connect 领域,您还应该配置另一个领域,例如身份验证链中的 native realm。
为了简化在Elastic Stack中配置OpenID Connect身份验证的过程,这里有一个逐步指南:使用OpenID Connect配置Elastic Stack的单点登录。
PKI 用户认证
edit您可以配置 Elasticsearch 使用公钥基础设施 (PKI) 证书来验证用户。在此场景中,直接连接到 Elasticsearch 的客户端必须提供 X.509 证书。首先,必须在 Elasticsearch 的 SSL/TLS 层接受这些证书以进行身份验证。然后,它们可以选择性地由 PKI 领域进一步验证。请参阅 PKI authentication for clients connecting directly to Elasticsearch。
您还可以使用PKI证书来验证Kibana的身份,但这需要一些额外的配置。在Elasticsearch上,此配置使Kibana能够充当SSL/TLS身份验证的代理,并将客户端证书提交给Elasticsearch以供PKI领域进一步验证。请参阅PKI authentication for clients connecting to Kibana。
直接连接到 Elasticsearch 的客户端的 PKI 认证
edit要在 Elasticsearch 中使用 PKI,您需要配置一个 PKI 领域,在所需的网络层(传输或 http)上启用客户端认证,并将用户证书中的主题字段中的可分辨名称(DNs)映射到角色。您可以在角色映射文件中创建映射,或使用角色映射 API。
-
在
elasticsearch.yml
文件的xpack.security.authc.realms.pki
命名空间下添加一个pki
领域的配置。您必须显式设置order
属性。有关可以为pki
领域设置的所有选项,请参阅 PKI 领域设置。例如,以下代码片段展示了最基本的
pki
领域配置:xpack: security: authc: realms: pki: pki1: order: 1
通过此配置,Elasticsearch SSL/TLS 层信任的任何证书都可用于身份验证。用户名是从终端实体证书的 Subject 字段中的 DN 提取的通用名称 (CN)。此配置不足以允许 PKI 身份验证到 Kibana;还需要其他步骤。
当您在
elasticsearch.yml
中配置领域时,仅使用您指定的领域进行身份验证。如果您还想使用native
或file
领域,则必须将它们包含在领域链中。 -
可选:用户名由 username_pattern 定义。 如果你想使用不同于主题 DN 的 CN 作为用户名,可以指定一个正则表达式来提取所需的用户名。该正则表达式应用于主题 DN。
例如,以下配置中的正则表达式从主题DN中提取电子邮件地址:
xpack: security: authc: realms: pki: pki1: order: 1 username_pattern: "EMAILADDRESS=(.*?)(?:,|$)"
如果正则表达式过于严格,并且与客户端证书的主题DN不匹配,那么领域不会验证该证书。
- 可选:如果您希望相同的用户在连接到 Kibana 时也使用证书进行身份验证,您必须配置 Elasticsearch PKI 领域以允许委托。请参阅 连接到 Kibana 的客户端的 PKI 身份验证。
- 重新启动 Elasticsearch,因为领域配置不会自动重新加载。如果您正在按照下一步操作,您可能希望最后再进行重新启动。
- 启用 SSL/TLS。
-
在所需的网络层(传输层或HTTP层)上启用客户端认证。
当客户端直接连接到 Elasticsearch 时使用 PKI,您必须启用带有客户端认证的 SSL/TLS。也就是说,您必须将
xpack.security.transport.ssl.client_authentication
和xpack.security.http.ssl.client_authentication
设置为optional
或required
。如果设置值为optional
,没有证书的客户端可以使用其他凭证进行认证。当客户端直接连接到 Elasticsearch 且未经过代理身份验证时,PKI 领域依赖于节点网络接口的 TLS 设置。该领域可以配置得比底层网络连接更为严格。也就是说,可以配置节点,使得某些连接被网络接口接受,但随后在 PKI 领域中身份验证失败。然而,反过来是不可能的。PKI 领域无法对已被网络接口拒绝的连接进行身份验证。
特别是这意味着:
-
传输或 http 接口必须通过将
client_authentication
设置为optional
或required
来请求客户端证书。 -
接口必须 信任 客户端提供的证书,通过配置
truststore
或certificate_authorities
路径,或者将verification_mode
设置为none
。 - 接口支持的 协议 必须与客户端使用的协议兼容。
有关这些设置的说明,请参阅通用 TLS 设置。
相关的网络接口(传输或http)必须配置为信任在PKI领域内使用的任何证书。然而,可以配置PKI领域仅信任网络接口接受的证书的子集。当SSL/TLS层信任由与签署用户证书不同的CA签署的客户端证书时,这是有用的。
要使用自己的信任库配置PKI领域,请指定
truststore.path
选项。路径必须位于Elasticsearch配置目录(ES_PATH_CONF
)内。例如:xpack: security: authc: realms: pki: pki1: order: 1 truststore: path: "pki1_truststore.jks"
如果信任库受密码保护,应通过向 Elasticsearch 密钥库添加适当的
secure_password
设置来配置密码。例如,以下命令为上述示例领域添加密码:bin/elasticsearch-keystore add \ xpack.security.authc.realms.pki.pki1.truststore.secure_password
可以使用
certificate_authorities
选项作为truststore.path
设置的替代方案,当证书文件为 PEM 格式时。该设置接受一个列表。这两个选项是互斥的,它们不能同时使用。 -
传输或 http 接口必须通过将
-
为PKI用户映射角色。
您通过角色映射 API或使用存储在每个节点上的文件为 PKI 用户映射角色。这两种配置选项会合并在一起。当用户针对 PKI 领域进行身份验证时,该用户的权限是用户所映射到的所有角色定义的权限的并集。
您通过用户证书中的专有名称来识别用户。 例如,以下映射配置使用角色映射 API 将
John Doe
映射到user
角色:PUT /_security/role_mapping/users { "roles" : [ "user" ], "rules" : { "field" : { "dn" : "cn=John Doe,ou=example,o=com" } }, "enabled": true }
或者,使用角色映射文件。例如:
文件的路径默认为
ES_PATH_CONF/role_mapping.yml
。您可以通过使用files.role_mapping
领域设置来指定不同的路径(该路径必须在ES_PATH_CONF
内)(例如xpack.security.authc.realms.pki.pki1.files.role_mapping
)。PKI用户的专有名称遵循X.500命名约定,将最具体的字段(如
cn
或uid
)放在名称的开头,将最一般的字段(如o
或dc
)放在名称的末尾。一些工具,如openssl,可能会以不同的格式打印出主题名称。确定证书正确DN的一种方法是使用authenticate API(使用相关的PKI证书作为身份验证手段)并检查结果中的元数据字段。用户的可分辨名称将在
pki_dn
键下填充。您还可以使用authenticate API来验证您的角色映射。有关更多信息,请参阅将用户和组映射到角色。
PKI 领域支持 授权领域 作为角色映射的替代方案。
连接到 Kibana 的客户端的 PKI 认证
edit默认情况下,PKI 领域依赖于节点的网络接口来执行 SSL/TLS 握手并提取客户端证书。此行为要求客户端直接连接到 Elasticsearch,以便其 SSL 连接由 Elasticsearch 节点终止。如果 SSL/TLS 身份验证将由 Kibana 执行,则必须配置 PKI 领域以允许委托。
具体来说,当客户端提供X.509证书连接到Kibana时,Kibana执行SSL/TLS认证。然后,Kibana通过调用Elasticsearch API将客户端的证书链转发,以便由已配置为委托的PKI领域进一步验证。
要为特定的 Elasticsearch PKI 领域启用身份验证委托,首先按照 PKI 身份验证用于直接连接到 Elasticsearch 的客户端 部分中的详细说明配置领域。在此场景中,当您启用 TLS 时,必须 加密 HTTP 客户端通信。
您还必须显式配置一个truststore
(或者等效地,certificate_authorities
),即使它与您在网络层配置的信任配置相同。xpack.security.authc.token.enabled
和 delegation.enabled
设置也必须为 true
。例如:
xpack: security: authc: token.enabled: true realms: pki: pki1: order: 1 delegation.enabled: true truststore: path: "pki1_truststore.jks"
在您重新启动 Elasticsearch 后,此领域可以验证委托的 PKI 身份验证。 然后您必须 配置 Kibana 以允许 PKI 证书身份验证。
一个启用了delegation.enabled
的PKI领域对于直接连接到Elasticsearch的客户端仍然可以正常工作。直接认证的用户和通过委派到Kibana进行PKI认证的用户都遵循相同的
角色映射规则或
授权领域配置。
然而,如果您使用角色映射API,您可以区分通过委托进行身份验证的用户和直接进行身份验证的用户。前者在用户元数据中具有额外的字段pki_delegated_by_user
和pki_delegated_by_realm
。在常见的设置中,身份验证被委托给Kibana,这些字段的值分别为kibana
和reserved
。例如,以下角色映射规则将role_for_pki1_direct
角色分配给所有通过pki1
领域直接进行身份验证的用户,方法是连接到Elasticsearch而不是通过Kibana:
SAML 认证
editElastic Stack 安全功能支持使用 SAML 单点登录 (SSO) 进行用户身份验证。安全功能通过 SAML 2.0 协议的 Web 浏览器 SSO 配置文件提供此支持。
此协议专为通过交互式网页浏览器进行身份验证而设计,因此它不作为标准身份验证领域运行。相反,Kibana 和 Elasticsearch 安全功能协同工作,以启用交互式 SAML 会话。
这意味着SAML领域不适合标准REST客户端使用。 如果您在Kibana中配置了SAML领域,您还应该配置另一个领域,例如在您的认证链中的本地领域。
为了简化在Elastic Stack中配置SAML认证的过程,这里有一份逐步指南,用于在Elastic Stack上配置SAML单点登录。
Kerberos 认证
edit您可以配置 Elastic Stack 安全功能以支持 Kerberos V5 身份验证,这是一种行业标准协议,用于在 Elasticsearch 中对用户进行身份验证。
您不能使用Kerberos领域在传输网络层进行身份验证。
要使用Kerberos验证用户,您需要配置一个Kerberos领域并将用户映射到角色。有关领域设置的更多信息,请参阅Kerberos领域设置。
关键概念
edit在设置Kerberos领域时,您会遇到一些术语和概念:
- kdc
- 密钥分发中心。一个发放Kerberos票据的服务。
- principal
-
Kerberos主体是一个唯一的身份,Kerberos可以为其分配票据。它可用于标识用户或服务器提供的服务。
Kerberos V5 主体名称的格式为
primary/instance@REALM
,其中primary
是用户名。instance
是一个可选的字符串,用于限定主标识符,并与主标识符之间用斜杠(/
)分隔。对于用户来说,通常不使用它;对于服务主机,它是主机的完全限定域名。REALM
是 Kerberos 领域。通常它是大写的域名。 一个典型的用户主体的例子是user@ES.DOMAIN.LOCAL
。一个典型的服务主体的例子是HTTP/es.domain.local@ES.DOMAIN.LOCAL
。 - realm
- 领域定义了认证服务器有权限进行用户和服务认证的管理边界。
- keytab
- 存储主体和加密密钥对的文件。
任何对该文件具有读取权限的人都可以使用网络中的凭证访问其他服务,因此使用适当的文件权限保护它非常重要。
- krb5.conf
- 包含Kerberos配置信息的文件,例如默认领域名称、密钥分发中心(KDC)的位置、领域信息、从域名到Kerberos领域的映射以及领域会话密钥加密类型的默认配置。
- ticket granting ticket (TGT)
- TGT是由Kerberos认证服务器生成的认证票据。它包含一个加密的认证器。
配置Kerberos领域
editKerberos 用于保护服务,并使用基于票据的身份验证协议来验证用户。 您可以配置 Elasticsearch 以使用 Kerberos V5 身份验证协议,这是一种行业标准协议,来验证用户。 在这种情况下,客户端必须提供 Kerberos 票据进行身份验证。
在Kerberos中,用户首先通过认证服务进行认证,然后通过票据授予服务生成TGT(票据授予票据)。此票据随后用于向服务进行认证。有关获取TGT的更多信息,请参阅您的Kerberos安装文档。Elasticsearch客户端必须首先获取TGT,然后启动与Elasticsearch的认证过程。
开始之前
edit-
部署 Kerberos。
您必须在您的环境中设置Kerberos基础设施。
Kerberos 需要许多外部服务才能正常运行,例如所有机器之间的时间同步以及域中的正向和反向 DNS 映射。有关更多详细信息,请参阅您的 Kerberos 文档。
这些说明不包括设置和配置您的Kerberos部署。提供的示例适用于MIT Kerberos V5部署。更多信息,请参阅MIT Kerberos文档
-
配置 Java GSS。
Elasticsearch 使用 Java GSS 框架支持 Kerberos 认证。 为了支持 Kerberos 认证,Elasticsearch 需要以下文件:
-
krb5.conf
, a Kerberos configuration file -
A
keytab
file that contains credentials for the Elasticsearch service principal
配置要求取决于您的Kerberos设置。请参阅您的Kerberos文档以配置
krb5.conf
文件。有关Java GSS的更多信息,请参阅 Java GSS Kerberos要求
-
-
为HTTP启用TLS。
如果您的 Elasticsearch 集群在生产模式下运行,您必须在启用 Kerberos 身份验证之前配置 HTTP 接口以使用 SSL/TLS。有关更多信息,请参阅 加密 Elasticsearch 的 HTTP 客户端通信。
此步骤是为了通过 Kibana 支持 Kerberos 认证所必需的。 对于直接针对 Elasticsearch Rest API 的 Kerberos 认证,这不是必需的。
-
启用令牌服务
Elasticsearch 的 Kerberos 实现使用了 Elasticsearch 令牌服务。如果在 HTTP 接口上配置了 TLS,此服务将自动启用。可以通过在
elasticsearch.yml
文件中添加以下设置来显式配置:xpack.security.authc.token.enabled: true
此步骤是为了通过 Kibana 支持 Kerberos 认证所必需的。 对于直接针对 Elasticsearch Rest API 的 Kerberos 认证,这不是必需的。
创建一个Kerberos领域
edit在 Elasticsearch 中配置 Kerberos 领域:
-
配置JVM以找到Kerberos配置文件。
Elasticsearch 使用 Java GSS 和 JAAS Krb5LoginModule 来支持使用简单和受保护的 GSSAPI 协商机制 (SPNEGO) 的 Kerberos 认证。 Kerberos 配置文件 (
krb5.conf
) 提供了诸如默认领域、密钥分发中心 (KDC) 和其他 Kerberos 认证所需配置细节的信息。当 JVM 需要一些配置属性时,它会尝试通过定位和加载此文件来找到这些值。配置文件路径的 JVM 系统属性是java.security.krb5.conf
。要配置 JVM 系统属性,请参阅 设置 JVM 选项。 如果未指定此系统属性,Java 将根据约定尝试定位该文件。建议为此系统属性配置Elasticsearch。 设置此属性的方法取决于您的Kerberos基础设施。 有关更多详细信息,请参阅您的Kerberos文档。
更多信息,请参阅 krb5.conf
-
为 Elasticsearch 节点创建一个 keytab。
keytab 是一个存储主体和加密密钥对的文件。Elasticsearch 使用 keytab 中的密钥来解密用户提供的票据。您必须使用 Kerberos 实现提供的工具为 Elasticsearch 创建一个 keytab。例如,一些创建 keytab 的工具有 Windows 上的
ktpass.exe
和 MIT Kerberos 的kadmin
。 -
将密钥表文件放在Elasticsearch配置目录中。
确保此密钥表文件具有读取权限。此文件包含凭据,因此您必须采取适当措施来保护它。
Elasticsearch 在 HTTP 网络层使用 Kerberos,因此必须在每个 Elasticsearch 节点上为 HTTP 服务主体提供一个 keytab 文件。服务主体名称必须具有格式
HTTP/es.domain.local@ES.DOMAIN.LOCAL
。由于它们包含主机名,keytab 文件对于每个节点都是唯一的。只要在配置的 keytab 中找到该主体及其凭据,Elasticsearch 节点就可以充当客户端请求的任何主体。 -
创建一个Kerberos领域。
要在 Elasticsearch 中启用 Kerberos 身份验证,您必须在领域链中添加一个 Kerberos 领域。
您只能在Elasticsearch节点上配置一个Kerberos领域。
要配置一个Kerberos领域,您需要在
elasticsearch.yml
配置文件中配置一些强制性的领域设置和其他可选设置。在xpack.security.authc.realms.kerberos
命名空间下添加一个领域配置。Kerberos 领域最常见的配置如下:
xpack.security.authc.realms.kerberos.kerb1: order: 3 keytab.path: es.keytab remove_realm_name: false
从用户提供的票据中提取的
用户名
通常具有用户名@REALM
的格式。这个用户名
用于将角色映射给用户。如果领域设置remove_realm_name
被设置为true
,则领域部分(@REALM
)将被移除。最终的用户名
用于角色映射。有关可用领域设置的详细信息,请参阅Kerberos realm settings。
- 重启 Elasticsearch
-
将Kerberos用户映射到角色。
The
kerberos
realm 允许您将 Kerberos 用户映射到角色。您可以通过使用 创建或更新角色映射 API 来配置这些角色映射。您可以通过其username
字段来识别用户。以下示例使用角色映射 API 将
user@REALM
映射到角色monitoring
和user
:POST /_security/role_mapping/kerbrolemapping { "roles" : [ "monitoring_user" ], "enabled": true, "rules" : { "field" : { "username" : "user@REALM" } } }
如果您想支持Kerberos跨领域认证,您可能需要根据Kerberos领域名称映射角色。对于此类场景,以下是可用于角色映射的额外用户元数据: -
kerberos_realm
将被设置为Kerberos领域名称。 -kerberos_user_principal_name
将被设置为用户主体名称,来自Kerberos票据。有关更多信息,请参阅将用户和组映射到角色。
Kerberos 领域支持 授权领域作为角色映射的替代方案。
为 Kerberos 配置 Kibana
edit如果您想通过浏览器和 Kibana 使用 Kerberos 进行身份验证,您需要在 Kibana 配置中启用相关的身份验证提供程序。请参阅 kerberos 单点登录
JWT 认证
editElasticsearch 可以配置为信任从外部服务颁发的 JSON Web Tokens (JWTs) 作为身份验证的承载令牌。
当使用 JWT realm 进行 Elasticsearch 身份验证时,会区分连接到 Elasticsearch 的 客户端 和代表其运行请求的 用户。JWT 用于验证用户,而单独的凭证用于验证客户端。
JWT realm 支持两种令牌类型,id_token
(默认)和 access_token
。
它们分别设计用于以下两种场景:
-
id_token
- 应用程序通过身份验证流程(例如 OpenID Connect (OIDC))对用户进行身份验证和识别,然后使用符合 OIDC ID Token 规范的 JSON Web Token (JWT) 代表已验证的用户访问 Elasticsearch。 -
access_token
- 应用程序使用其自身的身份(编码为 JWT)访问 Elasticsearch,例如,应用程序通过 OAuth2 客户端凭据流向中央身份平台进行身份验证,然后使用生成的基于 JWT 的访问令牌连接到 Elasticsearch。
一个单独的JWT领域只能与一种令牌类型一起工作。要处理两种令牌类型,您必须配置至少两个JWT领域。您应根据使用情况仔细选择令牌类型,因为它会影响验证的执行方式。
JWT realm 根据其配置的令牌类型验证传入的 JWT。 JSON Web Tokens (JWT) 的两种类型都必须包含以下 5 条信息。 虽然基于 OIDC 规范的 ID 令牌对应该提供这些信息的声明有严格的规定, 但访问令牌允许一些声明是可配置的。
声明 |
||
信息 |
ID Token |
访问令牌 |
发行者 |
|
|
主题 |
|
默认为 |
受众 |
|
默认为 |
发布时间 |
|
|
过期时间 |
|
|
此外,如果存在这些声明,Elasticsearch 还会验证 ID 令牌的 nbf
和 auth_time
声明。
但对于访问令牌,这些声明会被忽略。
总的来说,访问令牌类型的验证规则更为宽松,适用于更通用的JWT,包括自签名的JWT。
来自OIDC工作流的ID令牌
editElasticsearch中的JWT认证源自OIDC用户工作流程,其中不同的令牌可以由OIDC提供者(OP)颁发,包括ID令牌。
OIDC提供者颁发的ID令牌是定义良好的JSON Web令牌(JWT),并且应始终与id_token
令牌类型的JWT领域兼容。ID令牌的主题声明表示最终用户。
这意味着ID令牌通常会有许多允许的主题。
因此,id_token
令牌类型的JWT领域不强制执行allowed_subjects
(或allowed_subject_patterns
)验证。
因为JWT是在Elasticsearch外部获取的,您可以定义一个自定义工作流程,而不是使用OIDC工作流程。然而,JWT格式仍然必须是JSON Web Signature (JWS)。JWS头部和JWS签名使用OIDC ID令牌验证规则进行验证。
Elasticsearch 支持一个独立的 OpenID Connect realm。对于 Elasticsearch 可以作为 OIDC RP 的任何用例,这是首选。OIDC realm 是唯一支持在 Kibana 中启用 OIDC 认证的方式。
使用JWT领域进行身份验证的用户可以选择使用run_as
功能来模拟另一个用户。另请参阅将run_as
权限应用于JWT领域用户。
访问令牌
edit获取访问令牌的常见方法是使用OAuth2客户端凭证流。
这种流的典型用法是应用程序为自己获取凭证。
这是access_token
令牌类型设计的使用场景。
这个应用程序可能还会为其最终用户获取ID令牌。
为了防止最终用户的ID令牌被用于与为应用程序配置的JWT领域进行身份验证,当JWT领域的令牌类型为access_token
时,我们强制执行allowed_subjects
或allowed_subject_patterns
验证。
并非每个访问令牌都格式化为JSON Web Token(JWT)。 为了使其与JWT领域兼容,它至少必须使用JWT格式并满足上表中的相关要求。
配置 Elasticsearch 以使用 JWT 领域
edit要使用JWT认证,请在elasticsearch.yml
文件中创建领域,以在Elasticsearch认证链中进行配置。
JWT realm 有几项必填设置,以及在 JWT realm 设置中描述的可选设置。
JWT realms默认启用了客户端认证。虽然可以禁用客户端认证,但强烈不建议这样做。
-
将您的JWT领域添加到
elasticsearch.yml
文件中。以下示例包括最常见的设置,这些设置并不适用于所有用例:xpack.security.authc.realms.jwt.jwt1: order: 3 token_type: id_token client_authentication.type: shared_secret allowed_issuer: "https://issuer.example.com/jwt/" allowed_audiences: [ "8fb85eba-979c-496c-8ae2-a57fde3f12d0" ] allowed_signature_algorithms: [RS256,HS256] pkc_jwkset_path: jwt/jwkset.json claims.principal: sub
-
order
-
指定领域的
order
为3
,表示在验证用户时配置的领域被检查的顺序。领域按照升序被咨询,其中具有最低顺序值的领域首先被咨询。 -
token_type
-
指示领域将传入的JWT视为并验证为ID令牌(
id_token
)。 -
client_authentication.type
-
指定客户端认证类型为
shared_secret
,这意味着客户端使用必须匹配预配置的秘密值的HTTP请求头进行认证。客户端必须在每个请求中提供这个共享秘密,使用ES-Client-Authentication
头和SharedSecret
方案。头值必须与领域的client_authentication.shared_secret
完全匹配。 -
allowed_issuer
- 为您的JWT颁发者设置一个可验证的标识符。此值通常是一个URL、UUID或其他区分大小写的字符串值。
-
allowed_audiences
- 指定领域将允许的JWT受众列表。这些值通常是URL、UUID或其他区分大小写的字符串值。
-
allowed_signature_algorithms
-
指示Elasticsearch应使用
RS256
或HS256
签名算法来验证来自JWT颁发者的JWT签名。 -
pkc_jwkset_path
-
文件名或URL到一个JSON Web Key Set (JWKS),包含JWT领域用于验证令牌签名的公钥材料。如果值不以
https
开头,则被视为文件名。文件名相对于Elasticsearch配置目录解析。如果提供了URL,则必须以https://
开头(不支持http://
)。Elasticsearch自动缓存JWK集,并在签名验证失败时尝试刷新JWK集,因为这可能表明JWT提供者已轮换签名密钥。 -
claims.principal
- 包含用户主体(用户名)的JWT声明的名称。
以下是配置用于处理访问令牌的JWT领域的示例代码片段:
xpack.security.authc.realms.jwt.jwt2: order: 4 token_type: access_token client_authentication.type: shared_secret allowed_issuer: "https://issuer.example.com/jwt/" allowed_subjects: [ "123456-compute@admin.example.com" ] allowed_subject_patterns: [ "wild*@developer?.example.com", "/[a-z]+<1-10>\\@dev\\.example\\.com/"] allowed_audiences: [ "elasticsearch" ] required_claims: token_use: access version: ["1.0", "2.0"] allowed_signature_algorithms: [RS256,HS256] pkc_jwkset_path: "https://idp-42.example.com/.well-known/configuration" fallback_claims.sub: client_id fallback_claims.aud: scope claims.principal: sub
-
token_type
-
指示领域将传入的JWT视为并验证为访问令牌(
access_token
)。 -
allowed_subjects
- 指定领域将允许的JWT主体列表。这些值通常是URL、UUID或其他区分大小写的字符串值。
-
allowed_subject_patterns
-
类似于
allowed_subjects
,但它接受一个Lucene正则表达式和通配符列表,用于允许的JWT主体。通配符使用*
和?
特殊字符(由\
转义)分别表示“任何字符串”和“任何单个字符”,例如“a?\**”匹配“a1*”和“ab*whatever”,但不匹配“a”、“abc”或“abc*”(在Java字符串中,\
本身必须由另一个\
转义)。Lucene正则表达式必须用/
包围,例如“/https?://[^/]+/?/”匹配任何没有路径组件的http或https URL(匹配“https://elastic.co/”但不匹配“https://elastic.co/guide”)。
当
token_type
为access_token
时,必须指定至少一个allowed_subjects
或allowed_subject_patterns
设置(且不能为空)。当同时指定了
allowed_subjects
和allowed_subject_patterns
设置时,传入的JWT的sub
声明如果匹配其中任何一个列表,则会被接受。-
required_claims
- 指定一个键/值对列表,用于对JWT进行额外的验证。值可以是字符串或字符串数组。
-
fallback_claims.sub
-
如果
sub
声明不存在,提取主体信息的JWT声明的名称。此设置仅在token_type
为access_token
时可用。回退适用于sub
声明使用的任何地方。在上面的代码片段中,这意味着如果sub
不存在,claims.principal
也将回退到client_id
。 -
fallback_claims.aud
-
如果
aud
声明不存在,提取受众信息的JWT声明的名称。此设置仅在token_type
为access_token
时可用。回退适用于aud
声明使用的任何地方。
-
-
定义设置后,使用
elasticsearch-keystore
工具在 Elasticsearch 密钥库中存储安全设置的值。-
存储
shared_secret
值用于client_authentication.type
:bin/elasticsearch-keystore add xpack.security.authc.realms.jwt.jwt1.client_authentication.shared_secret
-
存储用于
allowed_signature_algorithms
的 HMAC 密钥,该算法在示例中使用 HMAC SHA-256 算法HS256
:建议使用JWKS。然而,您可以使用以下命令添加一个字符串格式的HMAC密钥。此格式与HMAC UTF-8密钥兼容,但仅支持没有属性的单个密钥。您只能同时使用一种HMAC格式(
hmac_jwkset
或hmac_key
)。bin/elasticsearch-keystore add xpack.security.authc.realms.jwt.jwt1.hmac_key
-
JWT 编码和验证
editJWT 可以解析为三个部分:
- Header
- 提供有关如何验证令牌的信息。
- Claims
- 包含有关调用用户或应用程序的数据。
- Signature
- 用于验证令牌的数据。
Header: {"typ":"JWT","alg":"HS256"} Claims: {"aud":"aud8","sub":"security_test_user","iss":"iss8","exp":4070908800,"iat":946684800} Signature: UnnFmsoFKfNmKMsVoDQmKI_3-j95PCaKdgqqau3jPMY
此示例演示了JWT的部分解码。有效期从2000年到2099年(包括2000年和2099年),由签发时间(iat
)和过期时间(exp
)定义。JWT通常具有短于100年的有效期,例如1-2小时或1-7天,而不是整个人生的时间。
此示例中的签名是确定性的,因为头部、声明和HMAC密钥是固定的。JWT通常有一个nonce
声明,以使签名非确定性。支持的JWT编码是JSON Web Signature (JWS),并且使用OpenID Connect ID Token验证规则验证JWS Header
和Signature
。一些验证可以通过JWT realm settings进行自定义。
头部声明
edit头部声明指示了令牌类型和用于签名令牌的算法。
-
alg
-
(必需, 字符串) 指示用于签名令牌的算法,例如
HS256
。该算法必须在领域允许列表中。 -
typ
-
(可选, 字符串) 指示令牌类型, 必须为
JWT
.
载荷声明
edit令牌包含几个声明,这些声明提供了有关发出令牌的用户的信息,以及令牌本身的信息。 根据令牌类型的不同,这些信息可以通过不同的声明选择性地识别。
JWT 载荷声明
edit以下声明由OIDC ID令牌规则的子集验证。
Elasticsearch 不会验证 nonce
声明,但自定义 JWT 发行者可以添加一个随机的 nonce
声明以在签名中引入熵。
您可以通过设置allowed_clock_skew
来放宽对任何基于时间的声明的验证。此值设置了在验证JWT相对于其认证时间(auth_time
)、创建时间(iat
)、生效时间(nbf
)和过期时间(exp
)之前的最大允许时钟偏差。
-
iss
-
(必需,字符串) 表示创建ID令牌的发行者。该值必须与
allowed_issuer
设置中的值完全一致,区分大小写。 -
sub
-
(必填*, 字符串) 表示创建ID令牌的主题。
如果JWT领域是
id_token
类型,此声明是强制性的。id_token
类型的JWT领域默认接受所有主题。 access_token类型的JWT领域必须指定allowed_subjects
设置,并且主题值 必须与allowed_subjects设置中的任何CSV值完全匹配,区分大小写。 access_token类型的JWT领域可以指定一个回退声明,该声明将在sub
声明不存在的地方使用。 -
aud
-
(必填*, 字符串) 表示ID令牌的目标受众,以逗号分隔值(CSV)表示。其中一个值必须与
allowed_audiences
设置中的任何CSV值完全一致,区分大小写。如果JWT领域是id_token
类型,则此声明是强制性的。access_token
类型的JWT领域可以指定一个备用声明,该声明将在aud
声明不存在的地方使用。 -
exp
- (必需,整数) ID 令牌的过期时间,表示为自纪元以来的 UTC 秒数。
-
iat
- (必需,整数) ID 令牌的签发时间,表示为自纪元以来的 UTC 秒数。
-
nbf
-
(可选, 整数) 表示在此时间之前不得接受JWT,以UTC秒为单位表示自纪元以来的时间。
此声明是可选的。如果存在,类型为
id_token
的JWT领域将验证它,而类型为access_token
的JWT领域将忽略它。 -
auth_time
-
(可选, 整数) 用户向JWT发行者进行身份验证的时间,
以自纪元以来的UTC秒数表示。
此声明是可选的。如果存在,
id_token
类型的JWT领域将验证它, 而access_token
类型的JWT领域将忽略它。
用于消费JWT声明的Elasticsearch设置
editElasticsearch 使用 JWT 声明进行以下设置。
-
principal
-
(必需,字符串) 包含用户的身份(用户名)。该值可以通过领域设置
claims.principal
进行配置。您可以使用claim_patterns.principal
配置一个可选的正则表达式来提取子字符串。 -
groups
-
(可选, JSON 数组) 包含用户的组成员身份。
该值可以通过领域设置
claims.groups
进行配置。您可以使用领域设置claim_patterns.groups
配置一个可选的正则表达式来提取子字符串值。 -
name
-
(可选, 字符串) 包含一个可读的标识符, 用于标识令牌的主题。该值可以通过领域设置
claims.name
进行配置。您可以使用领域设置claim_patterns.name
配置一个可选的正则表达式来提取子字符串值。 -
mail
-
(可选, 字符串) 包含与用户关联的电子邮件地址。该值可以通过领域设置
claims.mail
进行配置。您可以使用领域设置claim_patterns.mail
配置一个可选的正则表达式来提取子字符串值。 -
dn
-
(可选, 字符串) 包含用户的唯一标识名 (DN),用于唯一标识用户或组。该值可以通过领域设置
claims.dn
进行配置。您可以使用领域设置claim_patterns.dn
配置一个可选的正则表达式来提取子字符串值。
JWT 领域授权
editJWT 领域支持通过创建或更新角色映射 API 进行授权,或将授权委托给另一个领域。您不能同时使用这些方法,因此请选择最适合您环境的方法。
您不能使用 role_mapping.yml
文件在 JWT 领域中映射角色。
使用角色映射 API 进行授权
edit您可以使用 创建或更新角色映射 API 来定义 角色映射,这些映射决定了应根据用户的用户名、组或其他元数据将哪些角色分配给每个用户。
PUT /_security/role_mapping/jwt1_users?refresh=true { "roles" : [ "user" ], "rules" : { "all" : [ { "field": { "realm.name": "jwt1" } }, { "field": { "username": "principalname1" } }, { "field": { "dn": "CN=Principal Name 1,DC=example.com" } }, { "field": { "groups": "group1" } }, { "field": { "metadata.jwt_claim_other": "other1" } } ] }, "enabled": true }
如果您在JWT领域中使用此API,则以下声明可用于角色映射:
-
principal
- (必需,字符串) 用作 Elasticsearch 用户用户名的主要声明。
-
dn
- (可选, 字符串) 用作 Elasticsearch 用户 DN 的专有名称 (DN)。
-
groups
- (可选, 字符串) 逗号分隔值 (CSV) 列表,用作 Elasticsearch 用户的用户组列表。
-
metadata
-
(可选, 对象) 关于用户的额外元数据, 例如字符串、整数、布尔值和集合, 这些元数据用作Elasticsearch用户的元数据。这些值是以键值对的形式格式化的, 例如
metadata.jwt_claim_
=
。
将JWT授权委托给另一个领域
edit如果你从JWT领域委托授权给其他领域,只有principal
声明可用于角色查找。当从JWT领域委托角色分配和查找给另一个领域时,dn
、groups
、mail
、metadata
和name
的声明不会用于Elasticsearch用户的值。只有JWT的principal
声明会被传递给委托的授权领域。负责授权的领域(不是JWT领域)将负责填充Elasticsearch用户的所有值。
以下示例展示了如何在 elasticsearch.yml
文件中定义从 JWT 领域向多个其他领域进行委托授权。一个名为 jwt2
的 JWT 领域正在向多个领域进行授权委托:
xpack.security.authc.realms.jwt.jwt2.authorization_realms: file1,native1,ldap1,ad1
然后,您可以使用创建或更新角色映射 API将角色映射到授权领域。以下示例将native1
领域中的角色映射到principalname1
JWT 主体。
PUT /_security/role_mapping/native1_users?refresh=true { "roles" : [ "user" ], "rules" : { "all" : [ { "field": { "realm.name": "native1" } }, { "field": { "username": "principalname1" } } ] }, "enabled": true }
如果领域 jwt2
成功地使用JWT为委托人 principalname1
验证了一个客户端,并将授权委托给列出的领域之一(例如 native1
),那么该领域可以查找Elasticsearch用户的值。通过这个定义的角色映射,该领域还可以查找与领域 native1
链接的此角色映射规则。
将 run_as
权限应用于 JWT 领域用户
editElasticsearch 可以通过角色映射或委托授权来检索 JWT 用户的角色。无论您选择哪种选项,您都可以将 run_as
权限应用于角色,以便用户可以提交经过身份验证的请求以“作为”其他用户运行。要提交作为其他用户的请求,请在您的请求中包含 es-security-runas-user
头。请求将以该用户的身份运行,Elasticsearch 将使用他们的角色。
例如,假设有一个用户名为 user123_runas
的用户。
以下请求创建了一个名为 jwt_role1
的用户角色,该角色指定了一个用户名为 user123_runas
的 run_as
用户。任何拥有 jwt_role1
角色的用户都可以以指定的 run_as
用户身份发出请求。
POST /_security/role/jwt_role1?refresh=true { "cluster": ["manage"], "indices": [ { "names": [ "*" ], "privileges": ["read"] } ], "run_as": [ "user123_runas" ], "metadata" : { "version" : 1 } }
然后,您可以将该角色映射到特定领域中的用户。以下请求将jwt_role1
角色映射到jwt2
JWT领域中用户名为user2
的用户。这意味着Elasticsearch将使用jwt2
领域来验证名为user2
的用户。由于user2
拥有包含run_as
权限的角色(即jwt_role1
角色),Elasticsearch会检索user123_runas
用户的角色映射,并使用该用户的角色来提交请求。
POST /_security/role_mapping/jwt_user1?refresh=true { "roles": [ "jwt_role1"], "rules" : { "all" : [ { "field": { "realm.name": "jwt2" } }, { "field": { "username": "user2" } } ] }, "enabled": true, "metadata" : { "version" : 1 } }
映射角色后,您可以使用 JWT 进行
身份验证调用 到 Elasticsearch 并包含
ES-Client-Authentication
头:
curl -s -X GET -H "Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJhdWQiOlsiZXMwMSIsImVzMDIiLCJlczAzIl0sInN1YiI6InVzZXIyIiwiaXNzIjoibXktaXNzdWVyIiwiZXhwIjo0MDcwOTA4ODAwLCJpYXQiOjk0NjY4NDgwMCwiZW1haWwiOiJ1c2VyMkBzb21ldGhpbmcuZXhhbXBsZS5jb20ifQ.UgO_9w--EoRyUKcWM5xh9SimTfMzl1aVu6ZBsRWhxQA" -H "ES-Client-Authentication: sharedsecret test-secret" https://localhost:9200/_security/_authenticate
响应包括提交请求的用户(user2
),包括在JWT领域中映射到该用户的jwt_role1
角色:
{"username":"user2","roles":["jwt_role1"],"full_name":null,"email":"user2@something.example.com", "metadata":{"jwt_claim_email":"user2@something.example.com","jwt_claim_aud":["es01","es02","es03"], "jwt_claim_sub":"user2","jwt_claim_iss":"my-issuer"},"enabled":true,"authentication_realm": {"name":"jwt2","type":"jwt"},"lookup_realm":{"name":"jwt2","type":"jwt"},"authentication_type":"realm"} %
如果您想将请求指定为run_as
用户,请包含es-security-runas-user
头,并使用您希望提交请求的用户的名称。以下请求使用user123_runas
用户:
curl -s -X GET -H "Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJhdWQiOlsiZXMwMSIsImVzMDIiLCJlczAzIl0sInN1YiI6InVzZXIyIiwiaXNzIjoibXktaXNzdWVyIiwiZXhwIjo0MDcwOTA4ODAwLCJpYXQiOjk0NjY4NDgwMCwiZW1haWwiOiJ1c2VyMkBzb21ldGhpbmcuZXhhbXBsZS5jb20ifQ.UgO_9w--EoRyUKcWM5xh9SimTfMzl1aVu6ZBsRWhxQA" -H "ES-Client-Authentication: sharedsecret test-secret" -H "es-security-runas-user: user123_runas" https://localhost:9200/_security/_authenticate
在响应中,您会看到user123_runas
用户提交了请求,并且Elasticsearch使用了jwt_role1
角色:
{"username":"user123_runas","roles":["jwt_role1"],"full_name":null,"email":null,"metadata":{}, "enabled":true,"authentication_realm":{"name":"jwt2","type":"jwt"},"lookup_realm":{"name":"native", "type":"native"},"authentication_type":"realm"}%
PKC JWKS 重新加载
editJWT 认证支持使用 PKC(公钥加密)或 HMAC 算法进行签名验证。
PKC JSON Web Token 密钥集 (JWKS) 可以包含公钥 RSA 和 EC 密钥。HMAC JWKS 或 HMAC UTF-8 JWK 包含密钥。JWT 发行者通常会更频繁地轮换 PKC JWKS(例如每天),因为 RSA 和 EC 公钥的设计使得它们比 HMAC 这样的密钥更容易分发。
JWT realms 在启动时加载一个 PKC JWKS 和一个 HMAC JWKS 或 HMAC UTF-8 JWK。JWT realms 还可以在运行时重新加载 PKC JWKS 内容;重新加载由签名验证失败触发。
目前不支持HMAC JWKS或HMAC UTF-8 JWK重新加载。
加载失败、解析错误和配置错误会阻止节点启动(和重新启动)。然而,运行时PKC重新加载错误和恢复会得到妥善处理。
所有其他JWT领域验证在签名失败触发PKC JWKS重新加载之前都会被检查。如果多个JWT身份验证签名失败同时发生在一个Elasticsearch节点上,重新加载会被合并以减少外部发送的重新加载次数。
如果JWT签名失败触发,则无法合并单独的重载请求:
- 不同Elasticsearch节点中的PKC JWKS重新加载
- 同一Elasticsearch节点中不同时间点的PKC JWKS重新加载
强烈建议启用客户端认证(client_authentication.type
)。只有受信任的客户端应用程序和特定领域的JWT用户可以触发PKC重新加载尝试。此外,建议配置以下JWT安全设置:
-
allowed_audiences
-
allowed_clock_skew
-
allowed_issuer
-
allowed_signature_algorithms
使用HMAC UTF-8密钥授权到JWT领域
edit以下设置适用于JWT发行者、Elasticsearch以及Elasticsearch的客户端。示例HMAC密钥采用与HMAC兼容的OIDC格式。密钥字节是UNICODE字符的UTF-8编码。
HMAC UTF-8 密钥需要比 HMAC 随机字节密钥更长,以达到相同的密钥强度。
JWT 发行者
edit以下值适用于定制的 JWT 发行者。
Issuer: iss8 Audiences: aud8 Algorithms: HS256 HMAC UTF-8: hmac-oidc-key-string-for-hs256-algorithm
JWT 领域设置
edit要定义一个JWT领域,请将以下领域设置添加到elasticsearch.yml
中。
xpack.security.authc.realms.jwt.jwt8.order: 8 xpack.security.authc.realms.jwt.jwt8.allowed_issuer: iss8 xpack.security.authc.realms.jwt.jwt8.allowed_audiences: [aud8] xpack.security.authc.realms.jwt.jwt8.allowed_signature_algorithms: [HS256] xpack.security.authc.realms.jwt.jwt8.claims.principal: sub xpack.security.authc.realms.jwt.jwt8.client_authentication.type: shared_secret
JWT 领域安全设置
edit在定义了领域设置后,使用
elasticsearch-keystore
工具将以下安全设置添加到 Elasticsearch 密钥库中。在 Elastic Cloud 中,您可以在部署中的 安全 下为 Elasticsearch 密钥库定义设置。
xpack.security.authc.realms.jwt.jwt8.hmac_key: hmac-oidc-key-string-for-hs256-algorithm xpack.security.authc.realms.jwt.jwt8.client_authentication.shared_secret: client-shared-secret-string
JWT领域角色映射规则
edit以下请求为Elasticsearch在jwt8
领域中为用户principalname1
创建角色映射:
PUT /_security/role_mapping/jwt8_users?refresh=true { "roles" : [ "user" ], "rules" : { "all" : [ { "field": { "realm.name": "jwt8" } }, { "field": { "username": "principalname1" } } ] }, "enabled": true }
请求头
edit以下头设置适用于Elasticsearch客户端。
Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJpc3M4IiwiYXVkIjoiYXVkOCIsInN1YiI6InNlY3VyaXR5X3Rlc3RfdXNlciIsImV4cCI6NDA3MDkwODgwMCwiaWF0Ijo5NDY2ODQ4MDB9.UnnFmsoFKfNmKMsVoDQmKI_3-j95PCaKdgqqau3jPMY ES-Client-Authentication: SharedSecret client-shared-secret-string
您可以在 curl
请求中使用此标头来对 Elasticsearch 进行身份验证调用。承载令牌和客户端授权令牌都必须使用 -H
选项分别指定为单独的标头:
curl -s -X GET -H "Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJpc3M4IiwiYXVkIjoiYXVkOCIsInN1YiI6InNlY3VyaXR5X3Rlc3RfdXNlciIsImV4cCI6NDA3MDkwODgwMCwiaWF0Ijo5NDY2ODQ4MDB9.UnnFmsoFKfNmKMsVoDQmKI_3-j95PCaKdgqqau3jPMY" -H "ES-Client-Authentication: SharedSecret client-shared-secret-string" https://localhost:9200/_security/_authenticate
如果在JWT领域中使用了角色映射,响应将包括用户的用户名
、他们的角色
、关于用户的信息以及关于JWT领域本身的详细信息。
{"username":"user2","roles":["jwt_role1"],"full_name":null,"email":"user2@something.example.com", "metadata":{"jwt_claim_email":"user2@something.example.com","jwt_claim_aud":["es01","es02","es03"], "jwt_claim_sub":"user2","jwt_claim_iss":"my-issuer"},"enabled":true,"authentication_realm": {"name":"jwt2","type":"jwt"},"lookup_realm":{"name":"jwt2","type":"jwt"},"authentication_type":"realm"}
与其他认证系统集成
edit如果您使用的是Elasticsearch安全功能不支持的开箱即用的身份验证系统,您可以创建一个自定义领域来与之交互以验证用户。您可以将自定义领域实现为作为普通elasticsearch插件一部分的SPI加载的安全扩展。
实现自定义领域
edit提供了一个示例代码,展示了自定义领域的结构和实现,详见 https://github.com/elastic/elasticsearch/tree/master/x-pack/qa/security-example-spi-extension。您可以使用此代码作为创建自己的领域的起点。
要创建自定义领域,您需要:
-
扩展
org.elasticsearch.xpack.security.authc.Realm
以与您的身份验证系统通信,以验证用户。 -
在用于创建自定义领域的类中实现
org.elasticsearch.xpack.security.authc.Realm.Factory
接口。 -
扩展
org.elasticsearch.xpack.security.authc.DefaultAuthenticationFailureHandler
以在使用自定义领域时处理身份验证失败。
将您的自定义领域打包为插件:
-
为您的领域实现一个扩展类,该类扩展了
org.elasticsearch.xpack.core.security.SecurityExtension
。在那里,您需要重写以下方法中的一个或多个:@Override public Map
getRealms() { ... } The
getRealms
方法用于提供一个从类型名称到Factory
的映射,该工厂将用于创建领域。@Override public AuthenticationFailureHandler getAuthenticationFailureHandler() { ... }
方法
getAuthenticationFailureHandler
用于可选地提供一个自定义的AuthenticationFailureHandler
,它将控制Elasticsearch安全特性在某些身份验证失败事件中的响应方式。@Override public List
getSettingsFilter() { ... } 方法
Plugin#getSettingsFilter
返回一组设置名称,这些名称应从设置API中过滤掉,因为它们可能包含敏感的凭证。请注意,此方法不是SecurityExtension
接口的一部分,它作为elasticsearch插件主类的一部分可用。 - 创建插件的构建配置文件;我们推荐使用Gradle。
-
为扩展创建一个
META-INF/services/org.elasticsearch.xpack.core.security.SecurityExtension
描述符文件,其中包含您的org.elasticsearch.xpack.core.security.SecurityExtension
实现的全限定类名。 - 将所有内容打包到一个zip文件中。
使用自定义领域进行用户认证
edit要使用自定义领域:
-
在集群中的每个节点上安装领域扩展。您运行
bin/elasticsearch-plugin
并使用install
子命令,并指定指向包含扩展的zip文件的URL。例如:bin/elasticsearch-plugin install file:///
/my-realm-1.0.zip -
在
xpack.security.authc.realms
命名空间下,向elasticsearch.yml
添加适当类型的领域配置。 您必须在匹配扩展定义的类型的命名空间内定义您的领域。 您可以设置的选项取决于自定义领域暴露的设置。 至少,您必须显式设置order
属性以控制领域在身份验证期间被咨询的顺序。 您还必须确保每个配置的领域具有不同的order
设置。 如果两个或多个领域具有相同的order
,节点将无法启动。当您在
elasticsearch.yml
中配置领域时,仅使用您指定的领域进行身份验证。如果您还想使用native
或file
领域,则必须将它们包含在领域链中。 - 重启 Elasticsearch。
启用匿名访问
edit要嵌入 Kibana 仪表板或授予对 Kibana 的访问权限而不需要凭据,请使用 Kibana 的 匿名身份验证功能。
如果无法从传入请求中提取身份验证令牌,则认为传入请求是匿名的。默认情况下,匿名请求会被拒绝,并返回身份验证错误(状态码401
)。
要启用匿名访问,您可以在elasticsearch.yml
配置文件中为匿名用户分配一个或多个角色。例如,以下配置为匿名用户分配了role1
和role2
:
查找用户无需身份验证
editElasticsearch 领域 主要用于支持
用户认证。
一些领域使用密码认证用户(例如 native
和 ldap
领域),而其他领域使用
更复杂的认证协议(例如 saml
和
oidc
领域)。
在每种情况下,领域的主要目的是确定
向 Elasticsearch API 发出请求的用户的身份。
然而,某些 Elasticsearch 功能需要查找用户而不使用其凭据。
在每种情况下,用户必须首先在一个领域进行身份验证,然后Elasticsearch将查询第二个领域以找到另一个用户。 已验证的用户凭据仅用于在第一个领域进行身份验证, 第二个领域中的用户通过用户名检索,无需凭据。
当 Elasticsearch 使用用户的凭证(如在第一个领域中执行的操作)解析用户时,这被称为用户认证。
当 Elasticsearch 仅使用用户名解析用户时(如在第二个领域中执行的操作),这被称为用户查找。
请参阅run_as和委托授权
文档以了解更多关于这些功能的信息,包括哪些领域和认证方法支持run_as
或委托授权。
在这两种情况下,只有以下领域可以用于用户查找:
The pki
, saml
, oidc
, kerberos
和 jwt
领域不支持用户查找。
如果您只想使用某个领域进行用户查找并阻止用户针对该领域进行身份验证,您可以配置该领域并将authentication.enabled
设置为false
用户查找功能是一种内部功能,用于实现run-as
和委托授权功能 - 没有用于用户查找的API。
如果您希望测试您的用户查找配置,那么您可以使用run_as
来完成。使用Authenticate API,以superuser
(例如内置的elastic
用户)身份进行身份验证,并指定es-security-runas-user
请求头。
The Get users API 和 User profiles 功能是检索有关 Elastic Stack 用户信息的替代方法。这些 API 与用户查找功能无关。
控制用户缓存
edit用户凭证在每个节点上缓存在内存中,以避免每次传入请求时连接到远程认证服务或访问磁盘。您可以使用cache.ttl
、cache.max_users
和cache.hash_algo
领域设置来配置用户缓存的特性。
JWT realms 使用 jwt.cache.ttl
和 jwt.cache.size
realm 设置。
PKI 和 JWT 领域不会缓存用户凭证,但会缓存解析后的用户对象,以避免在每次请求时都进行不必要的角色映射。
缓存的用户凭证在内存中是经过哈希处理的。默认情况下,Elasticsearch 安全功能使用加盐的 sha-256
哈希算法。您可以通过设置 cache.hash_algo
领域设置来使用不同的哈希算法。请参阅 用户缓存和密码哈希算法。
从缓存中驱逐用户
edit您可以使用清除缓存 API来强制清除缓存的用户的缓存。例如,以下请求将从ad1
领域中清除所有用户:
$ curl -XPOST 'http://localhost:9200/_security/realm/ad1/_clear_cache'
要清除多个领域的缓存,请将领域指定为逗号分隔的列表:
$ curl -XPOST 'http://localhost:9200/_security/realm/ad1,ad2/_clear_cache'
您也可以驱逐特定用户:
$ curl -XPOST 'http://localhost:9200/_security/realm/ad1/_clear_cache?usernames=rdeniro,alpacino'
在 Elastic Stack 上配置 SAML 单点登录
editElastic Stack 支持使用 Elasticsearch 作为后端服务,通过 SAML 单点登录(SSO)进入 Kibana。在 SAML 术语中,Elastic Stack 作为服务提供商运行。
启用SAML单点登录所需的另一个组件是身份提供者,它是一个处理您的凭证并执行用户实际身份验证的服务。
如果您有兴趣将单点登录(SSO)配置到 Kibana 中,那么您需要向 Elasticsearch 提供有关您的 身份提供者 的信息,并且您需要将 Elastic Stack 注册为该身份提供者中的已知 服务提供者。此外,还需要在 Kibana 中进行一些配置更改以激活 SAML 身份验证提供者。
Kibana 中的 SAML 支持是基于这样的预期设计的:它将成为该 Kibana 实例用户的主要(或唯一)认证方法。一旦您在 Kibana 中启用了 SAML 认证,它将影响所有尝试登录的用户。配置 Kibana 部分提供了更多关于其工作原理的详细信息。
身份提供者
editElastic Stack 支持 SAML 2.0 的 Web Browser SSO 和 SAML 2.0 的 Single Logout 配置文件,并且可以与任何支持至少 SAML 2.0 Web Browser SSO Profile 的身份提供者 (IdP) 集成。 它已经与多个流行的 IdP 实现进行了测试,例如 Microsoft Active Directory Federation Services (ADFS), Azure Active Directory (AAD), 以及 Okta。
本指南假设您已有一个现有的身份提供者(IdP),并希望将Kibana添加为服务提供者(Service Provider)。
Elastic Stack 使用标准的 SAML 元数据 文档,以 XML 格式定义您的 IdP 的功能和特性。您应该能够在您的 IdP 管理界面中下载或生成这样的文档。
下载IdP元数据文档并将其存储在每个Elasticsearch节点上的config
目录中。出于本指南的目的,我们假设您将其存储为config/saml/idp-metadata.xml
。
IdP 将被分配一个标识符(在 SAML 术语中称为 EntityID),该标识符通常以 统一资源标识符(URI)形式表示。您的管理界面可能会告诉您这是什么,或者您可能需要阅读元数据文档来找到它——查找 EntityDescriptor
元素上的 entityID
属性。
大多数身份提供者(IdP)会提供一个包含Elastic Stack所需所有功能的适当元数据文件,并且只需要按照以下描述的配置步骤进行配置。为了完整性,Elastic Stack对IdP元数据的最低要求是:
Elastic Stack 要求 IdP 发出的所有消息都必须签名。
对于身份验证
消息,签名可以应用于响应本身,也可以应用于单个断言。
对于
消息,消息本身必须签名,并且签名应作为 URL 参数提供,如 HTTP-Redirect 绑定所要求的那样。
为 SAML 认证配置 Elasticsearch
edit在Elasticsearch中启用SAML认证有五个配置步骤:
- 启用HTTP的SSL/TLS
- 启用令牌服务
- 创建一个或多个SAML领域
- 配置角色映射
- 为您的身份提供者生成一个SAML元数据文件 (可选)
为HTTP启用TLS
edit如果您的 Elasticsearch 集群在生产模式下运行,那么在启用 SAML 认证之前,您必须配置 HTTP 接口以使用 SSL/TLS。
更多信息,请参阅 加密Elasticsearch的HTTP客户端通信。
启用令牌服务
editElasticsearch 的 SAML 实现使用了 Elasticsearch Token Service。如果您在 HTTP 接口上配置了 TLS,此服务将自动启用,并且可以通过在您的 elasticsearch.yml
文件中包含以下内容来显式配置:
xpack.security.authc.token.enabled: true
创建一个SAML领域
editSAML 认证通过在 Elasticsearch 的认证链中配置 SAML 领域来启用。
此领域有一些强制性设置和许多可选设置。可用设置的详细信息在安全设置中进行了描述。例如,SAML领域设置、SAML领域签名设置、SAML领域加密设置、SAML领域SSL设置。本指南将引导您了解最常见的设置。
通过将以下内容添加到您的 elasticsearch.yml
配置文件中来创建一个领域。每个配置值的解释如下。
xpack.security.authc.realms.saml.saml1: order: 2 idp.metadata.path: saml/idp-metadata.xml idp.entity_id: "https://sso.example.com/" sp.entity_id: "https://kibana.example.com/" sp.acs: "https://kibana.example.com/api/security/saml/callback" sp.logout: "https://kibana.example.com/logout" attributes.principal: "urn:oid:0.9.2342.19200300.100.1.1" attributes.groups: "urn:oid:1.3.6.1.4.1.5923.1.5.1."
SAML 用于通过 Kibana 进行身份验证,但它不是直接对 Elasticsearch REST API 进行身份验证的有效手段。因此,我们建议您在身份验证链中至少包含一个额外的领域,例如用于 API 客户端的 native realm。
上述示例中使用的配置值如下:
- xpack.security.authc.realms.saml.saml1
-
这定义了一个名为“saml1”的新
saml
认证领域。 有关领域的更多解释,请参见Realms。 - order
- 领域在领域链中的顺序。具有较低顺序的领域具有最高优先级,并且首先被咨询。我们建议给予基于密码的领域,如文件、本地、LDAP和Active Directory最低的顺序(最高优先级),其次是SSO领域,如SAML和OpenID Connect。如果你有多个相同类型的领域,给予最常访问的领域最低的顺序,以便首先咨询它。
- idp.metadata.path
-
这是您为身份提供者保存的元数据文件的路径。
您在此处输入的路径是相对于您的
config/
目录的。 Elasticsearch 将自动监控此文件的更改,并在更新时重新加载配置。 - idp.entity_id
-
这是您的IdP使用的标识符(SAML EntityID)。
它应与元数据文件中的
entityID
属性匹配。 - sp.entity_id
- 这是您的Kibana实例的唯一标识符,表示为URI。 当您在IdP中将Kibana添加为服务提供商时,将使用此值。 我们建议您使用Kibana实例的基本URL作为实体ID。
- sp.acs
-
断言消费者服务(ACS)端点是Kibana中接受来自IdP的身份验证消息的URL。
此ACS端点仅支持SAML HTTP-POST绑定。
它必须是用户尝试登录Kibana时,其网络浏览器可以访问的URL,不需要直接被Elasticsearch或IdP访问。
正确的值可能因您安装Kibana的方式以及是否涉及任何代理而异,但通常为
${kibana-url}/api/security/saml/callback
,其中${kibana-url}是您的Kibana实例的基本URL。 - sp.logout
-
这是Kibana中接受来自IdP的注销消息的URL。
与
sp.acs
URL类似,它必须可以从Web浏览器访问,但不需要直接被Elasticsearch或IdP访问。正确的值可能因您安装Kibana的方式以及是否涉及任何代理而有所不同,但它通常是${kibana-url}/logout
,其中${kibana-url}是您的Kibana实例的基本URL。 - attributes.principal
- 参见属性映射。
- attributes.groups
- 参见属性映射。
属性映射
edit当用户通过您的身份提供者连接到Kibana时,身份提供者将提供一个关于用户的SAML断言。该断言将包含一个认证声明,表明用户已成功通过身份提供者的认证,以及一个或多个属性声明,这些声明将包含用户的属性。
这些属性可能包括以下内容:
- 用户的用户名
- 用户的电子邮件地址
- 用户的组或角色
SAML中的属性使用URI命名,例如
urn:oid:0.9.2342.19200300.100.1.1
或
http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn
,并且与它们相关联的有一个或多个值。
这些属性标识符在不同的身份提供者(IdP)之间有所不同,大多数身份提供者提供了自定义URI及其关联值的方法。
Elasticsearch 使用这些属性来推断已登录用户的信息,并且它们可以用于角色映射(如下)。
为了让这些属性变得有用,Elasticsearch 和 IdP 需要对属性的名称有一个共同的值。这是通过手动配置 IdP 和 SAML 领域来使用相同的 URI 名称来实现的,每个逻辑用户属性都是如此。
配置这些SAML属性的推荐步骤如下:
- 咨询您的身份提供者(IdP),了解它可以提供哪些用户属性。 这因提供者而异,但您应该能够从文档或您的本地管理员处获得列表。
-
阅读Elasticsearch支持的用户属性列表,并决定哪些对您有用,并且可以由您的IdP提供。至少,需要
principal
属性。 - 配置您的IdP以“释放”这些属性到您的Kibana SAML服务提供者。此过程因提供者而异——有些会提供用户界面,而其他的可能需要您编辑配置文件。通常,IdP(或您的本地管理员)会建议为每个属性使用什么URI。您可以简单地接受这些建议,因为Elasticsearch服务是完全可配置的,不需要使用任何特定的URI。
-
在Elasticsearch中配置SAML领域,将Elasticsearch用户属性(参见下面的列表)与您在IdP中配置的URI关联起来。在上面的示例中,我们配置了
principal
和groups
属性。
特殊属性名称
edit一般来说,Elasticsearch 期望为属性配置的值将是一个 URI,例如 urn:oid:0.9.2342.19200300.100.1.1
,不过还有一些额外的名称可以使用:
-
nameid
-
这使用SAML
NameID
值(去除所有前导和尾随空格) 而不是SAML属性。SAMLNameID
元素是一个可选的,但通常提供的字段,在SAML断言中,IdP可能使用它来标识该断言的主题。在某些情况下,NameID
将与用户在IdP中的登录标识符(用户名)相关联,但在许多情况下,它们将是IdP内部生成的标识符,这些标识符在IdP外部没有明显的意义。 -
nameid:persistent
-
这使用SAML
NameID
值(去除所有前导和尾随空白),但仅当NameID格式为urn:oasis:names:tc:SAML:2.0:nameid-format:persistent
时。 SAMLNameID
元素具有一个可选的Format
属性,该属性指示所提供名称的语义。 IdP通常配置为使用“transient”NameID,每次会话都会提供一个新的标识符。 由于很少有用将transient NameID作为属性映射的一部分,因此可以使用“nameid:persistent”属性名称作为安全机制, 如果您尝试从没有持久值的NameID
进行映射,将会导致错误。
身份提供者可以静态配置为以特定格式发布NameID
,或者可以配置为尝试符合SP的要求。SP在其身份验证请求中使用一个称为NameIDPolicy
的元素声明其要求。如果需要,您可以设置名为nameid_format
的相关设置,以请求IdP以特定格式发布NameID
。
- friendlyName
-
SAML属性可能除了基于URI的名称外,还有一个friendlyName。
例如,名称为
urn:oid:0.9.2342.19200300.100.1.1
的属性 可能还有一个friendlyName为uid
。 您可以在属性映射中使用这些friendlyName,但建议您使用基于URI的名称,因为friendlyName既不是标准化的也不是强制性的。
下面的示例配置了一个领域,为主体使用持久化的nameid,并使用friendlyName为“roles”的属性来表示用户的组。
xpack.security.authc.realms.saml.saml1: order: 2 idp.metadata.path: saml/idp-metadata.xml idp.entity_id: "https://sso.example.com/" sp.entity_id: "https://kibana.example.com/" sp.acs: "https://kibana.example.com/api/security/saml/callback" attributes.principal: "nameid:persistent" attributes.groups: "roles" nameid_format: "urn:oasis:names:tc:SAML:2.0:nameid-format:persistent"
Elasticsearch 用户属性
editElasticsearch SAML realm 可以配置为将 SAML 属性
映射到经过身份验证的用户上的以下属性:
- principal
-
(必需)
这是将应用于与此领域进行身份验证的用户的用户名。
principal
出现在 Elasticsearch 审计日志等地方。 - groups
-
(推荐) 如果您希望使用您的身份提供者(IdP)的组或角色概念作为用户Elasticsearch权限的基础,您应该使用此属性进行映射。
groups
会直接传递给您的 角色映射规则。一些身份提供者(IdP)配置为将
groups
列表作为单个值、逗号分隔的字符串发送。要将此SAML属性映射到Elasticsearch领域中的attributes.groups
设置,您可以使用attribute_delimiters.group
设置配置字符串分隔符。例如,将SAML属性值
engineering,elasticsearch-admins,employees
以分隔符值,
进行分割, 将会得到engineering
、elasticsearch-admins
和employees
作为用户的组列表。 - name
- (可选) 用户的完整姓名。
- (可选) 用户的电子邮件地址。
- dn
- (可选) 用户的X.500 可分辨名称。
从SAML属性中提取部分值
edit在某些情况下,身份提供者(IdP)的属性可能包含比您希望在Elasticsearch中使用的更多信息。一个常见的例子是,IdP仅使用电子邮件地址,但您希望用户的principal
使用电子邮件地址的local-name部分。例如,如果他们的电子邮件地址是james.wong@staff.example.com
,那么您希望他们的principal仅为james.wong
。
这可以通过在 Elasticsearch 领域中使用 attribute_patterns
设置来实现,如下面的领域配置所示:
xpack.security.authc.realms.saml.saml1: order: 2 idp.metadata.path: saml/idp-metadata.xml idp.entity_id: "https://sso.example.com/" sp.entity_id: "https://kibana.example.com/" sp.acs: "https://kibana.example.com/api/security/saml/callback" attributes.principal: "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress" attribute_patterns.principal: "^([^@]+)@staff\\.example\\.com$"
在这种情况下,用户的principal
是从电子邮件属性映射的,但在将其分配给用户之前,会对该值应用一个正则表达式。如果正则表达式匹配,则使用第一个组的结果作为有效值。如果正则表达式不匹配,则属性映射失败。
在这个例子中,电子邮件地址必须属于 staff.example.com
域,
然后本地部分(@
之前的任何内容)被用作主体。
任何尝试使用不同电子邮件域登录的用户都将失败,因为正则表达式不会匹配他们的电子邮件地址,因此他们
的主体属性(这是强制性的)将不会被填充。
这些正则表达式中的小错误可能会带来严重的安全后果。例如,如果我们不小心遗漏了上面的例子中的结尾$
,那么我们将匹配任何域名以staff.example.com
开头的电子邮件地址,这将接受诸如admin@staff.example.com.attacker.net
这样的电子邮件地址。确保您的正则表达式尽可能精确是非常重要的,这样您就不会无意中为用户的冒充攻击打开一个途径。
请求特定的认证方法
edit有时,SAML SP 需要能够对在 IdP 上进行的身份验证施加特定的限制,以便评估其可以对相应的身份验证响应所放置的信任级别。这些限制可能与身份验证方法(密码、客户端证书等)、注册期间的用户识别方法以及其他细节有关。Elasticsearch 实现了 SAML 2.0 身份验证上下文,这可以根据 SAML 2.0 核心规范中的定义用于此目的。
简而言之,SAML SP定义了一组身份验证上下文类引用值,这些值描述了要对IdP施加的限制,并在身份验证请求中发送这些值。IdP尝试满足这些限制。如果无法满足这些限制,身份验证尝试将失败。如果用户成功通过身份验证,SAML响应的身份验证声明中将包含已满足的限制的指示。
您可以通过在SAML领域配置中使用req_authn_context_class_ref
选项来定义身份验证上下文类引用值。请参阅SAML领域设置。
Elasticsearch 仅支持 exact
比较方法用于认证上下文。
当它从身份提供者(IdP)接收到认证响应时,Elasticsearch 会检查 SAML 断言的认证声明中的一部分,即认证上下文类引用(Authentication Context Class Reference)的值。如果该值与请求的值之一匹配,则认证被视为成功。否则,认证尝试将失败。
SAML 注销
editSAML协议支持单点登出(SLO)的概念。 身份提供者对SLO的支持程度各不相同。 您应查阅您的身份提供者的文档,以确定它提供哪些登出服务。
默认情况下,如果以下条件为真,Elastic Stack 将支持 SAML SLO:
- 您的IdP元数据指定IdP提供单点注销服务
- 您的IdP在为您的用户发布的SAML断言的主题中释放了一个NameID
-
您配置了
sp.logout
-
设置
idp.use_single_logout
不是false
IdP SLO 服务
editElasticsearch从IdP的SAML元数据中读取的值之一是
。为了使单点注销与Elastic
stack一起工作,Elasticsearch要求此服务存在并支持绑定
urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect
。
Elastic Stack 将根据需要向此服务发送
和
消息。
sp.logout 设置
editElasticsearch realm 设置 sp.logout
指定了 Kibana 中的一个 URL,IdP 可以向该 URL 发送
和
消息。此服务使用 SAML HTTP-Redirect 绑定。
Elasticsearch 将处理
消息,并执行全局注销操作,使与提供的 SAML 会话关联的任何现有 Elasticsearch 安全令牌失效。
如果您没有为 sp.logout
配置值,Elasticsearch 将拒绝所有
消息。
IdP 通常要求 LogoutRequest
消息被签名,因此您可能需要配置 签名凭证。
idp.use_single_logout 设置
edit如果您的身份提供者(IdP)提供了一个
,但您不希望使用它,
您可以在您的SAML领域中配置idp.use_single_logout: false
,并且Elasticsearch
将忽略您的IdP提供的SLO服务。在这种情况下,当用户从Kibana注销时,它将使他们的Elasticsearch会话(安全令牌)失效,但
不会在IdP上执行任何注销操作。
在不使用单点注销的情况下使用 Kibana
edit如果您的身份提供程序(IdP)不支持单点注销,或者您选择不使用它,那么Kibana将仅执行“本地注销”。
这意味着Kibana将使其用于与Elasticsearch通信的会话令牌失效,但将无法执行任何类型的身份提供者会话失效。在大多数情况下,这意味着Kibana用户仍然被视为已登录到身份提供者。因此,如果用户导航到Kibana登录页面,他们将被自动重新认证,并开始一个新的Kibana会话,而无需输入任何凭证。
这个问题的可能解决方案是:
- 请向您的IdP管理员或供应商索取单点注销服务
-
如果您的IdP确实提供单点注销服务,请确保它包含在IdP元数据文件中,并且不要将
idp.use_single_logout
设置为false
。 - 建议您的用户在退出Kibana后关闭浏览器
-
在您的SAML领域中启用
force_authn
设置。此设置会导致Elastic Stack在每次用户尝试登录Kibana时从IdP请求新的身份验证。 此设置默认为false
,因为它可能会给用户带来更繁琐的体验,但它也可以作为一种有效的保护措施,防止用户利用现有的IdP会话。
加密和签名
editElastic Stack 支持生成签名的 SAML 消息(用于身份验证和/或注销),验证来自 IdP 的签名 SAML 消息(用于身份验证和注销),并且可以处理加密内容。
您可以为签名、加密或两者配置Elasticsearch,使用相同的或分别用于每种操作的密钥。
Elastic Stack 使用带有 RSA 私钥的 X.509 证书进行 SAML 加密。这些密钥可以使用任何标准的 SSL 工具生成,包括 elasticsearch-certutil
工具。
您的身份提供者(IdP)可能要求Elastic Stack拥有用于签署SAML消息的加密密钥,并且您需要在服务提供者配置中提供相应的签名证书(可以在Elastic Stack SAML元数据文件中配置,或者在IdP管理界面中手动配置)。虽然大多数IdP不期望身份验证请求被签名,但通常情况下,注销请求需要签名。您的IdP将根据为Elastic Stack服务提供者配置的签名证书来验证这些签名。
加密证书很少需要,但 Elastic Stack 支持在 IdP 或本地策略要求使用它们的情况下使用。
生成证书和密钥
editElasticsearch 支持 PEM、PKCS#12 或 JKS 格式的证书和密钥。 一些身份提供者对支持的格式有更严格的限制,并要求您以特定格式提供证书文件。 您应查阅您的 IdP 的文档,以确定他们支持的格式。由于 PEM 格式是最常用的支持格式,下面的示例将生成该格式的证书。
使用elasticsearch-certutil
工具,您可以使用以下命令生成签名证书:
bin/elasticsearch-certutil cert --self-signed --pem --days 1100 --name saml-sign --out saml-sign.zip
这将会
-
生成证书和密钥对(
cert
子命令) -
以PEM格式创建文件(
-pem
选项) -
生成有效期为3年的证书(
-days 1100
) -
将证书命名为
saml-sign
(-name
选项) -
将证书和密钥保存到
saml-sign.zip
文件中(-out
选项)
生成的zip压缩包将包含3个文件:
-
saml-sign.crt
,用于签名的公钥证书 -
saml-sign.key
,证书的私钥 -
ca.crt
,一个不需要的CA证书,可以忽略。
加密证书可以通过相同的过程生成。
配置 Elasticsearch 进行签名
edit默认情况下,如果已配置签名密钥,Elasticsearch 将对所有外发的 SAML 消息进行签名。
如果您希望使用PEM 格式的密钥和证书进行签名,那么您应该在 SAML 领域配置以下设置:
-
signing.certificate
-
PEM格式证书文件的路径。例如
saml/saml-sign.crt
-
signing.key
-
PEM格式密钥文件的路径。例如
saml/saml-sign.key
-
signing.secure_key_passphrase
-
密钥的密码,如果文件是加密的。这是一个
安全设置,必须使用
elasticsearch-keystore
工具进行设置。
如果您希望使用 PKCS#12 格式 文件或 Java Keystore 进行签名,则应在 SAML 领域配置以下设置:
-
signing.keystore.path
-
PKCS#12 或 JKS 密钥库的路径。例如
saml/saml-sign.p12
-
signing.keystore.alias
-
密钥库中密钥的别名。例如
signing-key
-
signing.keystore.secure_password
-
密钥库的密码,如果文件已加密。这是一个
安全设置,必须使用
elasticsearch-keystore
工具进行设置。
如果您希望签署某些但不是所有外发的SAML消息,那么您应该在SAML领域配置以下设置:
-
signing.saml_messages
-
要签名的消息类型列表。消息类型由用于消息的XML元素的本地名称标识。支持的值包括:
AuthnRequest
、LogoutRequest
和LogoutResponse
。
配置 Elasticsearch 以处理加密消息
editElasticsearch 安全功能支持使用单一密钥进行消息解密。如果配置了密钥,则 Elasticsearch 会尝试使用该密钥来解密身份验证响应中的 EncryptedAssertion
和 EncryptedAttribute
元素,以及注销请求中的 EncryptedID
元素。
Elasticsearch 拒绝任何包含无法解密的 EncryptedAssertion
的 SAML 消息。
如果一个断言
包含加密和明文属性,那么未能解密加密属性不会导致自动拒绝。相反,Elasticsearch会处理可用的明文属性(以及任何可以解密的加密属性
)。
如果您希望使用 PEM 格式的 密钥和证书进行 SAML 加密, 那么您应该在 SAML 领域配置以下设置:
-
encryption.certificate
-
PEM格式证书文件的路径。例如
saml/saml-crypt.crt
-
encryption.key
-
PEM格式密钥文件的路径。例如
saml/saml-crypt.key
-
encryption.secure_key_passphrase
-
密钥的密码,如果文件是加密的。这是一个
安全设置,必须使用
elasticsearch-keystore
工具进行设置。
如果您希望使用 PKCS#12 格式 文件或 Java Keystore 进行 SAML 加密,那么您应该在 SAML 领域配置以下设置:
-
encryption.keystore.path
-
PKCS#12 或 JKS 密钥库的路径。例如
saml/saml-crypt.p12
-
encryption.keystore.alias
-
密钥库中密钥的别名。例如
encryption-key
-
encryption.keystore.secure_password
-
密钥库的密码,如果文件已加密。这是一个
安全设置,必须使用
elasticsearch-keystore
工具进行设置。
生成SP元数据
edit一些身份提供商支持从服务提供商导入元数据文件。这将自动配置身份提供商和服务提供商之间的许多集成选项。
Elastic Stack 支持使用 bin/elasticsearch-saml-metadata
命令 或 SAML 服务提供商元数据 API 生成此类元数据文件。
您可以通过向Elasticsearch发出API请求来生成SAML元数据,并使用jq
等工具将其存储为XML文件。例如,以下命令生成SAML领域realm1
的元数据并将其保存到metadata.xml
文件中:
curl -u user_name:password -X GET http://localhost:9200/_security/saml/metadata/saml1 -H 'Content-Type: application/json' | jq -r '.[]' > metadata.xml
配置角色映射
edit当用户使用SAML进行身份验证时,他们会被识别到Elastic Stack,但这并不会自动授予他们执行任何操作或访问任何数据的权限。
您的SAML用户在被分配角色之前无法执行任何操作。这可以通过 添加角色映射API 或使用 授权领域来完成。
您不能使用角色映射文件 来授予通过SAML进行身份验证的用户角色。
这是一个简单的角色映射示例,它将 example_role
角色授予任何针对 saml1
领域进行身份验证的用户:
PUT /_security/role_mapping/saml-example { "roles": [ "example_role" ], "enabled": true, "rules": { "field": { "realm.name": "saml1" } } }
通过领域配置映射的属性用于处理角色映射规则,这些规则决定了用户被授予哪些角色。
提供给角色映射的用户字段是从SAML属性中派生出来的,如下所示:
-
username
: Theprincipal
attribute -
dn
: Thedn
attribute -
groups
: Thegroups
attribute -
metadata
: 参见 用户元数据
有关更多信息,请参阅用户和组到角色的映射以及 角色映射。
如果您的身份提供者(IdP)能够向服务提供者提供组或角色,那么您应该将此SAML属性映射到Elasticsearch领域中的attributes.groups
设置,然后按照以下示例在角色映射中使用它。
此映射授予通过 saml1
领域进行身份验证并属于 finance-team
组的用户 Elasticsearch finance_data
角色。
PUT /_security/role_mapping/saml-finance { "roles": [ "finance_data" ], "enabled": true, "rules": { "all": [ { "field": { "realm.name": "saml1" } }, { "field": { "groups": "finance-team" } } ] } }
属性 |
如果您的用户也存在于可以直接被Elasticsearch访问的存储库中(例如LDAP目录),那么您可以使用授权领域,而不是角色映射。
在这种情况下,您执行以下步骤:
1. 在您的 SAML 领域中,通过配置 attributes.principal
设置,分配一个 SAML 属性作为查找用户 ID。
2. 创建一个新的领域,该领域可以从您的本地存储库(例如 ldap
领域)中查找用户。
3. 在您的 SAML 领域中,将 authorization_realms
设置为您在步骤 2 中创建的领域的名称。
用户元数据
edit默认情况下,通过SAML进行身份验证的用户将具有一些额外的元数据字段。
-
saml_nameid
将被设置为 SAML 认证响应中NameID
元素的值 -
saml_nameid_format
将被设置为 NameID 的format
属性的完整 URI -
每个在认证响应中提供的 SAML 属性(无论它是否映射到 Elasticsearch 用户属性),都将被添加为元数据字段
saml(name)
,其中 "name" 是属性的完整 URI 名称。例如saml(urn:oid:0.9.2342.19200300.100.1.3)
。 -
对于每个具有 friendlyName 的 SAML 属性,也将被添加为元数据字段
saml_friendlyName
,其中 "name" 是属性的完整 URI 名称。例如saml_mail
。
可以通过在saml realm中添加设置populate_user_metadata: false
来禁用此行为。
配置 Kibana
edit在Kibana中使用SAML认证需要一些额外的设置,除了标准的Kibana安全配置。 Kibana安全文档 提供了你可以应用的可用配置选项的详细信息。
特别是,由于您的 Elasticsearch 节点已配置为在 HTTP 接口上使用 TLS,您必须配置 Kibana 使用 https
URL 连接到 Elasticsearch,并且您可能需要配置 elasticsearch.ssl.certificateAuthorities
以信任 Elasticsearch 已配置使用的证书。
Kibana中的SAML认证受以下kibana.yml
中的超时设置影响:
您可能希望根据您的安全要求调整这些超时设置。
支持SAML所需的三个附加设置如下所示:
xpack.security.authc.providers: saml.saml1: order: 0 realm: "saml1"
上述示例中使用的配置值如下:
-
xpack.security.authc.providers
-
添加
saml
提供程序以指示 Kibana 使用 SAML SSO 作为身份验证方法。 -
xpack.security.authc.providers.saml.<provider-name>.realm
-
将此设置为您在 Elasticsearch 领域配置中使用的 SAML 领域名称,例如:
saml1
在 Kibana 中支持 SAML 和基本身份验证
editKibana 中的 SAML 支持是基于这样的预期设计的,即它将成为该 Kibana 实例用户的主要(或唯一)身份验证方法。然而,通过按照以下示例设置 xpack.security.authc.providers
,可以在单个 Kibana 实例中同时支持 SAML 和基本身份验证:
xpack.security.authc.providers: saml.saml1: order: 0 realm: "saml1" basic.basic1: order: 1
如果Kibana以这种方式配置,用户在登录选择器UI上会看到一个选择。他们可以使用SAML登录,或者提供用户名和密码,并依赖Elasticsearch中的其他安全领域之一。只有那些拥有已配置的Elasticsearch认证领域用户名和密码的用户才能通过Kibana登录表单登录。
或者,当启用了basic
身份验证提供程序时,您可以在Kibana前面放置一个反向代理,并将其配置为为每个请求发送一个基本身份验证头(Authorization: Basic ....
)。如果存在并有效此头,Kibana将不会启动SAML身份验证过程。
操作多个 Kibana 实例
edit如果您希望拥有多个Kibana实例,这些实例都针对同一个Elasticsearch集群进行身份验证,那么每个配置为SAML身份验证的Kibana实例都需要其自己的SAML领域。
每个SAML领域必须拥有自己的唯一实体ID(sp.entity_id
),以及自己的
断言消费者服务(sp.acs
)。每个Kibana实例将通过查找匹配的sp.acs
值来映射到正确的领域。
这些领域可以使用相同的身份提供者,但并非必须如此。
以下是拥有3个不同Kibana实例的示例,其中2个使用相同的内部IdP,另一个使用不同的IdP。
xpack.security.authc.realms.saml.saml_finance: order: 2 idp.metadata.path: saml/idp-metadata.xml idp.entity_id: "https://sso.example.com/" sp.entity_id: "https://kibana.finance.example.com/" sp.acs: "https://kibana.finance.example.com/api/security/saml/callback" sp.logout: "https://kibana.finance.example.com/logout" attributes.principal: "urn:oid:0.9.2342.19200300.100.1.1" attributes.groups: "urn:oid:1.3.6.1.4.1.5923.1.5.1." xpack.security.authc.realms.saml.saml_sales: order: 3 idp.metadata.path: saml/idp-metadata.xml idp.entity_id: "https://sso.example.com/" sp.entity_id: "https://kibana.sales.example.com/" sp.acs: "https://kibana.sales.example.com/api/security/saml/callback" sp.logout: "https://kibana.sales.example.com/logout" attributes.principal: "urn:oid:0.9.2342.19200300.100.1.1" attributes.groups: "urn:oid:1.3.6.1.4.1.5923.1.5.1." xpack.security.authc.realms.saml.saml_eng: order: 4 idp.metadata.path: saml/idp-external.xml idp.entity_id: "https://engineering.sso.example.net/" sp.entity_id: "https://kibana.engineering.example.com/" sp.acs: "https://kibana.engineering.example.com/api/security/saml/callback" sp.logout: "https://kibana.engineering.example.com/logout" attributes.principal: "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn"
可以有一个或多个使用 SAML 的 Kibana 实例,而其他实例则使用基本身份验证针对另一种领域类型(例如 Native 或 LDAP)。
SAML 领域配置故障排除
editSAML 2.0 规范为标准的实现者提供了许多选项和灵活性,这反过来又增加了复杂性和服务提供商(Elastic Stack)和身份提供商处可用的配置选项数量。此外,不同的安全域有不同的安全要求,需要特定的配置来满足。我们已尽力通过合理的默认值和上述详细的文档来掩盖这种复杂性,但如果您在配置 SAML 领域时遇到问题,可以查看我们的 SAML 故障排除文档,其中包含常见问题的建议和解决方案。
没有 Kibana 的 SAML
editElasticsearch 中的 SAML 领域旨在允许用户通过 Kibana 进行身份验证,因此,上述指南的大部分内容都假设使用了 Kibana。本节描述了自定义 Web 应用程序如何使用相关的 SAML REST API 来通过 SAML 对用户进行 Elasticsearch 身份验证。
本节假设读者熟悉SAML 2.0标准,更具体地说是SAML 2.0 Web浏览器单点登录配置文件。
单点登录领域如 OpenID Connect 和 SAML 利用 Elasticsearch 中的 Token Service,原则上将 SAML 或 OpenID Connect 认证响应交换为 Elasticsearch 访问令牌和刷新令牌。访问令牌用作后续调用 Elasticsearch 的凭证。刷新令牌使用户能够在当前令牌过期后获取新的 Elasticsearch 访问令牌。
SAML 领域
edit您必须在Elasticsearch中创建一个SAML领域并相应地配置它。请参阅配置Elasticsearch以进行SAML认证
用于访问API的服务帐户用户
edit该领域的设计基于一个假设,即需要有一个特权实体作为认证代理。在这种情况下,自定义Web应用程序是处理最终用户认证(更准确地说,“委托”认证给SAML身份提供者)的认证代理。SAML相关的API需要认证以及认证用户所需的必要授权级别。因此,您必须创建一个服务账户用户并为其分配一个角色,该角色赋予其manage_saml
集群权限。在认证发生后,使用manage_token
集群权限将是必要的,以便服务账户用户可以维持访问权限,以便代表已认证用户刷新访问令牌或随后将他们注销。
POST /_security/role/saml-service-role { "cluster" : ["manage_saml", "manage_token"] }
POST /_security/user/saml-service-user { "password" : "<somePasswordHere>", "roles" : ["saml-service-role"] }
处理SP发起的身份验证流程
edit在高层次上,自定义Web应用程序需要执行以下步骤,以便使用SAML对Elasticsearch进行用户身份验证:
-
向
_security/saml/prepare
发起 HTTP POST 请求,以saml-service-user
用户身份进行认证。可以使用 Elasticsearch 配置中的 SAML 领域名称或请求体中的断言消费者服务 URL 值。更多详情请参见 SAML prepare authentication API。POST /_security/saml/prepare { "realm" : "saml1" }
-
处理来自
/_security/saml/prepare
的响应。Elasticsearch 的响应将包含 3 个参数:redirect
、realm
和id
。自定义 Web 应用程序需要将id
的值存储在用户的会话中(客户端在 cookie 中或服务器端,如果会话信息以这种方式持久化)。它还必须将用户的浏览器重定向到redirect
参数中返回的 URL。id
值不应被忽略,因为它在 SAML 中用作 nonce,以减轻重放攻击。 -
处理来自 SAML 身份提供者的后续响应。用户在身份提供者处成功认证后,将被重定向回断言消费者服务 URL。这个
sp.acs
需要定义为一个自定义 Web 应用程序处理的 URL。当它接收到这个 HTTP POST 请求时,自定义 Web 应用程序必须解析它,并向_security/saml/authenticate
API 发起一个 HTTP POST 请求。它必须以saml-service-user
用户身份进行认证,并传递作为请求体发送的 Base64 编码的 SAML 响应。它还必须传递之前在用户会话中保存的id
值。详情请参见 SAML authenticate API。
POST /_security/saml/authenticate { "content" : "PHNhbWxwOlJlc3BvbnNlIHhtbG5zOnNhbWxwPSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6cHJvdG9jb2wiIHhtbG5zOnNhbWw9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMD.....", "ids" : ["4fee3b046395c4e751011e97f8900b5273d56685"] }
Elasticsearch 将验证这一点,如果一切正确,将响应一个可以作为
Bearer
令牌用于后续请求的访问令牌。它还提供了一个刷新令牌,可以稍后用于刷新给定的访问令牌,如 获取令牌 API 中所述。 -
调用
/_security/saml/authenticate
的响应将仅包含已认证用户的用户名。如果您需要获取该用户在 SAML 响应中包含的 SAML 属性值,您可以使用访问令牌作为Bearer
令牌调用 Authenticate API/_security/_authenticate/
,SAML 属性值将作为 用户元数据 的一部分包含在响应中。
处理IdP发起的身份验证流程
editElasticsearch 还可以处理 SAML 2 Web Browser SSO 配置文件的 IdP 发起的单点登录流程。在这种情况下,身份验证从 SAML 身份提供者发出的未经请求的身份验证响应开始。与 SP 发起的 SSO 的区别在于,Web 应用程序需要处理不会作为先前重定向响应的 sp.acs
请求。因此,它将不会为用户已经有一个会话,并且它将不会为 id
参数存储任何值。在这种情况下,对 _security/saml/authenticate
API 的请求将如下所示:
POST /_security/saml/authenticate { "content" : "PHNhbWxwOlJlc3BvbnNlIHhtbG5zOnNhbWxwPSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6cHJvdG9jb2wiIHhtbG5zOnNhbWw9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMD.....", "ids" : [] }
处理注销流程
edit-
在必要时,自定义Web应用程序可以通过使用SAML logout API并传递访问令牌和刷新令牌作为参数来注销用户。例如:
POST /_security/saml/logout { "token" : "46ToAxZVaXVVZTVKOVF5YU04ZFJVUDVSZlV3", "refresh_token": "mJdXLtmvTUSpoLwMvdBt_w" }
如果SAML领域配置正确且IdP支持(参见SAML注销),此请求将触发SAML SP发起的单点注销。在这种情况下,响应将包含一个
redirect
参数,指示用户需要在IdP上重定向以完成注销。 -
或者,IdP 可能在某个时候启动单点注销流程。为了处理这种情况,自定义 Web 应用程序需要处理注销 URL(
sp.logout
)。用户将被重定向到的 URL 的查询部分将包含一个 SAML 注销请求,并且需要将此查询部分使用 SAML invalidate API 传递给 Elasticsearch。POST /_security/saml/invalidate { "query" : "SAMLRequest=nZFda4MwFIb%2FiuS%2BmviRpqFaClKQdbvo2g12M2KMraCJ9cRR9utnW4Wyi13sMie873MeznJ1aWrnS3VQGR0j4mLkKC1NUeljjA77zYyhVbIE0dR%2By7fmaHq7U%2BdegXWGpAZ%2B%2F4pR32luBFTAtWgUcCv56%2Fp5y30X87Yz1khTIycdgpUW9kY7WdsC9zxoXTvMvWuVV98YyMnSGH2SYE5pwALBIr9QKiwDGpW0oGVUznGeMyJZKFkQ4jBf5HnhUymjIhzCAL3KNFihbYx8TBYzzGaY7EnIyZwHzCWMfiDnbRIftkSjJr%2BFu0e9v%2B0EgOquRiiZjKpiVFp6j50T4WXoyNJ%2FEWC9fdqc1t%2F1%2B2F3aUpjzhPiXpqMz1%2FHSn4A&SigAlg=http%3A%2F%2Fwww.w3.org%2F2001%2F04%2Fxmldsig-more%23rsa-sha256&Signature=MsAYz2NFdovMG2mXf6TSpu5vlQQyEJAg%2B4KCwBqJTmrb3yGXKUtIgvjqf88eCAK32v3eN8vupjPC8LglYmke1ZnjK0%2FKxzkvSjTVA7mMQe2AQdKbkyC038zzRq%2FYHcjFDE%2Bz0qISwSHZY2NyLePmwU7SexEXnIz37jKC6NMEhus%3D", "realm" : "saml1" }
自定义Web应用程序还需要处理响应,该响应将包含一个带有URL的
redirect
参数,该URL位于IdP中,包含SAML注销响应。应用程序应将用户重定向到该URL以完成注销。
对于SP发起的单点注销,IdP可能会发送一个注销响应,该响应可以通过Elasticsearch使用SAML complete logout API进行验证。
使用 OpenID Connect 配置 Elastic Stack 的单点登录
editElastic Stack 支持使用 OpenID Connect 通过 Kibana 进行单点登录 (SSO),其中 Elasticsearch 作为后端服务,持有大部分功能。Kibana 和 Elasticsearch 共同代表一个 OpenID Connect 依赖方 (RP),支持授权代码流和隐式流,这些流在 OpenID Connect 规范中定义。
本指南假设您有一个OpenID Connect提供程序,其中将注册Elastic Stack依赖方。
Kibana 中的 OpenID Connect 领域支持旨在预期它将成为该 Kibana 实例用户的主要身份验证方法。配置 Kibana 部分描述了这意味着什么以及如何在必要时设置它以支持其他领域。
OpenID Connect 提供者
editOpenID Connect 提供者(OP)是 OpenID Connect 中负责验证用户身份并向依赖方提供必要的令牌以包含身份验证和用户信息的实体。
为了使 Elastic Stack 能够使用您的 OpenID Connect Provider 进行身份验证,需要在 OP 和 RP 之间建立信任关系。在 OpenID Connect Provider 中,这意味着将 RP 注册为客户端。OpenID Connect 定义了一个动态客户端注册协议,但这通常面向实时客户端注册,而不是跨安全域单点登录的信任建立过程。所有 OP 还将允许通过用户界面(或较少情况下通过消费元数据文档)手动将 RP 注册为客户端。
注册Elastic Stack RP的过程将因OP而异,遵循提供商的相关文档是明智的。您通常需要为注册提供的RP信息如下:
-
Relying Party Name
: 依赖方的任意标识符。规范和Elastic Stack实现都不会对此值施加任何限制。 -
Redirect URI
: 这是OP在身份验证后将用户浏览器重定向到的URI。此值的适当值将取决于您的设置以及Kibana是否位于代理或负载均衡器后面。它通常为${kibana-url}/api/security/oidc/callback
(用于授权代码流程)或${kibana-url}/api/security/oidc/implicit
(用于隐式流程),其中${kibana-url}是您的Kibana实例的基本URL。您可能还会看到这被称为Callback URI
。
在注册过程结束时,OP将为RP(Elastic Stack)分配一个客户端标识符和一个客户端密钥。请注意这两个值,因为它们将在Elasticsearch配置中使用。
为 OpenID Connect 认证配置 Elasticsearch
edit以下是启用Elasticsearch中使用OpenID Connect进行身份验证所需的配置步骤摘要:
为HTTP启用TLS
edit如果您的 Elasticsearch 集群在生产模式下运行,那么在启用 OpenID Connect 认证之前,您必须配置 HTTP 接口以使用 SSL/TLS。
更多信息,请参阅 加密Elasticsearch的HTTP客户端通信。
启用令牌服务
editElasticsearch OpenID Connect 实现使用了 Elasticsearch Token 服务。如果你在 HTTP 接口上配置了 TLS,该服务会自动启用,并且可以通过在你的 elasticsearch.yml
文件中包含以下内容来显式配置:
xpack.security.authc.token.enabled: true
创建一个OpenID Connect领域
edit基于OpenID Connect的身份验证通过在Elasticsearch的认证链中配置适当的领域来启用。
此领域有一些强制性设置和一些可选设置。可用设置的详细描述请参见OpenID Connect realm settings。本指南将探讨最常见的设置。
在您的 elasticsearch.yml
文件中创建一个 OpenID Connect(领域类型为 oidc
)领域,类似于下面所示的内容:
下面使用的值只是一个示例,并不打算适用于每个用例。配置片段下方的详细信息提供了见解和建议,以帮助您根据您的OP配置选择适当的值。
xpack.security.authc.realms.oidc.oidc1: order: 2 rp.client_id: "the_client_id" rp.response_type: code rp.redirect_uri: "https://kibana.example.org:5601/api/security/oidc/callback" op.issuer: "https://op.example.org" op.authorization_endpoint: "https://op.example.org/oauth2/v1/authorize" op.token_endpoint: "https://op.example.org/oauth2/v1/token" op.jwkset_path: oidc/jwkset.json op.userinfo_endpoint: "https://op.example.org/oauth2/v1/userinfo" op.endsession_endpoint: "https://op.example.org/oauth2/v1/logout" rp.post_logout_redirect_uri: "https://kibana.example.org:5601/security/logged_out" claims.principal: sub claims.groups: "http://example.info/claims/groups"
上述示例中使用的配置值如下:
- xpack.security.authc.realms.oidc.oidc1
-
这定义了一个名为“oidc1”的新
oidc
认证领域。 有关领域的更多解释,请参阅Realms。 - order
- 你应该在认证链中的每个领域定义一个唯一的顺序。 建议将OpenID Connect领域放在认证链的底部(即,它具有最高的顺序)。
- rp.client_id
- 这是一个通常不透明的任意字符串,是OP在注册时分配给Elastic Stack RP的客户端标识符。
- rp.response_type
-
这是一个标识符,用于控制此依赖方支持的OpenID Connect认证流程,以及此依赖方请求OP应遵循的流程。支持的值包括
-
code
, 这意味着RP希望使用授权码流程。如果你的OP支持授权码流程,你应该选择这个而不是隐式流程。 -
id_token token
这意味着RP希望使用隐式流程,并且我们还请求一个oAuth2访问令牌从OP,我们可以潜在地用于后续请求(UserInfo)。如果OP在其配置中提供了一个UserInfo端点,或者如果你知道你将需要用于角色映射的声明在ID令牌中不可用,则应选择此项。 -
id_token
这意味着RP希望使用隐式流程,但对其获取oAuth2令牌不感兴趣。如果你确定所有必要的声明都将包含在ID令牌中,或者如果OP不提供User Info端点,请选择此项。
-
- rp.redirect_uri
-
认证后OP将重定向浏览器的重定向URI。这需要与在注册时配置给OP的URI完全相同,并且通常为
${kibana-url}/api/security/oidc/callback
,其中${kibana-url}是您的Kibana实例的基本URL - op.issuer
- 您的OpenID Connect Provider的可验证标识符。发行者标识符通常是一个区分大小写的URL。 此设置的值应由您的OpenID Connect Provider提供。
- op.authorization_endpoint
- 授权端点的URL位于OP中。这是用户的浏览器将被重定向以启动身份验证过程的地方。此设置的值应由您的OpenID Connect提供商提供。
- op.token_endpoint
- OpenID Connect Provider 中的 Token Endpoint 的 URL。这是 Elasticsearch 将发送请求以交换代码以获取 ID Token 的端点。当你使用隐式流时,此设置是可选的。此设置的值应由你的 OpenID Connect Provider 提供。
- op.jwkset_path
- 包含用于签名令牌和声明响应的密钥材料的JSON Web Key Set文件或URL的路径。如果设置了路径,它将相对于Elasticsearch配置目录进行解析。 Elasticsearch将自动监控此文件的更改,并在更新时重新加载配置。您的OpenID Connect提供商应为您提供此文件或其可用的URL。
- op.userinfo_endpoint
- (可选) OpenID Connect Provider 中的 UserInfo Endpoint 的 URL。这是 OP 的端点,如果需要,可以查询此端点以获取更多用户信息。此设置的值应由您的 OpenID Connect Provider 提供。
- op.endsession_endpoint
- (可选) OpenID Connect Provider 中的结束会话端点的 URL。这是用户浏览器在本地注销后将被重定向的端点,前提是领域配置为 RP 发起的单点注销,并且 OP 支持此功能。此设置的值应由您的 OpenID Connect Provider 提供。
- rp.post_logout_redirect_uri
-
(可选) 在成功完成单点注销后,OpenID Connect 提供者应将用户重定向到的重定向 URL(假设上面也设置了
op.endsession_endpoint
)。这应该设置为一个不会触发新的 OpenID Connect 认证的值,例如${kibana-url}/security/logged_out
或${kibana-url}/login?msg=LOGGED_OUT
,其中 ${kibana-url} 是您的 Kibana 实例的基本 URL。 - claims.principal
- 参见 Claims mapping。
- claims.groups
- 参见 Claims mapping。
OpenID Connect realm 的最后一部分配置是设置在 OP 中注册时分配给 RP 的 Client Secret
。这是一个安全设置,因此不会在 elasticsearch.yml
的 realm 配置中定义,而是添加到 elasticsearch 密钥库中。例如
bin/elasticsearch-keystore add xpack.security.authc.realms.oidc.oidc1.rp.client_secret
更改 client_secret
需要重新启动 Elasticsearch 节点以应用更改。
根据OpenID Connect规范,OP还应在其已知的URL上提供其配置,该URL是其Issuer
值与.well-known/openid-configuration
字符串的连接。例如:https://op.org.com/.well-known/openid-configuration
该文档应包含在Elasticsearch中配置OpenID Connect领域所需的所有必要信息。
声明映射
edit声明和范围
edit当使用 OpenID Connect 进行 Kibana 身份验证时,OP 将以 OpenID Connect Claims 的形式提供用户信息,这些信息可以包含在 ID Token 中,或者从 OP 的 UserInfo 端点获取。声明(claim)被定义为由 OP 为已验证用户断言的信息片段。简单来说,声明是一个包含用户信息的名/值对。与声明相关,我们还有 OpenID Connect 范围(Scopes)的概念。范围是用于请求访问特定声明列表的标识符。标准定义了一组可以请求的范围标识符。唯一强制性的是 openid
,而常用的包括 profile
和 email
。profile
范围请求访问 name
、family_name
、given_name
、middle_name
、nickname
、preferred_username
、profile
、picture
、website
、gender
、birthdate
、zoneinfo
、locale
和 updated_at
声明。email
范围请求访问 email
和 email_verified
声明。流程是 RP 在身份验证请求期间请求特定的范围。如果 OP 隐私政策允许并且验证用户同意,则相关声明将返回给 RP(无论是 ID Token 还是 UserInfo 响应)。
支持的声明列表会因您使用的OP而异,但您可以预期标准声明会得到广泛支持。
将声明映射到用户属性
edit声明映射的目标是配置 Elasticsearch,以便能够将指定返回声明的值映射到 Elasticsearch 支持的 用户属性之一。这些用户属性随后用于在 Kibana UI 或审计日志中识别用户,并且还可以用于创建 角色映射规则。
配置OpenID Claims映射的推荐步骤如下:
- 查阅您的OP配置,了解它可能支持哪些声明。请注意,OP的元数据或配置页面中提供的列表是可能支持的声明列表。然而,出于隐私原因,它可能不是一个完整的列表,或者并非所有支持的声明都适用于所有经过身份验证的用户。
-
浏览Elasticsearch支持的用户属性列表,并决定哪些对您有用,并且可以以声明的形式由您的OP提供。至少,需要
principal
用户属性。 -
配置您的OP以“释放”这些声明到您的Elastic Stack依赖方。此过程因提供商而异。您可以使用静态配置,而其他提供商则支持依赖方在身份验证时请求与要“释放”的声明相对应的范围。有关如何配置要请求的范围的详细信息,请参见
rp.requested_scopes
。为了确保互操作性并最小化错误,您应该仅请求OP支持的范围,并且您打算将其映射到Elasticsearch用户属性。注意:您只能映射值为字符串、数字、布尔值或上述类型的数组的声明。
-
在Elasticsearch中配置OpenID Connect领域,以将Elasticsearch用户属性(参见 列表)与您的OP将发布的声明名称关联起来。在上面的示例中,我们已将
principal
和groups
用户属性配置如下:-
claims.principal: sub
: 这指示Elasticsearch在OP为用户发布的ID令牌(或在UserInfo响应中)中查找名为sub
的OpenID Connect声明,并将此声明的值分配给principal
用户属性。sub
是用于principal属性的常用声明,因为它是OP中用户的标识符,并且也是ID令牌的必需声明,因此提供了它将可用的保证。然而,这里仅作为示例使用,OP可能会提供另一个更适合您需求的声明。 -
claims.groups: "http://example.info/claims/groups"
: 同样,这指示Elasticsearch查找名为http://example.info/claims/groups
的声明(请注意,这是一个URI - 一个标识符,被视为字符串而不是指向将检索的位置的URL),无论是在ID令牌中还是在UserInfo响应中,并将其值映射到Elasticsearch中的用户属性groups
。规范中没有用于表示经过身份验证用户在OP中的角色或组成员资格的标准声明,因此此处应映射的声明名称在提供商之间会有很大差异。有关更多详细信息,请查阅您的OP文档。
-
Elasticsearch 用户属性
editElasticsearch OpenID Connect 领域可以配置为将 OpenID Connect 声明映射到经过身份验证的用户上的以下属性:
- principal
-
(必需)
这是将应用于与此领域进行身份验证的用户的用户名。
principal
出现在 Elasticsearch 审计日志等地方。
如果principal属性未能从声明中映射,则身份验证失败。
- groups
-
(推荐)
如果您希望使用您的 OP 的组或角色概念作为用户 Elasticsearch 权限的基础,您应该使用此属性进行映射。
groups
会直接传递给您的 角色映射规则。 - name
- (可选) 用户的完整姓名。
- (可选) 用户的电子邮件地址。
- dn
- (可选) 用户的X.500 可分辨名称。
从OpenID Connect声明中提取部分值
edit有些情况下,声明的值可能包含比您希望在 Elasticsearch 中使用的更多信息。一个常见的例子是,OP 仅使用电子邮件地址,但您希望用户的 principal
使用电子邮件地址的 local-name 部分。例如,如果他们的电子邮件地址是 james.wong@staff.example.com
,那么您希望他们的 principal 简单地是 james.wong
。
这可以通过在 Elasticsearch 领域中使用 claim_patterns
设置来实现,如下面的领域配置所示:
xpack.security.authc.realms.oidc.oidc1: order: 2 rp.client_id: "the_client_id" rp.response_type: code rp.redirect_uri: "https://kibana.example.org:5601/api/security/oidc/callback" op.authorization_endpoint: "https://op.example.org/oauth2/v1/authorize" op.token_endpoint: "https://op.example.org/oauth2/v1/token" op.userinfo_endpoint: "https://op.example.org/oauth2/v1/userinfo" op.endsession_endpoint: "https://op.example.org/oauth2/v1/logout" op.issuer: "https://op.example.org" op.jwkset_path: oidc/jwkset.json claims.principal: email_verified claim_patterns.principal: "^([^@]+)@staff\\.example\\.com$"
在这种情况下,用户的principal
是从email_verified
声明映射的,但在将其分配给用户之前,会对该值应用一个正则表达式。如果正则表达式匹配,则使用第一个组的结果作为有效值。如果正则表达式不匹配,则声明映射失败。
在这个例子中,电子邮件地址必须属于 staff.example.com
域,
然后本地部分(@
之前的任何内容)被用作主体。
任何尝试使用不同电子邮件域登录的用户都将失败,因为正则表达式不会匹配他们的电子邮件地址,因此他们
的主体用户属性(这是强制性的)将不会被填充。
这些正则表达式中的小错误可能会带来严重的安全后果。例如,如果我们不小心遗漏了上面的例子中的结尾$
,那么我们将匹配任何域名以staff.example.com
开头的电子邮件地址,这将接受诸如admin@staff.example.com.attacker.net
这样的电子邮件地址。确保您的正则表达式尽可能精确是非常重要的,这样您就不会无意中为用户的冒充攻击打开一个途径。
第三方发起的单点登录
editElasticsearch 中的 Open ID Connect 领域支持第三方发起的登录,如相关规范中所述。
这允许OP本身或另一个不同于RP的第三方,在请求使用OP进行身份验证时启动身份验证过程。请注意,为了使此过程成功,Elastic Stack RP应已为此OP配置。
OpenID Connect 注销
editElasticsearch 中的 OpenID Connect 领域支持 RP 发起的注销功能,如 规范的相关部分所述
在这个过程中,OpenID Connect RP(在此情况下为Elastic Stack)将在成功完成本地注销后,将用户的浏览器重定向到OP的预定义URL。根据配置,OP随后也可以注销用户,并最终将用户重定向回RP。领域配置中的op.endsession_endpoint
决定了浏览器将被重定向到的OP中的URL。rp.post_logout_redirect_uri
设置决定了在OP注销用户后重定向用户的URL。
在配置rp.post_logout_redirect_uri
时,应注意不要将其指向会触发用户重新认证的URL。例如,当使用OpenID Connect支持Kibana的单点登录时,可以将其设置为${kibana-url}/security/logged_out
,这将向用户显示一条友好的消息,或者设置为${kibana-url}/login?msg=LOGGED_OUT
,这将把用户带到Kibana的登录选择器。
OpenID Connect 领域 SSL 配置
editOpenID Connect 依赖于 TLS 来提供诸如传输加密和端点认证等安全特性。RP 需要与 OP 建立后端通信,以便在授权码授予流程中交换代码以获取 ID Token,并从 UserInfo 端点获取额外的用户信息。此外,如果您将 op.jwks_path
配置为 URL,Elasticsearch 将需要从托管在该位置的文件中获取 OP 的签名密钥。因此,确保 Elasticsearch 能够验证并信任 OP 用于 TLS 的服务器证书非常重要。由于系统信任库用于传出 https 连接的客户端上下文,如果您的 OP 使用的是受信任 CA 颁发的证书,则无需额外配置。
然而,如果您的OP证书的颁发者未被Elasticsearch运行的JVM所信任(例如,它使用了一个组织CA),那么您必须配置Elasticsearch以信任该CA。假设您已将签署OP用于TLS的证书的CA证书存储在Elasticsearch配置目录中的/oidc/company-ca.pem文件中,您需要在领域配置中设置以下属性:
xpack.security.authc.realms.oidc.oidc1: order: 1 ... ssl.certificate_authorities: ["/oidc/company-ca.pem"]
配置角色映射
edit当用户使用OpenID Connect进行身份验证时,他们会被识别到Elastic Stack,但这并不自动授予他们执行任何操作或访问任何数据的权限。
您的 OpenID Connect 用户在被分配角色之前无法执行任何操作。这可以通过 添加角色映射 API 或使用 授权领域 来完成。
您不能使用角色映射文件 来授予通过OpenID Connect进行身份验证的用户角色。
这是一个简单的角色映射示例,它将 example_role
角色授予任何针对 oidc1
OpenID Connect 领域进行身份验证的用户:
PUT /_security/role_mapping/oidc-example { "roles": [ "example_role" ], "enabled": true, "rules": { "field": { "realm.name": "oidc1" } } }
通过领域配置映射的用户属性用于处理角色映射规则,这些规则决定了用户被授予哪些角色。
提供给角色映射的用户字段是从OpenID Connect声明中派生出来的,如下所示:
-
username
: 用户属性principal
-
dn
: 用户属性dn
-
groups
: 用户属性groups
-
metadata
: 参见 用户元数据
有关更多信息,请参阅用户和组到角色的映射以及 角色映射。
如果你的OP能够通过使用OpenID Claim向RPs提供组或角色,那么你应该将此声明映射到Elasticsearch领域中的claims.groups
设置(参见将声明映射到用户属性),然后按照以下示例在角色映射中使用它。
此映射授予通过 oidc1
领域进行身份验证并属于 finance-team
组的任何用户 Elasticsearch finance_data
角色。
PUT /_security/role_mapping/oidc-finance { "roles": [ "finance_data" ], "enabled": true, "rules": { "all": [ { "field": { "realm.name": "oidc1" } }, { "field": { "groups": "finance-team" } } ] } }
如果您的用户也存在于可以直接被Elasticsearch访问的存储库中(例如LDAP目录),那么您可以使用授权领域,而不是角色映射。
在这种情况下,您执行以下步骤:
-
在您的OpenID Connect领域中,通过配置
claims.principal
设置,分配一个声明作为查找用户ID。 -
创建一个新的领域,可以从您的本地存储库(例如
ldap
领域)中查找用户。 -
在您的OpenID Connect领域中,将
authorization_realms
设置为您在步骤2中创建的领域的名称。
用户元数据
edit默认情况下,通过 OpenID Connect 进行身份验证的用户将具有一些额外的元数据字段。这些字段将包括身份验证响应中提供的每个 OpenID 声明(无论是否映射到 Elasticsearch 用户属性)。例如,在元数据字段 oidc(claim_name)
中,"claim_name" 是声明的名称,如它在 ID 令牌或用户信息响应中所包含的那样。请注意,这些将包括与身份验证事件相关的所有 ID 令牌声明,而不是用户本身。
可以通过在oidc领域中添加populate_user_metadata: false
作为设置来禁用此行为。
配置 Kibana
edit在Kibana中使用OpenID Connect进行身份验证需要一些额外的设置,除了标准的Kibana安全配置之外。 Kibana安全文档 提供了您可以应用的可用配置选项的详细信息。
特别是,由于您的 Elasticsearch 节点已配置为在 HTTP 接口上使用 TLS,您必须配置 Kibana 使用 https
URL 连接到 Elasticsearch,并且您可能需要配置 elasticsearch.ssl.certificateAuthorities
以信任 Elasticsearch 已配置使用的证书。
Kibana中的OpenID Connect认证受以下kibana.yml
中的超时设置影响:
您可能希望根据您的安全要求调整这些超时设置。
支持OpenID Connect所需的三个附加设置如下所示:
xpack.security.authc.providers: oidc.oidc1: order: 0 realm: "oidc1"
上述示例中使用的配置值如下:
-
xpack.security.authc.providers
-
添加
oidc
提供者以指示 Kibana 使用 OpenID Connect 单点登录作为身份验证方法。这指示 Kibana 在用户尝试访问 Kibana 中的 URL 时,如果用户尚未经过身份验证,则尝试启动 SSO 流程。如果您还希望允许用户使用用户名和密码登录,则还必须启用basic
身份验证提供者。例如:
xpack.security.authc.providers: oidc.oidc1: order: 0 realm: "oidc1" basic.basic1: order: 1
这将允许尚未通过 OpenID Connect 进行身份验证的用户使用 Kibana 登录表单进行登录。
-
xpack.security.authc.providers.oidc.<provider-name>.realm
- Elasticsearch中处理此Kibana实例身份验证的OpenID Connect领域的名称。
不使用 Kibana 的 OpenID Connect
editOpenID Connect 领域旨在允许用户向 Kibana 进行身份验证,因此,上述指南的大部分内容都假设使用 Kibana。本节描述了自定义 Web 应用程序如何使用相关的 OpenID Connect REST API 来通过 OpenID Connect 对用户进行 Elasticsearch 身份验证。
单点登录领域如 OpenID Connect 和 SAML 利用 Elasticsearch 中的 Token Service,原则上将 SAML 或 OpenID Connect 身份验证响应交换为 Elasticsearch 访问令牌和刷新令牌。访问令牌用作后续调用 Elasticsearch 的凭证。刷新令牌使用户能够在当前令牌过期后获取新的 Elasticsearch 访问令牌。
Elasticsearch Token Service 可以被视为一个最小的 oAuth2 授权服务器, 上面提到的访问令牌和刷新令牌是仅与此授权服务器相关的令牌。它们仅由 Elasticsearch 生成和使用, 与 OpenID Connect Provider 颁发的令牌(访问令牌和 ID 令牌)没有任何关系。
在OpenID Connect提供商处注册RP
edit依赖方(Elasticsearch 和自定义 Web 应用)需要注册为 OpenID Connect 提供商的客户端。请注意,在注册 重定向 URI
时,它需要是自定义 Web 应用中的一个 URL。
OpenID Connect 领域
edit需要创建并配置一个OpenID Connect领域在Elasticsearch中。请参阅配置Elasticsearch以进行OpenID Connect身份验证
用于访问API的服务帐户用户
edit领域的设计基于一个假设,即需要有一个特权实体作为认证代理。在这种情况下,自定义Web应用程序是处理最终用户认证(更准确地说,“委托”认证给OpenID Connect提供者)的认证代理。OpenID Connect API需要认证以及认证用户所需的必要授权级别。因此,需要创建一个服务账户用户并分配一个角色,赋予他们manage_oidc
集群权限。在认证完成后,使用manage_token
集群权限将是必要的,以便用户可以保持访问或随后被注销。
POST /_security/role/facilitator-role { "cluster" : ["manage_oidc", "manage_token"] }
POST /_security/user/facilitator { "password" : "<somePasswordHere>", "roles" : [ "facilitator-role"] }
处理身份验证流程
edit在高层次上,自定义Web应用程序需要执行以下步骤,以便使用OpenID Connect对用户进行身份验证:
-
向
_security/oidc/prepare
发起 HTTP POST 请求,以facilitator
用户身份进行身份验证,并在请求体中使用 Elasticsearch 配置中的 OpenID Connect realm 名称。更多详情,请参阅 OpenID Connect 准备身份验证 API。POST /_security/oidc/prepare { "realm" : "oidc1" }
-
处理对
/_security/oidc/prepare
的响应。Elasticsearch 的响应将包含 3 个参数:redirect
、state
、nonce
。自定义 Web 应用程序需要将state
和nonce
的值存储在用户的会话中(客户端在 cookie 中或服务器端,如果会话信息以这种方式持久化),并将用户的浏览器重定向到redirect
值中包含的 URL。 -
处理来自 OP 的后续响应。在用户成功通过 OpenID Connect Provider 认证后,他们将被重定向回回调/重定向 URI。在接收到此 HTTP GET 请求后,自定义 Web 应用程序需要再次以
facilitator
用户身份向_security/oidc/authenticate
发出 HTTP POST 请求,传递用户浏览器被重定向到的 URL 作为参数,以及之前在用户会话中保存的nonce
和state
值。如果配置了多个 OpenID Connect 领域,自定义 Web 应用程序可以指定用于处理此请求的领域名称,但此参数是可选的。有关更多详细信息,请参阅 OpenID Connect authenticate。POST /_security/oidc/authenticate { "redirect_uri" : "https://oidc-kibana.elastic.co:5603/api/security/oidc/callback?code=jtI3Ntt8v3_XvcLzCFGq&state=4dbrihtIAt3wBTwo6DxK-vdk-sSyDBV8Yf0AjdkdT5I", "state" : "4dbrihtIAt3wBTwo6DxK-vdk-sSyDBV8Yf0AjdkdT5I", "nonce" : "WaBPH0KqPVdG5HHdSxPRjfoZbXMCicm5v1OiAj0DUFM", "realm" : "oidc1" }
Elasticsearch 将验证这一点,如果一切正确,将响应一个可以作为
Bearer
令牌用于后续请求的访问令牌,以及一个可以在以后用于刷新给定访问令牌的刷新令牌,如 获取令牌 中所述。 -
在必要时,自定义 Web 应用程序可以通过使用 OIDC logout API 并传递访问令牌和刷新令牌作为参数来注销用户。例如:
POST /_security/oidc/logout { "token" : "dGhpcyBpcyBub3QgYSByZWFsIHRva2VuIGJ1dCBpdCBpcyBvbmx5IHRlc3QgZGF0YS4gZG8gbm90IHRyeSB0byByZWFkIHRva2VuIQ==", "refresh_token": "vLBPvmAB6KvwvJZr27cS" }
如果领域配置得当,这可能会导致返回一个包含
redirect
参数的响应,指示用户需要在 OP 中重定向到哪里以完成注销过程。