📣 极限科技诚招搜索运维工程师(Elasticsearch/Easysearch)- 全职/北京 👉 : 立即申请加入

适用版本: 8.x

1. 错误异常的基本描述 #

Can't get contents for setting [jwkSetConfigKeyPkc] value [jwkSetPathPkcUri] 表示 Elasticsearch 在读取 OpenID Connect(OIDC)或 JWT 认证配置中的 JSON Web Key(JWK)内容时失败。这个错误发生在读取动作本身,而不是后续的 JWK 解析阶段,意味着 Elasticsearch 无法获取到 JWK 数据。

常见现象 #

  • 节点启动或热加载安全配置时抛出 SettingsException,节点可能无法启动或安全配置加载失败。
  • 处理认证请求时失败,用户无法通过 OIDC/JWT 进行身份验证。
  • 日志中会出现具体的设置名和对应的文件路径或 URI。
  • 如果配置的是远程 JWK 地址,还可能伴随连接失败、超时、TLS 校验失败等异常。

典型报错与异常栈 #

典型错误信息如下:

SettingsException: Can't get contents for setting [xpack.security.authc.realms.jwt.jwt1.jwk_set_path] value [https://keycloak.example.com/realms/master/protocol/openid-connect/certs].

底层异常栈通常类似:

SettingsException: Can't get contents for setting [jwkSetConfigKeyPkc] value [jwkSetPathPkcUri].
    at org.elasticsearch.xpack.security.authc.jwt.JwtRealmSettings.getJwkContents(JwtRealmSettings.java:XX)
    at org.elasticsearch.xpack.security.authc.jwt.JwtRealm.<init>(JwtRealm.java:XX)
Caused by: IOException: Failed to fetch JWK from URI
    at org.elasticsearch.xpack.security.authc.jwt.JwtUtil.readBytes(...)

在 Elasticsearch 日志文件中可能会出现:

[ERROR][o.e.x.s.a.j.JwtRealmSettings] [node_name] failed to load JWK settings
SettingsException[Can't get contents for setting [xpack.security.authc.realms.jwt.jwt1.jwk_set_path] value [...]]

2. 为什么会发生这个错误 #

Can't get contents for setting [jwkSetConfigKeyPkc] value [jwkSetPathPkcUri] 异常由以下几种原因导致:

  • 本地 JWK 文件不存在或不可读:配置的 jwk_set_path 指向本地文件,但文件不存在、路径错误或 Elasticsearch 进程没有读取权限。
  • 远程 JWK URI 不可访问:配置的 JWK 端点(如 OIDC Provider 的 /certs 端点)网络不可达,可能被防火墙、代理或网络策略拦截。
  • TLS/SSL 证书问题:访问 HTTPS 类型的 JWK URI 时,Elasticsearch 不信任远程服务器的证书(自签名证书、证书链不完整等)。
  • DNS 解析失败:JWK URI 的主机名无法解析到正确的 IP 地址。
  • 代理配置问题:如果 Elasticsearch 需要通过代理访问外部 JWK URI,代理配置可能不正确。
  • 配置值格式不合法jwk_set_path 的值格式错误,导致底层读取器无法正确创建请求或打开文件。
  • URI 协议不支持:配置的 URI 协议(如 ftp://)不被 Elasticsearch 支持。

3. 如何排查和解决这个异常和解决这个异常 #

建议按以下步骤进行排查:

排查步骤 #

  1. 确认报错中的设置名和取值

查看日志中的完整错误信息,确定是哪个设置项和具体的值导致了问题。

  1. 如果是本地文件,检查文件是否存在和可读
# 检查文件是否存在
ls -la /path/to/jwk.json

# 检查文件权限
stat /path/to/jwk.json

# 切换到 elasticsearch 用户测试读取
sudo -u elasticsearch cat /path/to/jwk.json
  1. 如果是远程 URI,检查网络连通性
# 测试 DNS 解析
nslookup keycloak.example.com

# 测试网络连通性
curl -v https://keycloak.example.com/realms/master/protocol/openid-connect/certs

# 如果是 HTTPS,检查证书
openssl s_client -connect keycloak.example.com:443 -showcerts
  1. 检查 Elasticsearch 的 JWK 相关配置
# 查看当前 JWT/OIDC 配置
curl -X GET "localhost:9200/_cluster/settings?include_defaults=true&flat_settings=true" | grep -i "jwt\|oidc\|jwk"
  1. 查看完整的异常堆栈

在 Elasticsearch 日志中查找根因异常,确认是 IOException、证书错误、超时还是其他问题:

grep -A10 "Can't get contents for setting" /var/log/elasticsearch/elasticsearch.log

排查时需要注意的问题 #

  • 本地文件路径可以是绝对路径,也可以是相对于 Elasticsearch 配置目录($ES_PATH_CONF)的相对路径。
  • 如果使用远程 JWK URI,确保 Elasticsearch 节点能够访问该 URI,特别是在有网络限制的生产环境中。
  • JWK 内容应该是有效的 JSON 格式,但此错误发生在读取阶段,尚未到解析阶段。

4. 如何解决这个错误 #

常用修复思路 #

  1. 修正本地 JWK 文件路径
# 在 elasticsearch.yml 中配置
xpack.security.authc.realms.jwt.jwt1:
  order: 1
  jwk_set_path: "/etc/elasticsearch/jwk.json"  # 确保文件存在且可读

确保文件权限正确:

chown elasticsearch:elasticsearch /etc/elasticsearch/jwk.json
chmod 644 /etc/elasticsearch/jwk.json
  1. 修正远程 JWK URI 配置
xpack.security.authc.realms.jwt.jwt1:
  order: 1
  jwk_set_path: "https://keycloak.example.com/realms/master/protocol/openid-connect/certs"

如果远程 JWK 使用自签名证书,需要将 CA 证书添加到 Elasticsearch 的信任库:

# 将 CA 证书添加到 Java 信任库
keytool -import -alias custom-ca -file /path/to/ca.crt -keystore $JAVA_HOME/lib/security/cacerts
  1. 配置代理(如果需要)

如果 Elasticsearch 需要通过代理访问外部 JWK URI:

# 在 jvm.options 中添加代理设置
-Dhttp.proxyHost=proxy.example.com
-Dhttp.proxyPort=3128
-Dhttps.proxyHost=proxy.example.com
-Dhttps.proxyPort=3128
  1. 使用本地 JWK 文件作为替代方案

如果远程 JWK URI 不稳定,可以定期拉取 JWK 并保存为本地文件:

#!/bin/bash
# 定期更新 JWK 文件的脚本
JWK_URL="https://keycloak.example.com/realms/master/protocol/openid-connect/certs"
JWK_FILE="/etc/elasticsearch/jwk.json"

curl -s "$JWK_URL" > "$JWK_FILE"
chown elasticsearch:elasticsearch "$JWK_FILE"

后续注意事项与推荐建议 #

  • 对于生产环境,建议使用本地 JWK 文件副本,避免依赖外部服务的可用性。
  • 如果使用远程 JWK URI,设置监控来检查 JWK 端点的可用性。
  • JWK 内容可能会定期轮换,确保有机制来更新 JWK 配置。
  • 在变更 JWK 配置后,使用 curl 测试认证流程是否正常工作。

借助 INFINI 产品提升排障效率 #

  • INFINI Console 可以可视化查看和管理 Elasticsearch 集群的安全配置。通过 Console 的集群设置管理界面,可以快速检查和验证 JWT/OIDC 相关配置是否正确。Console 还提供节点日志聚合查看功能,帮助快速定位 JWK 加载失败的具体原因。

  • INFINI Gateway 部署在 Elasticsearch 前端时,虽然不直接处理 JWK 读取问题,但可以对认证请求进行监控。当 OIDC/JWT 认证失败时,Gateway 的请求日志可以帮助分析是 JWK 读取问题还是令牌验证问题。此外,如果 JWK 端点不稳定,可以考虑将 JWK 请求通过 Gateway 进行缓存和重试。

5. 小结 #

Can't get contents for setting [jwkSetConfigKeyPkc] value [jwkSetPathPkcUri] 是一个 JWK 内容读取失败的错误,根因是"拿不到内容"而非"内容解析失败"。解决这个问题的关键是:

  1. 首先确认 JWK 来源是本地文件还是远程 URI;
  2. 针对不同类型的来源,解决路径、权限、网络或证书问题;
  3. 修复读取问题后,再验证 JWK 内容本身是否可被正确解析。

通过 INFINI Console 进行安全配置管理,以及使用 INFINI Gateway 实现请求监控,可以更高效地排查和解决此类认证配置问题。

相关错误 #

参考文档 #

附:日志上下文 #

下面保留当前页面中的源码或日志片段,便于继续结合异常调用栈定位问题:

final CloseableHttpAsyncClient httpClient
 ) throws SettingsException {
 try {
 return JwtUtil.readBytes(httpClient; jwkSetPathPkcUri);
 } catch (Exception e) {
 throw new SettingsException("Can't get contents for setting [" + jwkSetConfigKeyPkc + "] value [" + jwkSetPathPkcUri + "]."; e);
 }
 }  public static byte[] readFileContents(final String jwkSetConfigKeyPkc; final String jwkSetPathPkc; final Environment environment)