6.5. 启用粘性会话
典型的集群部署由负载均衡器(反向代理)和 2 个或更多红帽在专用网络上构建 Keycloak 服务器。出于性能的需要,如果负载均衡器将与特定浏览器会话相关的所有请求转发到同一红帽构建的 Keycloak 后端节点,这可能很有用。
其原因在于,红帽构建的 Keycloak 使用 Infinispan 分布式缓存,覆盖之下,以保存与当前身份验证会话和用户会话相关的数据。Infinispan 分布式缓存默认配置为两个所有者。这意味着,特定的会话主要存储在两个集群节点上,而其他节点需要远程查找会话(如果想要访问它)。
例如,如果 ID 为 123 的验证会话保存在 node1 上的 Infinispan 缓存中,则 node2 需要通过网络向 node1 发送请求,以返回特定的会话实体。
如果特定的会话实体始终在本地可用,这可以通过粘性会话的帮助来完成。集群环境中的工作流带有公共前端负载均衡器,以及两个红帽构建的 Keycloak 节点,如下所示:
- 用户发送初始请求以查看红帽 Keycloak 登录屏幕的构建
- 此请求由 frontend 负载均衡器提供,该负载均衡器将其转发到一些随机节点(例如 node1)。严格说,节点不需要随机,但可以根据某些其他条件(客户端 IP 地址等)进行选择。它都取决于底层负载均衡器的实施和配置(反向代理)。
- 红帽构建的 Keycloak 使用随机 ID (如 123)创建身份验证会话,并将其保存到 Infinispan 缓存。
- Infinispan 分布式缓存根据会话 ID 的哈希值分配会话的主要所有者。有关此问题的更多详细信息,请参阅 Infinispan 文档。假设 Infinispan 分配 node2 是此会话的所有者。
- Red Hat build of Keycloak 创建 cookie AUTH_SESSION_ID,格式为 <session-id>.<owner-node-id>。在我们的示例中,它将为 123.node2。
- 使用红帽构建的 Keycloak 登录屏幕和浏览器中的 AUTH_SESSION_ID cookie 返回用户的响应
从此时,如果负载均衡器将所有下一个请求转发到 node2,因为这是 ID 为 123 的验证会话的所有者,因此 Infinispan 可以在本地查找此会话。身份验证完成后,身份验证会话将转换为用户会话,该会话也会保存在 node2 中,因为它具有相同的 ID 123。
集群设置的粘性会话不是强制的,但由于上述原因,最好是性能。您需要通过 AUTH_SESSION_ID cookie 将 loadbalancer 配置为粘性。具体操作取决于您的负载均衡器。
如果您的代理支持会话关联,而不处理来自后端节点的 Cookie,您应该将 spi-sticky-session-encoder-infinispan-should-attach-route
选项设为 false
,以避免将节点附加到 Cookie,并只依赖于反向代理功能。
bin/kc.[sh|bat] start --spi-sticky-session-encoder-infinispan-should-attach-route=false
默认情况下,spi-sticky-session-encoder-infinispan-should-attach-route
选项值为 true
,以便节点名称附加到 Cookie,以指示后续请求应发送到的反向代理。
6.5.1. 公开管理控制台
默认情况下,管理控制台 URL 仅基于请求来解析正确的方案、主机名和端口。例如,如果您使用 边缘
代理模式,且代理配置不正确,则来自 TLS 终止代理的后端请求将使用普通 HTTP,并可能导致管理控制台被访问,因为将使用 http
方案创建 URL,代理不支持普通 HTTP。
要正确公开管理控制台,您应该确保代理在这里设置 X-Forwarded
114 标头,以便使用代理公开的方案、主机名和端口来创建 URL。
6.5.2. 公开的路径建议
当使用反向代理时,红帽构建的 Keycloak 只需要公开某些路径。下表显示了要公开的推荐路径。
红帽构建的 Keycloak 路径 | 反向代理路径 | expose | 原因 |
---|---|---|---|
/ | - | 否 | 在公开所有路径时,管理路径会不必要地公开。 |
/admin/ | - | 否 | 公开的管理路径会导致不必要的攻击向量。 |
/js/ | - | 是(请参阅以下备注) | 访问"内部"客户端所需的 keycloak.js,例如帐户控制台 |
/welcome/ | - | 否 | 不需要在初始安装后公开欢迎页面。 |
/realms/ | /realms/ | 是 | 需要这个路径才能正常工作,例如对于 OIDC 端点。 |
/resources/ | /resources/ | 是 | 需要此路径才能正确提供资产。它可以从 CDN 而不是红帽构建的 Keycloak 路径提供。 |
/robots.txt | /robots.txt | 是 | 搜索引擎规则 |
/metrics | - | 否 | 公开的指标会导致不必要的攻击向量。 |
/health | - | 否 | 公开健康检查会导致不必要的攻击向量。 |
由于像帐户控制台等内部客户端需要 js
路径,因此最好使用 JavaScript 软件包管理器中的 keycloak.js
,如 npm 或 yarn 用于外部客户端。
我们假设您在反向代理/网关公共 API 的 root 路径 /
上运行红帽 Keycloak。如果没有,请使用您所需路径作为前缀。
6.5.3. 启用客户端证书查找
当代理配置为 TLS 终止代理时,客户端证书信息可以通过特定的 HTTP 请求标头转发到服务器,然后用于验证客户端。您可以根据您使用的代理,配置服务器如何检索客户端证书信息。
通过 X.509 身份验证的代理标头进行客户端证书查找被视为安全敏感。如果配置错误,则使用伪客户端证书标头进行身份验证。需要采取额外的预防措施,以确保在通过代理标头传递时可以信任客户端证书信息。
- 仔细检查您的用例需要重新加密或边缘 TLS 终止,这意味着使用代理标头进行客户端证书查找。当需要 X.509 身份验证时,建议使用 TLS passthrough 作为更安全的选项,因为它不需要通过代理标头传递证书。代理标头中的客户端证书查找仅适用于重新加密和边缘 TLS 终止。
如果 passthrough 不是一个选项,请实现以下安全措施:
- 配置网络,以便红帽构建的 Keycloak 被隔离,只能接受来自代理的连接。
-
确保代理覆盖
spi-x509cert-lookup-<provider>-ssl-client-cert
选项中配置的标头。 -
额外注意
spi-x509cert-lookup-<provider>-trust-proxy-verification
设置。请确保仅在信任代理以验证客户端证书时启用它。在没有代理验证客户端证书链的情况下,设置 spi-x509cert-lookup-<provider>-trust-proxy-verification=true
将红帽构建的 Keycloak 公开给安全漏洞。
服务器支持一些最常见的 TLS 终止代理,例如:
Proxy | 供应商 |
---|---|
Apache HTTP 服务器 | Apache |
HAProxy | hapoxy |
NGINX | nginx |
要配置如何从您需要的请求检索客户端证书:
启用对应的代理供应商
bin/kc.[sh|bat] build --spi-x509cert-lookup-provider=<provider>
配置 HTTP 标头
bin/kc.[sh|bat] start --spi-x509cert-lookup-<provider>-ssl-client-cert=SSL_CLIENT_CERT --spi-x509cert-lookup-<provider>-ssl-cert-chain-prefix=CERT_CHAIN --spi-x509cert-lookup-<provider>-certificate-chain-length=10
在配置 HTTP 标头时,您需要确保您使用的值对应于代理使用客户端证书信息转发的标头的名称。
用于配置供应商的可用选项有:
选项 | 描述 |
---|---|
ssl-client-cert | 保存客户端证书的标头名称 |
ssl-cert-chain-prefix |
标头在链中包含额外证书的前缀,用于相应地检索单个证书到链的长度。例如,值 |
certificate-chain-length | 证书链的最大长度。 |
trust-proxy-verification | 启用信任 NGINX 代理证书验证,而不是将证书转发到红帽构建的 Keycloak 并在红帽构建的 Keycloak 中进行验证。 |
6.5.3.1. 配置 NGINX 供应商
NGINX SSL/TLS 模块不会公开客户端证书链。红帽构建的 Keycloak 的 NGINX 证书查找供应商使用红帽构建的 Keycloak 信任存储重新构建它。
如果您使用此供应商,请参阅配置可信证书 以了解如何配置红帽构建的 Keycloak Truststore。