用户认证

edit

身份验证用于识别个人。为了访问受限资源,用户必须通过密码、凭证或其他方式(通常称为身份验证令牌)证明其身份。

Elastic Stack 通过识别请求到达集群的用户并验证他们是否是他们所声称的人来进行用户认证。认证过程由一个或多个称为领域的认证服务处理。

您可以使用本机支持来管理和验证用户,或与外部用户管理系统(如LDAP和Active Directory)集成。

Elastic Stack 安全功能提供了内置的领域,如 nativeldapactive_directorypkifilesamlkerberosoidcjwt。如果 这些内置领域都不符合您的需求,您还可以构建自己的 自定义领域并将其插入到 Elastic Stack 中。

当启用安全功能时,根据您配置的领域,您必须将用户凭据附加到发送给Elasticsearch的请求中。例如,当使用支持用户名和密码的领域时,您可以简单地将基本认证头附加到请求中。

安全功能提供两种服务:令牌服务和API密钥服务。您可以使用这些服务将当前的身份验证交换为令牌或密钥。然后,此令牌或密钥可以用作身份验证新请求的凭据。 API密钥服务默认启用。 当为HTTP启用TLS/SSL时,令牌服务默认启用。

内置用户

edit

Elastic 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_agentremote_monitoring_collector角色。

内置用户的工作原理

edit

这些内置用户存储在一个特殊的 .security 索引中,该索引由 Elasticsearch 管理。如果内置用户被禁用或其密码更改,更改会自动反映在集群中的每个节点上。然而,如果你的 .security 索引被删除或从快照中恢复,你应用的任何更改都将丢失。

尽管它们共享相同的API,内置用户与由本地领域管理的用户是分开且不同的。禁用本地领域不会对内置用户产生任何影响。可以使用禁用用户API单独禁用内置用户。

Elastic 引导密码

edit

当您安装 Elasticsearch 时,如果 elastic 用户还没有密码, 它会使用默认的引导密码。引导密码是一个临时的 密码,使您能够运行设置所有内置用户密码的工具。

默认情况下,引导密码是从一个随机化的 keystore.seed 设置中派生的,该设置在安装期间被添加到密钥库中。您不需要知道或更改此引导密码。如果您在密钥库中定义了 bootstrap.password 设置,则将使用该值。有关与密钥库交互的更多信息,请参阅 安全设置

在您为内置用户设置密码,特别是为elastic用户设置密码后,引导密码将不再有进一步的用途。

设置内置用户密码

edit

您必须为所有内置用户设置密码。

使用 elasticsearch-setup-passwords 工具是为内置用户首次设置密码的最简单方法。它使用 elastic 用户的引导密码来运行用户管理 API 请求。例如,您可以在“交互”模式下运行该命令,该模式会提示您为 elastickibana_systemlogstash_systembeats_systemapm_systemremote_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_systemremote_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

服务账户

edit

Elastic 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 EnterpriseElastic 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"
}

服务账号令牌的名称。

服务账户令牌的类型。该值始终以_service_account_开头,后跟一个表示所使用的服务令牌后端的字符串(可以是fileindex)。

内部用户

edit

这些用户仅用于 Elasticsearch 的内部使用。不支持使用这些用户进行身份验证。

Elastic Stack 安全功能使用八个内部用户(_system_xpack_xpack_security_async_search_security_profile_data_stream_lifecycle_synonyms_storage), 这些用户负责在 Elasticsearch 集群内部进行的操作。

这些用户仅用于源自集群内部的请求。因此,它们不能用于对API进行身份验证,并且没有需要管理或重置的密码。

偶尔你可能会在你的日志中看到这些用户之一的引用,包括审计日志

基于令牌的身份验证服务

edit

Elastic 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-serviceapi-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

您可以在单个用户的多个领域中使用相同的用户名。在Elasticsearch中,两个不同的领域可以使用相同的用户名和不同的角色来验证用户。Elasticsearch默认情况下不会假设这些用户是同一个人,而是将他们视为具有不同用户配置文件的独立个体。

对于一个个体可以针对多个领域进行认证的用例,您可以使用安全域功能,以便这些不同的用户被视为相同的身份并共享一个用户配置文件。

创建和管理用户档案

edit

要创建新用户配置文件或更新现有配置文件,请使用激活用户配置文件API。当您提交请求时,Elasticsearch会尝试为指定用户查找现有的配置文件文档。如果不存在,Elasticsearch会创建一个新的配置文件文档。

无论哪种情况,配置文件文档都会捕获用户的full_nameemailrolesrealms,还包括配置文件的唯一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
  • 创建新的用户配置文件需要用户的身份验证详细信息 (usernamepassword 或其 OAuth2访问令牌)。 这意味着用户必须至少进行一次身份验证才能创建用户配置文件。从未向Kibana (或其他支持配置文件的应用程序)进行身份验证的用户将没有用户配置文件,并且 建议用户配置文件API 不会为这些用户返回任何结果。
  • 用户配置文件适用于交互式用户,例如与Kibana交互的人类用户。因此,用户配置文件不支持API密钥或服务账户

    OAuth2令牌表示交互式最终用户是受支持的。

领域

edit

Elastic 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 的安全功能管理。每个内部领域类型最多只能配置一个领域。安全功能提供了两种内部领域类型:nativefile
External
需要与Elasticsearch外部的各方/组件进行交互的领域,通常与企业级身份管理系统进行交互。与内部领域不同,可以有任意数量的外部领域 - 每个领域都有其独特的名称和配置。安全功能提供了以下外部领域类型:ldapactive_directorysamlkerberospki

领域链

edit

领域存在于一个领域链中。它本质上是一个配置领域的优先级列表(通常是各种类型的领域)。领域按照升序进行咨询(也就是说,具有最低order值的领域首先被咨询)。你必须确保每个配置的领域都有一个独特的order设置。如果两个或多个领域具有相同的order,节点将无法启动。

在认证过程中,Elastic Stack 安全功能会依次咨询并尝试在每个领域中认证请求。一旦其中一个领域成功认证了请求,认证就被认为是成功的。认证的用户与请求相关联,然后请求进入授权阶段。如果一个领域无法认证请求,链中的下一个领域将被咨询。如果链中的所有领域都无法认证请求,认证就被认为是不成功的,并返回一个认证错误(作为 HTTP 状态码 401)。

某些系统(例如 Active Directory)在连续多次登录失败后会有一个临时锁定期。如果同一用户名存在于多个领域,可能会导致无意的账户锁定。更多信息,请参见 用户频繁被锁定在 Active Directory 中

默认的领域链包含filenative领域。要显式配置领域链,您可以在elasticsearch.yml文件中指定链。如果您的领域链不包含filenative领域,或者没有显式禁用它们,filenative领域将按此顺序自动添加到领域链的开头。要选择退出自动行为,您可以使用orderenabled设置显式配置filenative领域。

以下代码片段配置了一个领域链,启用了文件领域以及两个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密钥。

跨域资源共享

edit

Elasticsearch 中某些类型的资源归单个用户所有,例如 异步搜索上下文API 密钥用户配置文件。当用户创建资源时,Elasticsearch 会捕获用户的用户名和领域信息作为资源元数据的一部分。同样,如果用户更新资源(例如 API 密钥), Elasticsearch 会自动重新捕获用户的当前领域信息。

当用户稍后尝试访问资源时,Elasticsearch 会将捕获的用户名和领域信息与访问用户的用户名和领域信息进行比较。除非领域和用户名都匹配,否则 Elasticsearch 将拒绝访问。如果 Elasticsearch 检测到来自两个不同领域的用户名尝试访问资源,Elasticsearch 会假设这些用户是不同的,并且不允许这些用户之间共享资源。

然而,有些情况下,同一个用户可以通过多个领域进行身份验证,并且需要在不同领域之间共享同一组资源。例如,LDAP领域SAML领域可以由同一个目录服务支持。此外,授权委托允许一个领域将授权委托给另一个领域。如果两个领域都使用相同的用户名对用户进行身份验证,那么从资源所有权的角度来看,将这些用户视为同一个用户是合理的。

安全域通过将这些领域分组在同一域下,使得跨领域的资源共享成为可能。Elasticsearch始终强制执行与当前认证用户相关的权限,这在使用安全域时仍然适用。当资源共享需要时,安全域不会绕过用户授权。例如,用户需要manage_own_api_key权限来管理他们自己的API密钥。如果该用户在通过一个领域认证时没有此权限,他们在通过另一个领域认证时将无法管理API密钥。

跨领域管理角色

edit

Elasticsearch 提供了多种方法来在多个领域中一致地应用角色。例如,您可以使用 授权委托来 确保用户从多个领域中分配到相同的角色。您还可以 手动配置由同一目录服务支持的多个领域。 尽管在通过不同领域进行身份验证时可以为同一用户配置不同的角色,但这推荐。

配置安全域

edit

安全域是一个需要仔细配置的高级功能。配置错误或误用可能导致意外行为。

安全域必须在集群中的所有节点上一致配置。 配置不一致可能导致以下问题:

  • 重复的用户配置文件
  • 根据认证节点的配置,资源的所有权不同

配置安全域:

  1. elasticsearch.yml 文件的 xpack.security.authc.domains 命名空间中添加安全域配置:

    xpack:
      security:
        authc:
          domains:
            my_domain:
              realms: [ 'default_native', 'saml1' ] 

    此配置定义了一个名为 my_domain 的安全域,其中包含两个名为 default_nativesaml1 的领域。

    指定的 realms 必须在 elasticsearch.yml 中定义,但不需要启用。

    基于文件的用户认证和本地用户认证会分别自动启用为default_filedefault_native,无需任何显式配置。即使它们未在elasticsearch.yml中显式定义,您也可以在域下列出这些领域。

  2. 重启 Elasticsearch。

    如果域配置无效,Elasticsearch 可能无法启动,例如:

    • 同一个领域在多个域下配置。
    • 任何未定义的领域、合成领域或保留领域被配置为在域下。
  3. 在执行与安全域相关的操作之前,请在集群中的所有节点上应用相同的配置,包括创建和管理资源,如用户配置文件API密钥异步搜索

    在向安全域添加领域时,避免在更改完全应用到所有节点之前使用新添加的领域进行身份验证。

从安全域中移除领域

edit

从安全域中移除领域可能会导致意外行为,因此不建议这样做。 在移除之前创建或更新的资源可能由不同用户拥有,具体取决于资源类型:

  • 用户配置文件 属于最后 激活 该配置文件的用户。 对于其领域不再与所有者用户在同一域中的用户,下次调用激活用户配置文件 API 时,将为其创建一个新的用户配置文件。
  • API 密钥属于最初 创建 或最后 更新 它的用户。 包括 API 密钥的原始创建者在内的用户,如果他们的领域不再与当前 API 密钥所有者的领域在同一域中,将失去所有权。
  • 异步搜索上下文等资源属于最初创建它们的用户。

与其删除领域,不如考虑禁用它们并将它们作为安全域的一部分保留。 在任何情况下,跨领域资源共享仅在用户使用相同用户名时才可能实现。

Active Directory 用户身份验证

edit

您可以配置 Elastic Stack 安全功能以与 Active Directory 通信以验证用户。请参阅 配置 Active Directory 领域

安全功能使用 LDAP 与 Active Directory 进行通信,因此 active_directory 领域类似于 ldap 领域。与 LDAP 目录类似,Active Directory 以层次结构存储用户和组。目录的层次结构由容器构建,例如 组织单位ou)、组织o)和 域组件dc)。

条目的路径是一个专有名称(DN),用于唯一标识用户或组。用户和组名通常具有诸如通用名称cn)或唯一IDuid)等属性。DN被指定为一个字符串,例如"cn=admin,dc=example,dc=com"(空格被忽略)。

安全功能仅支持Active Directory安全组。您不能将通讯组映射到角色。

当您使用 Active Directory 进行身份验证时,用户输入的用户名应与 sAMAccountNameuserPrincipalName 匹配,而不是通用名称。

Active Directory 领域使用 LDAP 绑定请求来验证用户。在验证用户后,领域会在 Active Directory 中搜索以找到用户的条目。一旦找到用户,Active Directory 领域就会从用户条目中的 tokenGroups 属性中检索用户的组成员身份。

配置Active Directory领域

edit

要与Active Directory集成,您需要配置一个active_directory领域,并将Active Directory用户和组映射到角色映射文件中的角色。

  1. elasticsearch.yml 文件的 xpack.security.authc.realms.active_directory 命名空间下添加一个类型为 active_directory 的领域配置。 至少,您必须指定 Active Directory 的 domain_nameorder

    请参阅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 

    领域顺序控制了在验证用户时,配置的领域被检查的顺序。

    如果你不指定URL,它默认使用ldap::389

    当您在 elasticsearch.yml 中配置领域时,仅使用您指定的领域进行身份验证。如果您还想使用 nativefile 领域,则必须将它们包含在领域链中。

  2. 如果您在林中的多个域中进行用户身份验证,则需要额外的步骤。配置和用户身份验证的方式有一些细微的差异。

    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名称中检索域名。

  3. (可选) 配置 Elasticsearch 如何与多个 Active Directory 服务器交互。

    可以在领域级别使用load_balance.type设置。支持两种操作模式:故障转移和负载均衡。请参阅Active Directory realm settings

  4. (可选) 为了保护密码, 加密 Elasticsearch 和 Active Directory 服务器之间的通信
  5. 重启 Elasticsearch。
  6. (可选) 配置一个绑定用户。

    Active Directory 领域使用 LDAP 绑定请求来验证用户。默认情况下,所有 LDAP 操作都由 Elasticsearch 正在验证的用户执行。在某些情况下,普通用户可能无法访问 Active Directory 中的所有必要项目,因此需要一个 绑定用户。可以配置绑定用户,并用于执行除 LDAP 绑定请求之外的所有操作,该请求是验证用户提供的凭据所必需的。

    使用绑定用户可以启用 run as 功能与 Active Directory 领域一起使用,并能够维护一组与 Active Directory 的池化连接。这些池化连接减少了每次用户认证时必须创建和销毁的资源数量。

    以下示例展示了通过使用bind_dnsecure_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 

    这是所有Active Directory搜索请求执行时所使用的用户。 如果没有配置绑定用户,所有请求将以与Elasticsearch进行身份验证的用户身份运行。

    应通过将适当的 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 设置来禁用连接池。

  7. 将Active Directory用户和组映射到角色。

    领域认证过程中的一个重要部分是解析与已认证用户相关的角色。角色定义了用户在集群中的权限。

    由于使用 active_directory 领域时,用户在外部的 Active Directory 服务器上进行管理,因此期望他们的角色也在那里进行管理。事实上,Active Directory 支持组的概念,这些组通常代表组织中不同系统的用户角色。

    通过 active_directory 领域,您可以将 Active Directory 用户映射到角色,通过他们的 Active Directory 组或其他元数据。这种角色映射可以通过 角色映射 API 或通过存储在每个节点上的文件进行配置。当用户针对 Active Directory 领域进行身份验证时,该用户的权限是用户映射到的所有角色定义的权限的并集。

    在映射定义中,您可以使用其专有名称指定组。例如,以下映射配置将Active Directory的admins组映射到monitoringuser角色,将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
    }

    Active Directory 中 admins 组的专有名称 (DN)。

    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 识别名称(DN)。

    用户的 Active Directory 识别名 (DN) John Doe

    或者,也可以通过角色映射文件进行配置:

    monitoring: 
      - "cn=admins,dc=example,dc=com" 
    user:
      - "cn=users,dc=example,dc=com" 
      - "cn=admins,

Active Directory 领域中的用户元数据

edit

当用户通过Active Directory领域进行身份验证时,用户的元数据中会填充以下属性:

字段

描述

ldap_dn

用户的唯一标识名称。

ldap_groups

为该用户解析的每个组的专有名称(无论这些组是否映射到角色)。

此元数据在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证书。

  1. elasticsearch.yml文件中为xpack.security.authc.realms命名空间创建领域配置。请参阅配置Active Directory领域
  2. 在领域配置中设置url属性,以指定LDAPS协议和安全端口号。例如,url: ldaps://ad.example.com:636
  3. 配置每个节点以信任由签署您的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领域设置

  4. 重启Elasticsearch。

默认情况下,当您配置 Elasticsearch 以使用 SSL/TLS 连接到 Active Directory 时,它会尝试验证证书中的主机名或 IP 地址与 realm 配置中 url 属性指定的值是否匹配。如果证书中的值与 realm 配置中的值不匹配,Elasticsearch 将不允许连接到 Active Directory 服务器。这是为了防止中间人攻击。如果需要,您可以通过将 ssl.verification_mode 属性设置为 certificate 来禁用此行为。

基于文件的用户认证

edit

您可以使用内置的 file 领域来管理和认证用户。 通过 file 领域,用户在集群中的每个节点上的本地文件中定义。

作为集群的管理员,您的责任是确保在集群的每个节点上定义相同的用户。Elastic Stack 的安全功能并不提供任何机制来保证这一点。您还应该注意,无法通过 用户 APIfile 领域中添加或管理用户,也无法在 Kibana 的 管理 / 安全 / 用户 页面上添加或管理它们。

文件领域(file realm)非常有用,可以作为备用或恢复领域。例如,在集群无响应或安全索引不可用的情况下,或者当你忘记了管理用户的密码时。在这种情况下,文件领域是一个方便的解决方案——你可以在文件领域中定义一个新的管理用户(admin),并使用它登录以重置所有其他用户的凭证。

要定义用户,安全功能提供了 users 命令行工具。该工具使您能够添加 和删除用户、分配用户角色以及管理用户密码。

配置文件领域

edit

您不需要显式配置file领域。默认情况下,filenative领域会自动添加到领域链中。除非另有配置,否则file领域会首先添加,然后是native领域。

虽然可以定义其他领域的多个实例,但每个节点只能定义一个 文件领域。

关于file领域中所有用户的数据存储在集群中每个节点的两个文件中:usersusers_roles。这两个文件都位于ES_PATH_CONF中,并在启动时读取。

文件usersusers_roles由节点在本地管理,并且不由集群全局管理。这意味着在典型的多节点集群中,需要在集群中的每个节点上应用完全相同的更改。

一个更安全的方法是在其中一个节点上应用更改,并将文件分发或复制到集群中的所有其他节点(无论是手动操作还是使用Puppet或Chef等配置管理系统)。

  1. (可选) 在 elasticsearch.yml 文件的 xpack.security.authc.realms.file 命名空间下添加一个领域配置。至少,您必须设置领域的 order 属性。

    例如,以下代码片段展示了一个file领域配置,将order设置为零,以便首先检查该领域:

    xpack:
      security:
        authc:
          realms:
            file:
              file1:
                order: 0

    您只能在 Elasticsearch 节点上配置一个文件领域。

  2. 重启 Elasticsearch。
  3. 将用户信息添加到集群中每个节点上的 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 安全功能不提供任何机制来保证这一点。

  4. 在集群中的每个节点上,将角色信息添加到ES_PATH_CONF/users_roles文件中。

    The users_roles 文件存储与用户关联的角色。例如:

    admin:rdeniro
    power_user:alpacino,jacknich
    user:jacknich

    每一行将一个角色映射到一个逗号分隔的与该角色关联的所有用户的列表。

    您可以使用elasticsearch-users工具来更新此文件。您必须确保在集群中的每个节点上都进行相同的更改。

  5. (可选) 更改检查 usersusers_roles 文件的频率。

    默认情况下,Elasticsearch 每 5 秒检查这些文件的更改。您可以通过更改 elasticsearch.yml 文件中的 resource.reload.interval.high 设置来改变此默认行为(由于这是 Elasticsearch 中的一个常见设置,更改其值可能会影响系统中的其他调度)。

LDAP 用户认证

edit

您可以配置 Elastic Stack 安全功能,以便与轻量级目录访问协议 (LDAP) 服务器通信以进行用户身份验证。请参阅 配置 LDAP 领域

LDAP 以分层方式存储用户和组,类似于文件系统中文件夹的分组方式。LDAP 目录的层次结构由容器构建,例如组织单元ou)、组织o)和域组件dc)。

条目的路径是一个专有名称(DN),用于唯一标识用户或组。用户和组名通常具有诸如通用名称cn)或唯一IDuid)等属性。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 组映射到用户角色。

  1. 确定您要使用的模式。ldap 领域支持两种操作模式,一种是用户搜索模式,另一种是具有特定用户DN模板的模式。

    LDAP 用户搜索是最常见的操作模式。在这种模式下,使用一个具有搜索 LDAP 目录权限的特定用户来根据提供的用户名和 LDAP 属性搜索认证用户的 DN。一旦找到,用户将通过尝试使用找到的 DN 和提供的密码绑定到 LDAP 服务器来进行认证。

    如果您的 LDAP 环境使用一些特定的标准命名条件来标识用户,您可以使用用户 DN 模板来配置领域。这种方法的优点是无需执行搜索即可找到用户 DN。然而,可能需要多次绑定操作才能找到正确的用户 DN。

  2. 配置一个使用用户搜索的 ldap 领域:

    1. elasticsearch.yml 文件的 xpack.security.authc.realms.ldap 命名空间下添加一个领域配置。至少,您必须指定 LDAP 服务器的 urlorder,并将 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 中配置领域时,仅使用您指定的领域进行身份验证。如果您还想使用 nativefile 领域,则必须将它们包含在领域链中。

  3. 要使用用户DN模板配置ldap领域:

    1. elasticsearch.yml 文件的 xpack.security.authc.realms.ldap 命名空间中添加一个领域配置。至少,您必须指定 LDAP 服务器的 urlorder,并使用 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操作都以认证用户身份运行。

  4. (可选) 配置安全功能如何与多个 LDAP 服务器交互。

    可以在领域级别使用load_balance.type设置。Elasticsearch的安全功能支持故障转移和负载均衡操作模式。 请参阅LDAP领域设置

  5. (可选) 为了保护密码, 加密 Elasticsearch 和 LDAP 服务器之间的通信
  6. 重启 Elasticsearch。
  7. 将 LDAP 组映射到角色。

    通过 ldap 领域,您可以将 LDAP 用户通过其 LDAP 组或其他元数据映射到角色。此角色映射可以通过 添加角色映射 API 或通过存储在每个节点上的文件进行配置。当用户使用 LDAP 进行身份验证时,该用户的权限是用户所映射的所有角色定义的权限的并集。

    在映射定义中,您可以使用其专有名称指定组。例如,以下映射配置将 LDAP admins 组映射到 monitoringuser 角色,并将 users 组映射到 user 角色。

    通过角色映射 API 配置:

    PUT /_security/role_mapping/admins
    {
      "roles" : [ "monitoring" , "user" ],
      "rules" : { "field" : {
        "groups" : "cn=admins,dc=example,dc=com" 
      } },
      "enabled": true
    }

    LDAP 专有名称 (DN) 的 admins 组。

    PUT /_security/role_mapping/basic_users
    {
      "roles" : [ "user" ],
      "rules" : { "field" : {
        "groups" : "cn=users,dc=example,dc=com" 
      } },
      "enabled": true
    }

    LDAP 专有名称 (DN) 的 users 组。

    或者,也可以通过角色映射文件进行配置:

    monitoring: 
      - "cn=admins,dc=example,dc=com" 
    user:
      - "cn=users,dc=example,dc=com" 
      - "cn=admins,dc=example,dc=com"

    映射角色的名称。

    LDAP 专有名称 (DN) 的 admins 组。

    LDAP 专有名称 (DN) 的 users 组。

    更多信息,请参阅 映射 LDAP 组到角色映射用户和组到角色

    LDAP 领域支持 授权领域作为角色映射的替代方案。

  8. (可选) 在 LDAP 领域配置 metadata 设置,以在用户的元数据中包含额外字段。

    默认情况下,用户的元数据中会填充 ldap_dnldap_groups。 有关更多信息,请参阅 LDAP 领域中的用户元数据

    下面的示例在用户的元数据中包含了用户的常用名称(cn)作为附加字段。

    xpack:
      security:
        authc:
          realms:
            ldap:
              ldap1:
                order: 0
                metadata: cn
  9. 设置 SSL 以加密 Elasticsearch 和 LDAP 之间的通信。请参阅 加密 Elasticsearch 和 LDAP 之间的通信

LDAP 领域中的用户元数据

edit

当用户通过LDAP领域进行身份验证时,用户的元数据中会填充以下属性:

字段

描述

ldap_dn

用户的唯一标识名称。

ldap_groups

为该用户解析的每个组的专有名称(无论这些组是否映射到角色)。

此元数据在 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用户认证

  1. 在每个节点上配置域的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服务器或证书是自签名的情况下才推荐使用。

  2. 设置域配置中的url属性以指定LDAPS协议和安全端口号。例如,url: ldaps://ldap.example.com:636
  3. 重启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 领域使您能够设置它在领域链中的顺序,临时禁用该领域,并控制其缓存选项。

  1. 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 哈希算法进行哈希处理。要使用不同的哈希算法,请参阅 用户缓存和密码哈希算法

  2. 重启Elasticsearch。

管理本地用户

edit

Elastic Stack 安全功能使您能够轻松地在 Kibana 的 管理 / 安全 / 用户 页面上管理用户。

或者,您可以通过user API管理用户。有关更多信息和示例,请参阅用户

OpenID Connect 认证

edit

OpenID 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。

  1. 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 中配置领域时,仅使用您指定的领域进行身份验证。如果您还想使用 nativefile 领域,则必须将它们包含在领域链中。

  2. 可选:用户名由 username_pattern 定义。 如果你想使用不同于主题 DN 的 CN 作为用户名,可以指定一个正则表达式来提取所需的用户名。该正则表达式应用于主题 DN。

    例如,以下配置中的正则表达式从主题DN中提取电子邮件地址:

    xpack:
      security:
        authc:
          realms:
            pki:
              pki1:
                order: 1
                username_pattern: "EMAILADDRESS=(.*?)(?:,|$)"

    如果正则表达式过于严格,并且与客户端证书的主题DN不匹配,那么领域不会验证该证书。

  3. 可选:如果您希望相同的用户在连接到 Kibana 时也使用证书进行身份验证,您必须配置 Elasticsearch PKI 领域以允许委托。请参阅 连接到 Kibana 的客户端的 PKI 身份验证
  4. 重新启动 Elasticsearch,因为领域配置不会自动重新加载。如果您正在按照下一步操作,您可能希望最后再进行重新启动。
  5. 启用 SSL/TLS
  6. 在所需的网络层(传输层或HTTP层)上启用客户端认证。

    当客户端直接连接到 Elasticsearch 时使用 PKI,您必须启用带有客户端认证的 SSL/TLS。也就是说,您必须将 xpack.security.transport.ssl.client_authenticationxpack.security.http.ssl.client_authentication 设置为 optionalrequired。如果设置值为 optional,没有证书的客户端可以使用其他凭证进行认证。

    当客户端直接连接到 Elasticsearch 且未经过代理身份验证时,PKI 领域依赖于节点网络接口的 TLS 设置。该领域可以配置得比底层网络连接更为严格。也就是说,可以配置节点,使得某些连接被网络接口接受,但随后在 PKI 领域中身份验证失败。然而,反过来是不可能的。PKI 领域无法对已被网络接口拒绝的连接进行身份验证。

    特别是这意味着:

    • 传输或 http 接口必须通过将 client_authentication 设置为 optionalrequired 来请求客户端证书。
    • 接口必须 信任 客户端提供的证书,通过配置 truststorecertificate_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 格式时。该设置接受一个列表。这两个选项是互斥的,它们不能同时使用。

  7. 为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
    }

    PKI用户的专有名称(DN)。

    或者,使用角色映射文件。例如:

    user: 
      - "cn=John Doe,ou=example,o=com" 

    角色的名称。

    PKI用户的专有名称(DN)。

    文件的路径默认为 ES_PATH_CONF/role_mapping.yml。您可以通过使用 files.role_mapping 领域设置来指定不同的路径(该路径必须在 ES_PATH_CONF 内)(例如 xpack.security.authc.realms.pki.pki1.files.role_mapping)。

    PKI用户的专有名称遵循X.500命名约定,将最具体的字段(如cnuid)放在名称的开头,将最一般的字段(如odc)放在名称的末尾。一些工具,如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.enableddelegation.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_userpki_delegated_by_realm。在常见的设置中,身份验证被委托给Kibana,这些字段的值分别为kibanareserved。例如,以下角色映射规则将role_for_pki1_direct角色分配给所有通过pki1领域直接进行身份验证的用户,方法是连接到Elasticsearch而不是通过Kibana:

PUT /_security/role_mapping/direct_pki_only
{
  "roles" : [ "role_for_pki1_direct" ],
  "rules" : {
    "all": [
      {
        "field": {"realm.name": "pki1"}
      },
      {
        "field": {
          "metadata.pki_delegated_by_user": null 
        }
      }
    ]
  },
  "enabled": true
}

如果此元数据字段已设置(即,它不是 null),则用户已在委托场景中进行了身份验证。

SAML 认证

edit

Elastic 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领域

edit

Kerberos 用于保护服务,并使用基于票据的身份验证协议来验证用户。 您可以配置 Elasticsearch 以使用 Kerberos V5 身份验证协议,这是一种行业标准协议,来验证用户。 在这种情况下,客户端必须提供 Kerberos 票据进行身份验证。

在Kerberos中,用户首先通过认证服务进行认证,然后通过票据授予服务生成TGT(票据授予票据)。此票据随后用于向服务进行认证。有关获取TGT的更多信息,请参阅您的Kerberos安装文档。Elasticsearch客户端必须首先获取TGT,然后启动与Elasticsearch的认证过程。

开始之前

edit
  1. 部署 Kerberos。

    您必须在您的环境中设置Kerberos基础设施。

    Kerberos 需要许多外部服务才能正常运行,例如所有机器之间的时间同步以及域中的正向和反向 DNS 映射。有关更多详细信息,请参阅您的 Kerberos 文档。

    这些说明不包括设置和配置您的Kerberos部署。提供的示例适用于MIT Kerberos V5部署。更多信息,请参阅MIT Kerberos文档

  2. 配置 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要求

  3. 为HTTP启用TLS。

    如果您的 Elasticsearch 集群在生产模式下运行,您必须在启用 Kerberos 身份验证之前配置 HTTP 接口以使用 SSL/TLS。有关更多信息,请参阅 加密 Elasticsearch 的 HTTP 客户端通信

    此步骤是为了通过 Kibana 支持 Kerberos 认证所必需的。 对于直接针对 Elasticsearch Rest API 的 Kerberos 认证,这不是必需的。

  4. 启用令牌服务

    Elasticsearch 的 Kerberos 实现使用了 Elasticsearch 令牌服务。如果在 HTTP 接口上配置了 TLS,此服务将自动启用。可以通过在 elasticsearch.yml 文件中添加以下设置来显式配置:

    xpack.security.authc.token.enabled: true

    此步骤是为了通过 Kibana 支持 Kerberos 认证所必需的。 对于直接针对 Elasticsearch Rest API 的 Kerberos 认证,这不是必需的。

创建一个Kerberos领域

edit

在 Elasticsearch 中配置 Kerberos 领域:

  1. 配置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

  2. 为 Elasticsearch 节点创建一个 keytab。

    keytab 是一个存储主体和加密密钥对的文件。Elasticsearch 使用 keytab 中的密钥来解密用户提供的票据。您必须使用 Kerberos 实现提供的工具为 Elasticsearch 创建一个 keytab。例如,一些创建 keytab 的工具有 Windows 上的 ktpass.exe 和 MIT Kerberos 的 kadmin

  3. 将密钥表文件放在Elasticsearch配置目录中。

    确保此密钥表文件具有读取权限。此文件包含凭据,因此您必须采取适当措施来保护它。

    Elasticsearch 在 HTTP 网络层使用 Kerberos,因此必须在每个 Elasticsearch 节点上为 HTTP 服务主体提供一个 keytab 文件。服务主体名称必须具有格式 HTTP/es.domain.local@ES.DOMAIN.LOCAL。由于它们包含主机名,keytab 文件对于每个节点都是唯一的。只要在配置的 keytab 中找到该主体及其凭据,Elasticsearch 节点就可以充当客户端请求的任何主体。

  4. 创建一个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

  5. 重启 Elasticsearch
  6. 将Kerberos用户映射到角色。

    The kerberos realm 允许您将 Kerberos 用户映射到角色。您可以通过使用 创建或更新角色映射 API 来配置这些角色映射。您可以通过其 username 字段来识别用户。

    以下示例使用角色映射 API 将 user@REALM 映射到角色 monitoringuser

    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 认证

edit

Elasticsearch 可以配置为信任从外部服务颁发的 JSON Web Tokens (JWTs) 作为身份验证的承载令牌。

当使用 JWT realm 进行 Elasticsearch 身份验证时,会区分连接到 Elasticsearch 的 客户端 和代表其运行请求的 用户。JWT 用于验证用户,而单独的凭证用于验证客户端。

JWT realm 支持两种令牌类型,id_token(默认)和 access_token。 它们分别设计用于以下两种场景:

  1. id_token - 应用程序通过身份验证流程(例如 OpenID Connect (OIDC))对用户进行身份验证和识别,然后使用符合 OIDC ID Token 规范的 JSON Web Token (JWT) 代表已验证的用户访问 Elasticsearch。
  2. access_token - 应用程序使用其自身的身份(编码为 JWT)访问 Elasticsearch,例如,应用程序通过 OAuth2 客户端凭据流向中央身份平台进行身份验证,然后使用生成的基于 JWT 的访问令牌连接到 Elasticsearch。

一个单独的JWT领域只能与一种令牌类型一起工作。要处理两种令牌类型,您必须配置至少两个JWT领域。您应根据使用情况仔细选择令牌类型,因为它会影响验证的执行方式。

JWT realm 根据其配置的令牌类型验证传入的 JWT。 JSON Web Tokens (JWT) 的两种类型都必须包含以下 5 条信息。 虽然基于 OIDC 规范的 ID 令牌对应该提供这些信息的声明有严格的规定, 但访问令牌允许一些声明是可配置的。

声明

信息

ID Token

访问令牌

发行者

iss

iss

主题

sub

默认为 sub,但如果 sub 不存在,则会回退到另一个声明

受众

aud

默认为 aud,但如果 aud 不存在,则会回退到另一个声明

发布时间

iat

iat

过期时间

exp

exp

此外,如果存在这些声明,Elasticsearch 还会验证 ID 令牌的 nbfauth_time 声明。 但对于访问令牌,这些声明会被忽略。

总的来说,访问令牌类型的验证规则更为宽松,适用于更通用的JWT,包括自签名的JWT。

来自OIDC工作流的ID令牌

edit

Elasticsearch中的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_subjectsallowed_subject_patterns验证。

并非每个访问令牌都格式化为JSON Web Token(JWT)。 为了使其与JWT领域兼容,它至少必须使用JWT格式并满足上表中的相关要求。

配置 Elasticsearch 以使用 JWT 领域

edit

要使用JWT认证,请在elasticsearch.yml文件中创建领域,以在Elasticsearch认证链中进行配置。

JWT realm 有几项必填设置,以及在 JWT realm 设置中描述的可选设置。

JWT realms默认启用了客户端认证。虽然可以禁用客户端认证,但强烈不建议这样做。

  1. 将您的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
    指定领域的order3,表示在验证用户时配置的领域被检查的顺序。领域按照升序被咨询,其中具有最低顺序值的领域首先被咨询。
    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应使用RS256HS256签名算法来验证来自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_typeaccess_token时,必须指定至少一个allowed_subjectsallowed_subject_patterns设置(且不能为空)。

    当同时指定了allowed_subjectsallowed_subject_patterns设置时,传入的JWT的sub声明如果匹配其中任何一个列表,则会被接受。

    required_claims
    指定一个键/值对列表,用于对JWT进行额外的验证。值可以是字符串或字符串数组。
    fallback_claims.sub
    如果sub声明不存在,提取主体信息的JWT声明的名称。此设置仅在token_typeaccess_token时可用。回退适用于sub声明使用的任何地方。在上面的代码片段中,这意味着如果sub不存在,claims.principal也将回退到client_id
    fallback_claims.aud
    如果aud声明不存在,提取受众信息的JWT声明的名称。此设置仅在token_typeaccess_token时可用。回退适用于aud声明使用的任何地方。
  2. 定义设置后,使用 elasticsearch-keystore 工具在 Elasticsearch 密钥库中存储安全设置的值。

    1. 存储 shared_secret 值用于 client_authentication.type

      bin/elasticsearch-keystore add xpack.security.authc.realms.jwt.jwt1.client_authentication.shared_secret
    2. 存储用于 allowed_signature_algorithms 的 HMAC 密钥,该算法在示例中使用 HMAC SHA-256 算法 HS256

      bin/elasticsearch-keystore add-file xpack.security.authc.realms.jwt.jwt1.hmac_jwkset  

      JWKS 的路径,这是一个用于一组 JSON 编码的密钥的资源。 在您将内容加载到 Elasticsearch 密钥库后,可以删除该文件。

      建议使用JWKS。然而,您可以使用以下命令添加一个字符串格式的HMAC密钥。此格式与HMAC UTF-8密钥兼容,但仅支持没有属性的单个密钥。您只能同时使用一种HMAC格式(hmac_jwksethmac_key)。

      bin/elasticsearch-keystore add xpack.security.authc.realms.jwt.jwt1.hmac_key

JWT 编码和验证

edit

JWT 可以解析为三个部分:

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 HeaderSignature。一些验证可以通过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设置
edit

Elasticsearch 使用 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 领域授权

edit

JWT 领域支持通过创建或更新角色映射 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领域委托角色分配和查找给另一个领域时,dngroupsmailmetadataname的声明不会用于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 领域用户

edit

Elasticsearch 可以通过角色映射或委托授权来检索 JWT 用户的角色。无论您选择哪种选项,您都可以将 run_as 权限应用于角色,以便用户可以提交经过身份验证的请求以“作为”其他用户运行。要提交作为其他用户的请求,请在您的请求中包含 es-security-runas-user 头。请求将以该用户的身份运行,Elasticsearch 将使用他们的角色。

例如,假设有一个用户名为 user123_runas 的用户。 以下请求创建了一个名为 jwt_role1 的用户角色,该角色指定了一个用户名为 user123_runasrun_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 重新加载

edit

JWT 认证支持使用 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

在 Elastic Cloud 中,领域顺序从 2 开始。01 在 Elastic Cloud 的领域链中被保留。

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。您可以使用此代码作为创建自己的领域的起点。

要创建自定义领域,您需要:

  1. 扩展 org.elasticsearch.xpack.security.authc.Realm 以与您的身份验证系统通信,以验证用户。
  2. 在用于创建自定义领域的类中实现 org.elasticsearch.xpack.security.authc.Realm.Factory 接口。
  3. 扩展 org.elasticsearch.xpack.security.authc.DefaultAuthenticationFailureHandler 以在使用自定义领域时处理身份验证失败。

将您的自定义领域打包为插件:

  1. 为您的领域实现一个扩展类,该类扩展了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插件主类的一部分可用。

  2. 创建插件的构建配置文件;我们推荐使用Gradle。
  3. 为扩展创建一个META-INF/services/org.elasticsearch.xpack.core.security.SecurityExtension描述符文件,其中包含您的org.elasticsearch.xpack.core.security.SecurityExtension实现的全限定类名。
  4. 将所有内容打包到一个zip文件中。

使用自定义领域进行用户认证

edit

要使用自定义领域:

  1. 在集群中的每个节点上安装领域扩展。您运行bin/elasticsearch-plugin并使用install子命令,并指定指向包含扩展的zip文件的URL。例如:

    bin/elasticsearch-plugin install file:////my-realm-1.0.zip
  2. xpack.security.authc.realms 命名空间下,向 elasticsearch.yml 添加适当类型的领域配置。 您必须在匹配扩展定义的类型的命名空间内定义您的领域。 您可以设置的选项取决于自定义领域暴露的设置。 至少,您必须显式设置 order 属性以控制领域在身份验证期间被咨询的顺序。 您还必须确保每个配置的领域具有不同的 order 设置。 如果两个或多个领域具有相同的 order,节点将无法启动。

    当您在 elasticsearch.yml 中配置领域时,仅使用您指定的领域进行身份验证。如果您还想使用 nativefile 领域,则必须将它们包含在领域链中。

  3. 重启 Elasticsearch。

启用匿名访问

edit

要嵌入 Kibana 仪表板或授予对 Kibana 的访问权限而不需要凭据,请使用 Kibana 的 匿名身份验证功能。

如果无法从传入请求中提取身份验证令牌,则认为传入请求是匿名的。默认情况下,匿名请求会被拒绝,并返回身份验证错误(状态码401)。

要启用匿名访问,您可以在elasticsearch.yml配置文件中为匿名用户分配一个或多个角色。例如,以下配置为匿名用户分配了role1role2

xpack.security.authc:
  anonymous:
    username: anonymous_user 
    roles: role1, role2 
    authz_exception: true 

匿名用户的用户名/主体。如果未指定,默认为_es_anonymous_user

与匿名用户关联的角色。如果未指定角色,则禁用匿名访问——匿名请求将被拒绝并返回身份验证错误。

true时,如果匿名用户没有执行请求操作所需的权限,则会返回403 HTTP状态码,并且不会提示用户提供凭据以访问请求的资源。当false时,如果匿名用户没有必要的权限,则会返回401 HTTP状态码,并提示用户提供凭据以访问请求的资源。如果您正在结合HTTP使用匿名访问,您可能需要将authz_exception设置为false,如果您的客户端不支持抢占式基本身份验证。默认为true

查找用户无需身份验证

edit

Elasticsearch 领域 主要用于支持 用户认证。 一些领域使用密码认证用户(例如 nativeldap 领域),而其他领域使用 更复杂的认证协议(例如 samloidc 领域)。 在每种情况下,领域的主要目的是确定 向 Elasticsearch API 发出请求的用户的身份。

然而,某些 Elasticsearch 功能需要查找用户而不使用其凭据。

  • run_as 功能代表另一个用户执行请求。具有 run_as 权限的已验证用户可以代表另一个未验证用户执行请求。
  • 委托授权 功能将两个领域链接在一起,以便对一个领域进行身份验证的用户可以拥有与来自不同领域的用户关联的角色和元数据。

在每种情况下,用户必须首先在一个领域进行身份验证,然后Elasticsearch将查询第二个领域以找到另一个用户。 已验证的用户凭据仅用于在第一个领域进行身份验证, 第二个领域中的用户通过用户名检索,无需凭据。

当 Elasticsearch 使用用户的凭证(如在第一个领域中执行的操作)解析用户时,这被称为用户认证

当 Elasticsearch 仅使用用户名解析用户时(如在第二个领域中执行的操作),这被称为用户查找

请参阅run_as委托授权 文档以了解更多关于这些功能的信息,包括哪些领域和认证方法支持run_as或委托授权。 在这两种情况下,只有以下领域可以用于用户查找:

  • 保留的,nativefile 领域始终支持用户查找。
  • ldap 领域在领域配置为 用户搜索 模式时支持用户查找。当领域配置为 user_dn_templates 时,不支持用户查找。
  • active_directory 领域中的用户查找支持要求领域配置为具有 bind_dn 和绑定密码。

The pki, saml, oidc, kerberosjwt 领域不支持用户查找。

如果您只想使用某个领域进行用户查找并阻止用户针对该领域进行身份验证,您可以配置该领域并将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.ttlcache.max_userscache.hash_algo领域设置来配置用户缓存的特性。

JWT realms 使用 jwt.cache.ttljwt.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 单点登录

edit

Elastic Stack 支持使用 Elasticsearch 作为后端服务,通过 SAML 单点登录(SSO)进入 Kibana。在 SAML 术语中,Elastic Stack 作为服务提供商运行。

启用SAML单点登录所需的另一个组件是身份提供者,它是一个处理您的凭证并执行用户实际身份验证的服务。

如果您有兴趣将单点登录(SSO)配置到 Kibana 中,那么您需要向 Elasticsearch 提供有关您的 身份提供者 的信息,并且您需要将 Elastic Stack 注册为该身份提供者中的已知 服务提供者。此外,还需要在 Kibana 中进行一些配置更改以激活 SAML 身份验证提供者。

Kibana 中的 SAML 支持是基于这样的预期设计的:它将成为该 Kibana 实例用户的主要(或唯一)认证方法。一旦您在 Kibana 中启用了 SAML 认证,它将影响所有尝试登录的用户。配置 Kibana 部分提供了更多关于其工作原理的详细信息。

身份提供者

edit

Elastic 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元数据的最低要求是:

  • 一个具有与Elasticsearch 配置 匹配的entityID
  • 一个支持SAML 2.0协议的 (urn:oasis:names:tc:SAML:2.0:protocol)。
  • 至少一个配置为签名(即,它具有use="signing"或未指定use
  • 一个绑定为HTTP-Redirect的 (urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect)
  • 如果您希望支持单点注销,一个绑定为HTTP-Redirect的 (urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect)

Elastic Stack 要求 IdP 发出的所有消息都必须签名。 对于身份验证 消息,签名可以应用于响应本身,也可以应用于单个断言。 对于 消息,消息本身必须签名,并且签名应作为 URL 参数提供,如 HTTP-Redirect 绑定所要求的那样。

为 SAML 认证配置 Elasticsearch

edit

在Elasticsearch中启用SAML认证有五个配置步骤:

  1. 启用HTTP的SSL/TLS
  2. 启用令牌服务
  3. 创建一个或多个SAML领域
  4. 配置角色映射
  5. 为您的身份提供者生成一个SAML元数据文件 (可选)

为HTTP启用TLS

edit

如果您的 Elasticsearch 集群在生产模式下运行,那么在启用 SAML 认证之前,您必须配置 HTTP 接口以使用 SSL/TLS。

更多信息,请参阅 加密Elasticsearch的HTTP客户端通信

启用令牌服务

edit

Elasticsearch 的 SAML 实现使用了 Elasticsearch Token Service。如果您在 HTTP 接口上配置了 TLS,此服务将自动启用,并且可以通过在您的 elasticsearch.yml 文件中包含以下内容来显式配置:

xpack.security.authc.token.enabled: true

创建一个SAML领域

edit

SAML 认证通过在 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.1http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn,并且与它们相关联的有一个或多个值。

这些属性标识符在不同的身份提供者(IdP)之间有所不同,大多数身份提供者提供了自定义URI及其关联值的方法。

Elasticsearch 使用这些属性来推断已登录用户的信息,并且它们可以用于角色映射(如下)。

为了让这些属性变得有用,Elasticsearch 和 IdP 需要对属性的名称有一个共同的值。这是通过手动配置 IdP 和 SAML 领域来使用相同的 URI 名称来实现的,每个逻辑用户属性都是如此。

配置这些SAML属性的推荐步骤如下:

  1. 咨询您的身份提供者(IdP),了解它可以提供哪些用户属性。 这因提供者而异,但您应该能够从文档或您的本地管理员处获得列表。
  2. 阅读Elasticsearch支持的用户属性列表,并决定哪些对您有用,并且可以由您的IdP提供。至少,需要principal属性。
  3. 配置您的IdP以“释放”这些属性到您的Kibana SAML服务提供者。此过程因提供者而异——有些会提供用户界面,而其他的可能需要您编辑配置文件。通常,IdP(或您的本地管理员)会建议为每个属性使用什么URI。您可以简单地接受这些建议,因为Elasticsearch服务是完全可配置的,不需要使用任何特定的URI。
  4. 在Elasticsearch中配置SAML领域,将Elasticsearch用户属性(参见下面的列表)与您在IdP中配置的URI关联起来。在上面的示例中,我们配置了principalgroups属性。
特殊属性名称
edit

一般来说,Elasticsearch 期望为属性配置的值将是一个 URI,例如 urn:oid:0.9.2342.19200300.100.1.1,不过还有一些额外的名称可以使用:

nameid
这使用SAML NameID 值(去除所有前导和尾随空格) 而不是SAML属性。SAML NameID 元素是一个可选的,但通常提供的字段,在SAML断言中,IdP可能使用它来标识该断言的主题。在某些情况下,NameID 将与用户在IdP中的登录标识符(用户名)相关联,但在许多情况下,它们将是IdP内部生成的标识符,这些标识符在IdP外部没有明显的意义。
nameid:persistent
这使用SAML NameID 值(去除所有前导和尾随空白),但仅当NameID格式为 urn:oasis:names:tc:SAML:2.0:nameid-format:persistent时。 SAML NameID 元素具有一个可选的 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 用户属性
edit

Elasticsearch SAML realm 可以配置为将 SAML 属性 映射到经过身份验证的用户上的以下属性:

principal
(必需) 这是将应用于与此领域进行身份验证的用户的用户名principal 出现在 Elasticsearch 审计日志等地方。
groups

(推荐) 如果您希望使用您的身份提供者(IdP)的组或角色概念作为用户Elasticsearch权限的基础,您应该使用此属性进行映射。 groups 会直接传递给您的 角色映射规则

一些身份提供者(IdP)配置为将groups列表作为单个值、逗号分隔的字符串发送。要将此SAML属性映射到Elasticsearch领域中的attributes.groups设置,您可以使用attribute_delimiters.group设置配置字符串分隔符。

例如,将SAML属性值 engineering,elasticsearch-admins,employees 以分隔符值 , 进行分割, 将会得到 engineeringelasticsearch-adminsemployees 作为用户的组列表。

name
(可选) 用户的完整姓名。
mail
(可选) 用户的电子邮件地址。
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 注销

edit

SAML协议支持单点登出(SLO)的概念。 身份提供者对SLO的支持程度各不相同。 您应查阅您的身份提供者的文档,以确定它提供哪些登出服务。

默认情况下,如果以下条件为真,Elastic Stack 将支持 SAML SLO:

  • 您的IdP元数据指定IdP提供单点注销服务
  • 您的IdP在为您的用户发布的SAML断言的主题中释放了一个NameID
  • 您配置了sp.logout
  • 设置idp.use_single_logout不是false
IdP SLO 服务
edit

Elasticsearch从IdP的SAML元数据中读取的值之一是 。为了使单点注销与Elastic stack一起工作,Elasticsearch要求此服务存在并支持绑定 urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect

Elastic Stack 将根据需要向此服务发送 消息。

sp.logout 设置
edit

Elasticsearch 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会话。

加密和签名

edit

Elastic 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 或本地策略要求使用它们的情况下使用。

生成证书和密钥
edit

Elasticsearch 支持 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元素的本地名称标识。支持的值包括:AuthnRequestLogoutRequestLogoutResponse
配置 Elasticsearch 以处理加密消息
edit

Elasticsearch 安全功能支持使用单一密钥进行消息解密。如果配置了密钥,则 Elasticsearch 会尝试使用该密钥来解密身份验证响应中的 EncryptedAssertionEncryptedAttribute 元素,以及注销请求中的 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" }
  }
}

example_role 角色不是 Elasticsearch 内置角色。 这个示例假设您已经创建了一个自定义角色,并具有适当的访问权限,可以访问您的 数据流、索引Kibana 功能

通过领域配置映射的属性用于处理角色映射规则,这些规则决定了用户被授予哪些角色。

提供给角色映射的用户字段是从SAML属性中派生出来的,如下所示:

  • username: The principal attribute
  • dn: The dn attribute
  • groups: The groups 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" } } 
  ] }
}

属性 groups 支持使用通配符 (*)。更多信息请参考 创建或更新角色映射 API

如果您的用户也存在于可以直接被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 和基本身份验证

edit

Kibana 中的 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 实例,而其他实例则使用基本身份验证针对另一种领域类型(例如 NativeLDAP)。

SAML 领域配置故障排除

edit

SAML 2.0 规范为标准的实现者提供了许多选项和灵活性,这反过来又增加了复杂性和服务提供商(Elastic Stack)和身份提供商处可用的配置选项数量。此外,不同的安全域有不同的安全要求,需要特定的配置来满足。我们已尽力通过合理的默认值和上述详细的文档来掩盖这种复杂性,但如果您在配置 SAML 领域时遇到问题,可以查看我们的 SAML 故障排除文档,其中包含常见问题的建议和解决方案。

没有 Kibana 的 SAML

edit

Elasticsearch 中的 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进行用户身份验证:

  1. _security/saml/prepare 发起 HTTP POST 请求,以 saml-service-user 用户身份进行认证。可以使用 Elasticsearch 配置中的 SAML 领域名称或请求体中的断言消费者服务 URL 值。更多详情请参见 SAML prepare authentication API

    POST /_security/saml/prepare
    {
      "realm" : "saml1"
    }
  2. 处理来自 /_security/saml/prepare 的响应。Elasticsearch 的响应将包含 3 个参数: redirectrealmid。自定义 Web 应用程序需要将 id 的值存储在用户的会话中(客户端在 cookie 中或服务器端,如果会话信息以这种方式持久化)。它还必须将用户的浏览器重定向到 redirect 参数中返回的 URL。id 值不应被忽略,因为它在 SAML 中用作 nonce,以减轻重放攻击。
  3. 处理来自 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 中所述。

  4. 调用 /_security/saml/authenticate 的响应将仅包含已认证用户的用户名。如果您需要获取该用户在 SAML 响应中包含的 SAML 属性值,您可以使用访问令牌作为 Bearer 令牌调用 Authenticate API /_security/_authenticate/,SAML 属性值将作为 用户元数据 的一部分包含在响应中。

处理IdP发起的身份验证流程

edit

Elasticsearch 还可以处理 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
  1. 在必要时,自定义Web应用程序可以通过使用SAML logout API并传递访问令牌和刷新令牌作为参数来注销用户。例如:

    POST /_security/saml/logout
    {
      "token" : "46ToAxZVaXVVZTVKOVF5YU04ZFJVUDVSZlV3",
      "refresh_token": "mJdXLtmvTUSpoLwMvdBt_w"
    }

    如果SAML领域配置正确且IdP支持(参见SAML注销),此请求将触发SAML SP发起的单点注销。在这种情况下,响应将包含一个redirect参数,指示用户需要在IdP上重定向以完成注销。

  2. 或者,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 的单点登录

edit

Elastic Stack 支持使用 OpenID Connect 通过 Kibana 进行单点登录 (SSO),其中 Elasticsearch 作为后端服务,持有大部分功能。Kibana 和 Elasticsearch 共同代表一个 OpenID Connect 依赖方 (RP),支持授权代码流和隐式流,这些流在 OpenID Connect 规范中定义。

本指南假设您有一个OpenID Connect提供程序,其中将注册Elastic Stack依赖方。

Kibana 中的 OpenID Connect 领域支持旨在预期它将成为该 Kibana 实例用户的主要身份验证方法。配置 Kibana 部分描述了这意味着什么以及如何在必要时设置它以支持其他领域。

OpenID Connect 提供者

edit

OpenID 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客户端通信

启用令牌服务

edit

Elasticsearch 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,而常用的包括 profileemailprofile 范围请求访问 namefamily_namegiven_namemiddle_namenicknamepreferred_usernameprofilepicturewebsitegenderbirthdatezoneinfolocaleupdated_at 声明。email 范围请求访问 emailemail_verified 声明。流程是 RP 在身份验证请求期间请求特定的范围。如果 OP 隐私政策允许并且验证用户同意,则相关声明将返回给 RP(无论是 ID Token 还是 UserInfo 响应)。

支持的声明列表会因您使用的OP而异,但您可以预期标准声明会得到广泛支持。

将声明映射到用户属性
edit

声明映射的目标是配置 Elasticsearch,以便能够将指定返回声明的值映射到 Elasticsearch 支持的 用户属性之一。这些用户属性随后用于在 Kibana UI 或审计日志中识别用户,并且还可以用于创建 角色映射规则。

配置OpenID Claims映射的推荐步骤如下:

  1. 查阅您的OP配置,了解它可能支持哪些声明。请注意,OP的元数据或配置页面中提供的列表是可能支持的声明列表。然而,出于隐私原因,它可能不是一个完整的列表,或者并非所有支持的声明都适用于所有经过身份验证的用户。
  2. 浏览Elasticsearch支持的用户属性列表,并决定哪些对您有用,并且可以以声明的形式由您的OP提供。至少,需要principal用户属性。
  3. 配置您的OP以“释放”这些声明到您的Elastic Stack依赖方。此过程因提供商而异。您可以使用静态配置,而其他提供商则支持依赖方在身份验证时请求与要“释放”的声明相对应的范围。有关如何配置要请求的范围的详细信息,请参见rp.requested_scopes。为了确保互操作性并最小化错误,您应该仅请求OP支持的范围,并且您打算将其映射到Elasticsearch用户属性。

    注意:您只能映射值为字符串、数字、布尔值或上述类型的数组的声明。
  4. 在Elasticsearch中配置OpenID Connect领域,以将Elasticsearch用户属性(参见 列表)与您的OP将发布的声明名称关联起来。在上面的示例中,我们已将principalgroups用户属性配置如下:

    1. claims.principal: sub : 这指示Elasticsearch在OP为用户发布的ID令牌(或在UserInfo响应中)中查找名为sub的OpenID Connect声明,并将此声明的值分配给principal用户属性。sub是用于principal属性的常用声明,因为它是OP中用户的标识符,并且也是ID令牌的必需声明,因此提供了它将可用的保证。然而,这里仅作为示例使用,OP可能会提供另一个更适合您需求的声明。
    2. claims.groups: "http://example.info/claims/groups" : 同样,这指示Elasticsearch查找名为http://example.info/claims/groups的声明(请注意,这是一个URI - 一个标识符,被视为字符串而不是指向将检索的位置的URL),无论是在ID令牌中还是在UserInfo响应中,并将其值映射到Elasticsearch中的用户属性groups。规范中没有用于表示经过身份验证用户在OP中的角色或组成员资格的标准声明,因此此处应映射的声明名称在提供商之间会有很大差异。有关更多详细信息,请查阅您的OP文档。
Elasticsearch 用户属性
edit

Elasticsearch OpenID Connect 领域可以配置为将 OpenID Connect 声明映射到经过身份验证的用户上的以下属性:

principal
(必需) 这是将应用于与此领域进行身份验证的用户的用户名principal 出现在 Elasticsearch 审计日志等地方。

如果principal属性未能从声明中映射,则身份验证失败。

groups
(推荐) 如果您希望使用您的 OP 的组或角色概念作为用户 Elasticsearch 权限的基础,您应该使用此属性进行映射。 groups 会直接传递给您的 角色映射规则
name
(可选) 用户的完整姓名。
mail
(可选) 用户的电子邮件地址。
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这样的电子邮件地址。确保您的正则表达式尽可能精确是非常重要的,这样您就不会无意中为用户的冒充攻击打开一个途径。

第三方发起的单点登录

edit

Elasticsearch 中的 Open ID Connect 领域支持第三方发起的登录,如相关规范中所述。

这允许OP本身或另一个不同于RP的第三方,在请求使用OP进行身份验证时启动身份验证过程。请注意,为了使此过程成功,Elastic Stack RP应已为此OP配置。

OpenID Connect 注销

edit

Elasticsearch 中的 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 配置

edit

OpenID 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" }
  }
}

example_role 角色不是 Elasticsearch 内置角色。 这个示例假设您已经创建了一个自定义角色,并具有适当的访问权限,可以访问您的 数据流、索引Kibana 功能

通过领域配置映射的用户属性用于处理角色映射规则,这些规则决定了用户被授予哪些角色。

提供给角色映射的用户字段是从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目录),那么您可以使用授权领域,而不是角色映射。

在这种情况下,您执行以下步骤:

  1. 在您的OpenID Connect领域中,通过配置claims.principal设置,分配一个声明作为查找用户ID。
  2. 创建一个新的领域,可以从您的本地存储库(例如ldap领域)中查找用户。
  3. 在您的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

edit

OpenID 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对用户进行身份验证:

  1. _security/oidc/prepare 发起 HTTP POST 请求,以 facilitator 用户身份进行身份验证,并在请求体中使用 Elasticsearch 配置中的 OpenID Connect realm 名称。更多详情,请参阅 OpenID Connect 准备身份验证 API

    POST /_security/oidc/prepare
    {
      "realm" : "oidc1"
    }
  2. 处理对 /_security/oidc/prepare 的响应。Elasticsearch 的响应将包含 3 个参数: redirectstatenonce。自定义 Web 应用程序需要将 statenonce 的值存储在用户的会话中(客户端在 cookie 中或服务器端,如果会话信息以这种方式持久化),并将用户的浏览器重定向到 redirect 值中包含的 URL。
  3. 处理来自 OP 的后续响应。在用户成功通过 OpenID Connect Provider 认证后,他们将被重定向回回调/重定向 URI。在接收到此 HTTP GET 请求后,自定义 Web 应用程序需要再次以 facilitator 用户身份向 _security/oidc/authenticate 发出 HTTP POST 请求,传递用户浏览器被重定向到的 URL 作为参数,以及之前在用户会话中保存的 noncestate 值。如果配置了多个 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 令牌用于后续请求的访问令牌,以及一个可以在以后用于刷新给定访问令牌的刷新令牌,如 获取令牌 中所述。

  4. 在必要时,自定义 Web 应用程序可以通过使用 OIDC logout API 并传递访问令牌和刷新令牌作为参数来注销用户。例如:

    POST /_security/oidc/logout
    {
      "token" : "dGhpcyBpcyBub3QgYSByZWFsIHRva2VuIGJ1dCBpdCBpcyBvbmx5IHRlc3QgZGF0YS4gZG8gbm90IHRyeSB0byByZWFkIHRva2VuIQ==",
      "refresh_token": "vLBPvmAB6KvwvJZr27cS"
    }

    如果领域配置得当,这可能会导致返回一个包含 redirect 参数的响应,指示用户需要在 OP 中重定向到哪里以完成注销过程。