在 Elastic Stack 上配置 SAML 单点登录编辑

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

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

如果您有兴趣配置 SSO 登录 Kibana,则需要向 Elasticsearch 提供有关您的_身份提供者_的信息,并且需要在该身份提供者中将 Elastic Stack 注册为已知的_服务提供者_。还需要在 Kibana 中进行一些配置更改才能激活 SAML 身份验证提供程序。

Kibana 中的 SAML 支持的设计预期是,它将成为该 Kibana 实例用户的首选(或唯一)身份验证方法。在 Kibana 中启用 SAML 身份验证后,它将影响所有尝试登录的用户。配置 Kibana 部分提供了有关其工作原理的更多详细信息。

身份提供者编辑

Elastic Stack 支持 SAML 2.0 _Web 浏览器 SSO_ 和 SAML 2.0 _单点注销_ 配置文件,并且可以与至少支持 SAML 2.0 _Web 浏览器 SSO 配置文件_ 的任何身份提供者 (IdP) 集成。它已经过许多流行的 IdP 实现的测试,例如 Microsoft Active Directory 联合身份验证服务 (ADFS)Azure Active Directory (AAD)Okta

本指南假设您有一个现有的 IdP,并希望将 Kibana 添加为服务提供者。

Elastic Stack 使用标准 SAML _元数据_ 文档(XML 格式),该文档定义了 IdP 的功能和特性。您应该能够在 IdP 管理界面中下载或生成此类文档。

下载 IdP 元数据文档,并将其存储在每个 Elasticsearch 节点的 config 目录中。在本指南中,我们假设您将其存储为 config/saml/idp-metadata.xml

IdP 将被分配一个标识符(SAML 术语中的_实体 ID_),该标识符通常以_统一资源标识符_ (URI) 形式表示。您的管理员界面可能会告诉您这是什么,或者您可能需要阅读元数据文档才能找到它 - 在 EntityDescriptor 元素上查找 entityID 属性。

大多数 IdP 将提供一个适当的元数据文件,其中包含 Elastic Stack 所需的所有功能,并且应该只需要执行以下配置步骤。为了完整起见,Elastic Stack 对 IdP 元数据的最低要求是

  • 一个 <EntityDescriptor>,其 entityID 与 Elasticsearch 配置 匹配
  • 一个支持 SAML 2.0 协议 (urn:oasis:names:tc:SAML:2.0:protocol) 的 <IDPSSODescriptor>
  • 至少一个配置用于_签名_ 的 <KeyDescriptor>(即,它具有 use="signing" 或将 use 留空)
  • 一个具有 HTTP-Redirect 绑定的 <SingleSignOnService> (urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect)
  • 如果您希望支持 单点注销,则需要一个具有 HTTP-Redirect 绑定的 <SingleLogoutService> (urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect)

Elastic Stack 要求对来自 IdP 的所有消息进行签名。对于身份验证 <Response> 消息,签名可以应用于响应本身,也可以应用于各个断言。对于 <LogoutRequest> 消息,必须对消息本身进行签名,并且应按照 HTTP-Redirect 绑定的要求,将签名作为 URL 参数提供。

为 SAML 身份验证配置 Elasticsearch编辑

在 Elasticsearch 中启用 SAML 身份验证需要五个配置步骤

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

为 HTTP 启用 TLS编辑

如果您的 Elasticsearch 集群在生产模式下运行,则必须先将 HTTP 接口配置为使用 SSL/TLS,然后才能启用 SAML 身份验证。

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

启用令牌服务编辑

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

xpack.security.authc.token.enabled: true

创建 SAML 领域编辑

通过在 Elasticsearch 的身份验证链中配置 SAML 领域来启用 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 客户端使用。

上面示例中使用的配置值为

xpack.security.authc.realms.saml.saml1
这定义了一个名为“saml1”的新 saml 身份验证领域。有关领域的更多说明,请参阅 领域
order
领域在领域链中的顺序。顺序较低的领域具有最高优先级,并且会首先被查询。我们建议为基于密码的领域(例如文件、本机、LDAP 和 Active Directory)赋予最低顺序(最高优先级),然后是 SSO 领域(例如 SAML 和 OpenID Connect)。如果您有多个相同类型的领域,请为访问最频繁的领域赋予最低顺序,以便首先查询它。
idp.metadata.path
这是您为身份提供者保存的元数据文件的路径。您在此处输入的路径是相对于您的 config/ 目录的。Elasticsearch 将自动监视此文件的更改,并在更新时重新加载配置。
idp.entity_id
这是您的 IdP 使用的标识符(SAML 实体 ID)。它应该与元数据文件中的 entityID 属性匹配。
sp.entity_id
这是 Kibana 实例的唯一标识符,以 URI 表示。在 IdP 中添加 Kibana 作为服务提供者时,将使用此值。我们建议您使用 Kibana 实例的基本 URL 作为实体 ID。
sp.acs
_断言使用者服务_ (ACS) 端点是 Kibana 中接受来自 IdP 的身份验证消息的 URL。此 ACS 端点仅支持 SAML HTTP-POST 绑定。它必须是从尝试登录 Kibana 的用户的 Web 浏览器可以访问的 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
请参阅属性映射

属性映射编辑

当用户通过您的身份提供程序连接到 Kibana 时,身份提供程序将提供有关该用户的 SAML 断言。断言将包含一个*身份验证声明*,指示用户已成功向 IdP 进行身份验证,以及一个或多个*属性声明*,其中将包含用户的*属性*。

这些属性可能包括以下内容

  • 用户的用户名
  • 用户的电子邮件地址
  • 用户的组或角色

SAML 中的属性使用 URI 命名,例如 urn:oid:0.9.2342.19200300.100.1.1http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn,并且具有与其关联的一个或多个值。

这些属性标识符因 IdP 而异,大多数 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 属性。
特殊属性名称编辑

通常,Elasticsearch 期望属性的配置值为 URI,例如 urn:oid:0.9.2342.19200300.100.1.1,但是可以使用一些其他名称

nameid
这使用 SAML NameID 值(删除所有前导和尾随空格)而不是 SAML 属性。SAML NameID 元素是 SAML 断言中可选但经常提供的字段,IdP 可以使用它来标识该断言的主题。在某些情况下,NameID 将与 IdP 中用户的登录标识符(用户名)相关,但在许多情况下,它们将是 IdP 之外没有明显含义的内部生成的标识符。
nameid:persistent
这使用 SAML NameID 值(删除所有前导和尾随空格),但前提是 NameID 格式为 urn:oasis:names:tc:SAML:2.0:nameid-format:persistent。SAML NameID 元素具有可选的 Format 属性,该属性指示所提供名称的语义。IdP 通常配置为使用“瞬态”NameID,这些 NameID 为每个会话提供一个新的标识符。由于使用瞬态 NameID 作为属性映射的一部分很少有用,因此可以使用“nameid:persistent”属性名称作为一种安全机制,如果您尝试从没有持久值的 NameID 进行映射,则会导致错误。

身份提供程序可以静态配置为发布具有特定格式的 NameID,也可以配置为尝试符合 SP 的要求。SP 使用称为 NameIDPolicy 的元素在其身份验证请求中声明其要求。如果需要,您可以设置名为 nameid_format 的相关设置,以请求 IdP 发布具有特定格式的 NameID

friendlyName
SAML 属性除了其基于 URI 的名称外,还可以具有*友好名称*。例如,名称为 urn:oid:0.9.2342.19200300.100.1.1 的属性也可能具有友好名称 uid。您可以在属性映射中使用这些友好名称,但建议您使用基于 URI 的名称,因为友好名称既不是标准化的也不是强制性的。

下面的示例配置了一个领域,该领域使用持久性 nameid 作为主体,并使用友好名称“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 用户属性编辑

可以将 Elasticsearch SAML 领域配置为将 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 属性中提取部分值编辑

在某些情况下,IdP 的属性可能包含的信息超出了您希望在 Elasticsearch 中使用的信息。一个常见的例子是 IdP 专门使用电子邮件地址,但您希望用户的 principal 使用电子邮件地址的*本地名称*部分。例如,如果他们的电子邮件地址是 [email protected],那么您希望他们的主体只是 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 开头的任何电子邮件地址,这将接受诸如 [email protected] 之类的电子邮件地址。重要的是要确保您的正则表达式尽可能精确,以免无意中为用户冒充攻击打开方便之门。

请求特定的身份验证方法编辑

有时,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 断言的身份验证语句一部分的身份验证上下文类引用的值。如果它与其中一个请求的值匹配,则认为身份验证成功。否则,身份验证尝试失败。

SAML 注销编辑

SAML 协议支持单点注销 (SLO) 的概念。对 SLO 的支持级别因身份提供者而异。您应该查阅 IdP 的文档以确定它提供哪些注销服务。

默认情况下,如果满足以下条件,Elastic Stack 将支持 SAML SLO

  • 您的 IdP 元数据指定 IdP 提供 SLO 服务
  • 您的 IdP 在为您的用户发布的 SAML 断言的主题中发布 NameID
  • 您配置了 sp.logout
  • 设置 idp.use_single_logout 不是 false
IdP SLO 服务编辑

Elasticsearch 从 IdP 的 SAML 元数据中读取的值之一是 <SingleLogoutService>。为了使单点注销与 Elastic Stack 一起使用,Elasticsearch 要求它存在并支持 urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect 的绑定。

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

sp.logout 设置编辑

Elasticsearch 领域设置 sp.logout 指定了 Kibana 中的一个 URL,IdP 可以向其发送 <LogoutRequest><LogoutResponse> 消息。此服务使用 SAML HTTP-Redirect 绑定。

Elasticsearch 将处理 <LogoutRequest> 消息,并执行全局注销,使与提供的 SAML 会话关联的任何现有 Elasticsearch 安全令牌失效。

如果您没有为 sp.logout 配置值,Elasticsearch 将拒绝所有 <LogoutRequest> 消息。

IdP 通常要求对 LogoutRequest 消息进行签名,因此您可能需要配置签名凭据

idp.use_single_logout 设置编辑

如果您的 IdP 提供了 <SingleLogoutService> 但您不想使用它,则可以在 SAML 领域中配置 idp.use_single_logout: false,Elasticsearch 将忽略您的 IdP 提供的 SLO 服务。在这种情况下,当用户注销 Kibana 时,它将使其 Elasticsearch 会话(安全令牌)失效,但不会在 IdP 处执行任何注销。

在没有单点注销的情况下使用 Kibana编辑

如果您的 IdP 不支持单点注销,或者您选择不使用它,则 Kibana 将仅执行“本地注销”。

这意味着 Kibana 将使其用于与 Elasticsearch 通信的会话令牌失效,但将无法对身份提供者会话执行任何类型的失效。在大多数情况下,这意味着 Kibana 用户仍被视为已登录到 IdP。因此,如果用户导航到 Kibana 登录页面,他们将被自动重新验证,并将在无需输入任何凭据的情况下开始新的 Kibana 会话。

此问题的可能解决方案是

  • 要求您的 IdP 管理员或供应商提供单点注销服务
  • 如果您的 Idp 确实提供了单点注销服务,请确保它包含在 IdP 元数据文件中,并且*不要*将 idp.use_single_logout 设置为 false
  • 建议您的用户在注销 Kibana 后关闭浏览器
  • 在您的 SAML 领域上启用 force_authn 设置。此设置会导致 Elastic Stack 在每次用户尝试登录 Kibana 时都从 IdP 请求新的身份验证。此设置默认为 false,因为它可能会带来更麻烦的用户体验,但它也可以有效地防止用户搭载现有 IdP 会话的便车。

加密和签名编辑

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 或本地策略强制使用它们的情况。

生成证书和密钥编辑

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 以进行签名编辑

默认情况下,如果已配置签名密钥,则 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 密钥库**进行签名,则应在 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 以进行加密消息编辑

Elasticsearch 安全功能支持使用单个密钥进行消息解密。如果配置了密钥,则 Elasticsearch 会尝试使用它来解密身份验证响应中的 EncryptedAssertionEncryptedAttribute 元素,以及注销请求中的 EncryptedID 元素。

Elasticsearch 拒绝任何包含无法解密的 EncryptedAssertion 的 SAML 消息。

如果 Assertion 同时包含加密属性和纯文本属性,则无法解密加密属性不会导致自动拒绝。 相反,Elasticsearch 会处理可用的纯文本属性(以及任何可以解密的 EncryptedAttributes)。

如果您希望将 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 密钥库 用于 SAML 加密,则应在 SAML 领域配置以下设置

encryption.keystore.path
PKCS#12 或 JKS 密钥库的路径。 例如 saml/saml-crypt.p12
encryption.keystore.alias
密钥库中密钥的别名。 例如 encryption-key
encryption.keystore.secure_password
密钥库的密码,如果文件已加密。这是一个安全设置,必须使用 elasticsearch-keystore 工具进行设置。

生成 SP 元数据编辑

一些身份提供程序支持从服务提供程序导入元数据文件。 这将自动配置 IdP 和 SP 之间的许多集成选项。

Elastic Stack 支持使用 bin/elasticsearch-saml-metadata 命令SAML 服务提供程序元数据 API 生成此类元数据文件。

您可以通过向 Elasticsearch 发出 API 请求来生成 SAML 元数据,并使用 jq 等工具将其存储为 XML 文件。 例如,以下命令为 SAML 领域 realm1 生成元数据并将其保存到 metadata.xml 文件中

curl -u user_name:password  -X GET https://127.0.0.1:9200/_security/saml/metadata/saml1 -H 'Content-Type: application/json' | jq -r '.[]' > metadata.xml

配置角色映射编辑

当用户使用 SAML 进行身份验证时,他们会在 Elastic Stack 中被识别,但这不会自动授予他们执行任何操作或访问任何数据的权限。

在分配角色之前,您的 SAML 用户无法执行任何操作。 这可以通过 添加角色映射 API授权领域 来完成。

您不能使用 角色映射文件 来向通过 SAML 进行身份验证的用户授予角色。

这是一个简单角色映射的示例,该映射向任何针对 saml1 领域进行身份验证的用户授予 example_role 角色

PUT /_security/role_mapping/saml-example
{
  "roles": [ "example_role" ], 
  "enabled": true,
  "rules": {
    "field": { "realm.name": "saml1" }
  }
}

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

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

提供给角色映射的用户字段派生自 SAML 属性,如下所示

  • usernameprincipal 属性
  • dndn 属性
  • groupsgroups 属性
  • metadata:请参阅 用户元数据

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

如果您的 IdP 能够向服务提供程序提供组或角色,则您应该在 Elasticsearch 领域中将此 SAML 属性映射到 attributes.groups 设置,然后按照以下示例在角色映射中使用它。

此映射将 Elasticsearch finance_data 角色授予任何通过 saml1 领域进行身份验证并具有 finance-team 组的用户。

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 中创建的领域的名称。

用户元数据编辑

默认情况下,通过 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 领域中添加 populate_user_metadata: false 作为设置来禁用此行为。

配置 Kibana编辑

除了标准 Kibana 安全配置之外,Kibana 中的 SAML 身份验证还需要少量额外设置。 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 和基本身份验证编辑

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 实例编辑

如果您希望拥有多个针对同一个 Elasticsearch 集群进行身份验证的 Kibana 实例,则为 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 实例,而其他实例使用针对另一种领域类型(例如 本机LDAP)的基本身份验证。

SAML 领域配置故障排除编辑

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

没有 Kibana 的 SAML编辑

Elasticsearch 中的 SAML 领域旨在允许用户对 Kibana 进行身份验证,因此,上述指南的大部分内容都假设使用了 Kibana。 本节介绍自定义 Web 应用程序如何使用相关的 SAML REST API 以使用 SAML 对 Elasticsearch 中的用户进行身份验证。

本节假设读者熟悉 SAML 2.0 标准,尤其是 SAML 2.0 Web 浏览器单点登录配置文件。

单点登录领域(如 OpenID Connect 和 SAML)利用 Elasticsearch 中的令牌服务,原则上将 SAML 或 OpenID Connect 身份验证响应交换为 Elasticsearch 访问令牌和刷新令牌。 访问令牌用作后续调用 Elasticsearch 的凭据。 刷新令牌使用户能够在当前访问令牌过期后获取新的 Elasticsearch 访问令牌。

SAML 领域编辑

您必须创建一个 SAML 领域并在 Elasticsearch 中对其进行相应配置。 请参阅 为 SAML 身份验证配置 Elasticsearch

用于访问 API 的服务帐户用户编辑

该领域的设计假设需要一个特权实体充当身份验证代理。 在这种情况下,自定义 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 发起的身份验证流程编辑

在较高的级别上,自定义 Web 应用程序需要执行以下步骤才能使用 SAML 对 Elasticsearch 中的用户进行身份验证

  1. _security/saml/prepare 发出 HTTP POST 请求,以 saml-service-user 用户身份进行身份验证。 在请求正文中使用 Elasticsearch 配置中的 SAML 领域名称或断言使用者服务 URL 的值。 有关更多详细信息,请参阅 SAML 准备身份验证 API

    POST /_security/saml/prepare
    {
      "realm" : "saml1"
    }
  2. 处理来自 /_security/saml/prepare 的响应。 Elasticsearch 的响应将包含 3 个参数:redirectrealmid。 自定义 Web 应用程序需要将 id 的值存储在用户的会话中(如果以这种方式持久保存会话信息,则在 cookie 中存储在客户端或服务器端)。 它还必须将用户的浏览器重定向到 redirect 参数中返回的 URL。 id 值不应被忽略,因为它在 SAML 中用作随机数,以防止重放攻击。
  3. 处理来自 SAML IdP 的后续响应。 用户使用身份提供商成功进行身份验证后,他们将被重定向回断言使用者服务 URL。 此 sp.acs 需要定义为自定义 Web 应用程序处理的 URL。 当它收到此 HTTP POST 请求时,自定义 Web 应用程序必须对其进行解析,并向 _security/saml/authenticate API 发出 HTTP POST 请求。 它必须以 saml-service-user 用户身份进行身份验证,并传递作为请求正文发送的 Base64 编码的 SAML 响应。 它还必须传递之前保存在用户会话中的 id 的值。

    有关更多详细信息,请参阅 SAML 身份验证 API

    POST /_security/saml/authenticate
    {
      "content" : "PHNhbWxwOlJlc3BvbnNlIHhtbG5zOnNhbWxwPSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6cHJvdG9jb2wiIHhtbG5zOnNhbWw9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMD.....",
      "ids" : ["4fee3b046395c4e751011e97f8900b5273d56685"]
    }

    Elasticsearch 将对此进行验证,如果一切正确,将使用访问令牌进行响应,该令牌可以用作后续请求的 Bearer 令牌。 它还提供了一个刷新令牌,稍后可以使用该令牌来刷新给定的访问令牌,如 获取令牌 API 中所述。

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

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

Elasticsearch 还可以处理 SAML 2 Web 浏览器 SSO 配置文件的 IdP 发起的单点登录流程。 在这种情况下,身份验证从 SAML 身份提供商发出的未经请求的身份验证响应开始。 与 SP 发起的 SSO 的区别在于,Web 应用程序需要处理对 sp.acs 的请求,这些请求不会作为对先前重定向的响应。 因此,它不会为用户预先创建会话,并且不会为 id 参数存储任何值。 在这种情况下,对 _security/saml/authenticate API 的请求将类似于以下内容

POST /_security/saml/authenticate
{
  "content" : "PHNhbWxwOlJlc3BvbnNlIHhtbG5zOnNhbWxwPSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6cHJvdG9jb2wiIHhtbG5zOnNhbWw9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMD.....",
  "ids" : []
}

处理注销流程编辑

  1. 在某些时候,如果需要,自定义 Web 应用程序可以通过使用 SAML 注销 API 并传递访问令牌和刷新令牌作为参数来注销用户。 例如

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

    如果 SAML 领域已相应配置并且 IdP 支持它(请参阅 SAML 注销),则此请求将触发 SP 发起的 SAML 单点注销。 在这种情况下,响应将包含一个 redirect 参数,指示需要在 IdP 处将用户重定向到哪里才能完成注销。

  2. 或者,IdP 可能会在某个时候启动单点注销流程。 为了处理这种情况,注销 URL (sp.logout) 需要由自定义 Web 应用程序处理。 用户将被重定向到的 URL 的查询部分将包含一个 SAML 注销请求,并且需要使用 SAML 使无效 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 应用程序还需要处理响应,该响应将包含一个 redirect 参数,其中包含 IdP 中包含 SAML 注销响应的 URL。 应用程序应将用户重定向到那里以完成注销。

对于 SP 发起的单点注销,IdP 可能会发回一个注销响应,Elasticsearch 可以使用 SAML 完成注销 API 对其进行验证。