关于 elasticsearch-security-troubleshooting
elasticsearch-security-troubleshooting 是用于排查和解决 Elasticsearch 安全问题的技能,供集群管理员和运维人员按症状执行诊断。它覆盖认证、权限、TLS、API 密钥、角色映射、Kibana 登录及许可证锁定,并采用收集、诊断、解决的流程。
主要功能
- 01诊断 401 与 403 错误
- 02排查 TLS 与证书问题
- 03检查 API 密钥状态和权限
- 04分析角色映射问题
- 05处理 Kibana 登录和许可证锁定
适用场景
- 01定位凭据导致的认证失败
- 02查明用户缺少索引访问权限的原因
- 03排查证书或 TLS 握手错误
- 04恢复许可证到期后的访问
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ elastic/ agent-skills --skill elasticsearch-security-troubleshooting安装后在 Claude Code 中输入/elasticsearch-security-troubleshooting确认已加载。
附带文件references/api-reference.md
详细介绍
Elasticsearch 安全故障排查
诊断并解决常见的 Elasticsearch 安全问题。本技能提供结构化的分诊工作流,用于处理身份验证失败、授权错误、TLS 问题、API 密钥问题、角色映射不匹配、Kibana 登录失败以及许可证过期导致的锁定。
有关身份验证方法和 API 密钥管理,请参阅 elasticsearch-authn 技能。有关角色、用户和角色映射,请参阅 elasticsearch-authz 技能。有关许可证管理,请参阅 elasticsearch-license 技能。
有关诊断 API 端点,请参阅 references/api-reference.md。
**部署说明:**自管理、ECH 和 Serverless 部署中的诊断 API 可用性各不相同。详情请参阅 部署兼容性。
待完成事项
- 诊断 HTTP 401 身份验证失败
- 诊断 HTTP 403 权限被拒绝错误
- 排查 TLS/SSL 握手或证书错误
- 调查过期或无效的 API 密钥
- 调试未授予预期角色的角色映射
- 修复 Kibana 登录失败、重定向循环或 CORS 错误
- 从许可证过期导致的锁定中恢复
- 确定用户为何无法访问特定索引
前提条件
| 项目 | 描述 |
|---|---|
| Elasticsearch URL | 集群端点(例如 https://localhost:9200 或 Cloud 部署 URL) |
| 身份验证 | 任意有效凭据,即使权限最低,也能访问集群 |
| 集群权限 | 只读诊断需要 monitor;修复需要 manage_security |
请向用户询问任何缺失的值。如果用户完全无法通过身份验证,请从 TLS 和证书错误或许可证过期恢复开始。
诊断工作流
根据症状跳转到相应部分:
| 症状 | 部分 |
|---|---|
HTTP 401,authentication_exception | 身份验证失败 |
HTTP 403,security_exception,访问被拒绝 | 授权失败 |
| SSL/TLS 握手错误,证书被拒绝 | TLS 和证书错误 |
| API 密钥被拒绝、已过期或不起作用 | API 密钥问题 |
| 角色映射未授予预期角色 | 角色映射问题 |
| Kibana 登录故障、重定向循环、CORS 错误 | Kibana 身份验证问题 |
| 所有用户均被锁定、付费功能已禁用 | 许可证过期恢复 |
每个部分都遵循收集 - 诊断 - 解决模式。
诊断工具集
在任何安全问题调查开始时使用这些 API:
curl <auth_flags> "${ELASTICSEARCH_URL}/_security/_authenticate"
确认身份、领域和角色。如果此请求因 401 而失败,问题出在身份验证。
curl <auth_flags> "${ELASTICSEARCH_URL}/_xpack"
确认安全功能是否已启用(features.security.enabled)。如果安全功能已禁用,所有安全 API 都会返回错误。
curl -X POST "${ELASTICSEARCH_URL}/_security/user/_has_privileges" \
<auth_flags> \
-H "Content-Type: application/json" \
-d '{
"index": [
{ "names": ["'"${INDEX_PATTERN}"'"], "privileges": ["read"] }
]
}'
测试经过身份验证的用户是否拥有特定权限,无需 manage_security。
curl <auth_flags> "${ELASTICSEARCH_URL}/_license"
检查许可证类型和状态。付费许可证过期后,付费领域和功能将被禁用。
身份验证失败(401)
401 响应表示 Elasticsearch 无法验证调用方的身份。
收集信息
curl -v <auth_flags> "${ELASTICSEARCH_URL}/_security/_authenticate" 2>&1
-v 标志会显示标头和响应正文。请查找:
WWW-Authenticate标头——指明集群接受哪些身份验证方案。- 响应正文中的
authentication_exception——reason字段会说明失败原因。
诊断
| 症状 | 可能原因 |
|---|---|
unable to authenticate user | 用户名或密码错误 |
unable to authenticate with provided credentials | 凭据与链中的任何 realm 都不匹配 |
user is not enabled | 原生用户账户已禁用 |
token is expired | API 密钥或 bearer token 已过期 |
没有 WWW-Authenticate 标头 | 安全功能可能已禁用;检查 GET /_xpack |
如果用户通过外部 realm(LDAP、AD、SAML、OIDC)进行身份验证,realm 链的顺序很重要。Elasticsearch 会按配置顺序尝试各个 realm,并在首次匹配时停止。如果优先级较高的 realm 在到达预期 realm 之前拒绝了凭据,身份验证就会失败。
解决
| 原因 | 操作 |
|---|---|
| 凭据错误 | 验证用户名/密码或 API 密钥值。参见 elasticsearch-authn。 |
| 用户已禁用 | PUT /_security/user/{name}/_enable。参见 elasticsearch-authz。 |
| API 密钥已过期 | 创建新的 API 密钥。参见 API 密钥问题。 |
| Realm 链顺序 | 检查 elasticsearch.yml 中的 realm 顺序(仅适用于自行管理的部署)。 |
| 安全功能已禁用 | 在 elasticsearch.yml 中启用 xpack.security.enabled: true 并重启。 |
| 付费 realm 在许可证过期后 | 许可证已过期——参见许可证过期恢复。 |
授权失败(403)
403 响应表示用户已通过身份验证,但缺少所需的权限。
收集信息
测试操作所需的具体权限:
curl -X POST "${ELASTICSEARCH_URL}/_security/user/_has_privileges" \
<auth_flags> \
-H "Content-Type: application/json" \
-d '{
"index": [
{ "names": ["logs-*"], "privileges": ["read", "view_index_metadata"] }
],
"cluster": ["monitor"]
}'
响应包含一个 has_all_requested 布尔值以及按资源划分的详细信息。
另请检查用户的有效角色:
curl <auth_flags> "${ELASTICSEARCH_URL}/_security/_authenticate"
检查 roles 数组和 authentication_realm,确认该用户是你预期的用户。
诊断
| 症状 | 可能原因 |
|---|---|
对索引而言,has_all_requested: false | 角色缺少所需的索引权限 |
对集群而言,has_all_requested: false | 角色缺少所需的集群权限 |
| 用户拥有的角色少于预期 | 上次更新时角色数组被替换(而非合并) |
| API 密钥对之前允许的操作返回 403 | API 密钥权限是一个快照——角色变更不会应用到已有密钥 |
| 操作 | 创建后不会应用到已有密钥 |
解决
| 原因 | 处理方法 |
|---|---|
| 缺少索引权限 | 将该权限添加到角色中,或创建新角色。参见 elasticsearch-authz。 |
| 缺少集群权限 | 添加集群权限。参见 elasticsearch-authz。 |
| 更新时角色被替换 | 先获取当前角色,再使用完整数组更新。参见 elasticsearch-authz。 |
| API 密钥权限过期 | 使用更新后的 role_descriptors 创建新的 API 密钥。参见 elasticsearch-authn。 |
TLS 和证书错误
TLS 错误会导致客户端完全无法建立连接。
收集信息
curl -v --cacert "${CA_CERT}" "https://${ELASTICSEARCH_HOST}:9200/" 2>&1 | head -30
请留意:
SSL certificate problem: unable to get local issuer certificate— CA 不受信任。SSL certificate problem: certificate has expired— 证书已过有效期。SSL: no alternative certificate subject name matches target host name— 主机名不匹配。
如需深入检查(仅限自管理):
openssl s_client -connect "${ELASTICSEARCH_HOST}:9200" -showcerts </dev/null 2>&1
这会显示完整的证书链、到期日期和主题备用名称。
诊断
| 错误消息 | 可能原因 |
|---|---|
unable to get local issuer certificate | 缺少 CA 证书或 CA 证书不正确 |
certificate has expired | 服务器证书或 CA 证书已过期 |
no alternative certificate subject name matches | 证书 SAN 中不包含该主机名 |
self-signed certificate | 信任存储中没有自签名证书 |
SSLHandshakeException(Java 客户端) | 信任存储缺少 CA 证书或密码错误 |
解决
| 原因 | 处理方法 |
|---|---|
| CA 证书不正确 | 使用 --cacert 指定正确的 CA,或将其添加到系统信任存储中。 |
| 证书已过期 | 使用 elasticsearch-certutil 重新生成证书(自管理)。 |
| 主机名不匹配 | 使用正确的 SAN 条目重新生成证书。 |
| 自签名证书 | 将 CA 证书分发给所有客户端,或使用公开受信任的 CA。 |
| 临时解决方法 | 使用 curl -k / --insecure 跳过验证。不适用于生产环境。 |
在 ECH 上,TLS 由 Elastic 管理 — 证书错误通常表示客户端未使用正确的 Cloud 端点 URL。在 Serverless 上,TLS 完全由系统管理且对用户透明。
API 密钥问题
收集信息
获取密钥的元数据:
curl "${ELASTICSEARCH_URL}/_security/api_key?name=${KEY_NAME}" <auth_flags>
检查响应中的 expiration、invalidated 和 role_descriptors。
诊断
| 症状 | 可能原因 |
|---|---|
| 使用密钥时返回 401 | 密钥已过期或已失效 |
| 对本应允许的操作返回 403 | 创建密钥时使用的 role_descriptors 权限不足 |
| 派生密钥没有访问权限 | API 密钥创建了另一个 API 密钥 — 派生密钥没有权限 |
| 密钥对部分索引有效,但对其他索引无效 | role_descriptors 的作用范围太窄 |
解决
| 原因 | 操作 |
|---|---|
| 密钥已过期 | 创建具有适当 expiration 的新密钥。请参阅 elasticsearch-authn。 |
| 密钥已失效 | 创建新密钥。失效的密钥无法恢复。 |
| 范围错误 | 创建具有正确 role_descriptors 的新密钥。请参阅 elasticsearch-authn。 |
| 派生密钥问题 | 改用用户凭据调用 POST /_security/api_key/grant。请参阅 elasticsearch-authn。 |
角色映射问题
角色映射会为来自外部域的用户授予角色。如果映射未生效,用户虽然能够通过身份验证,却不会获得任何角色。
收集信息
curl <auth_flags> "${ELASTICSEARCH_URL}/_security/_authenticate"
记下 username、authentication_realm.name 和 roles 数组。
curl <auth_flags> "${ELASTICSEARCH_URL}/_security/role_mapping"
列出所有映射,并检查其 rules 和 enabled 字段。
诊断
| 症状 | 可能原因 |
|---|---|
用户的 roles 数组为空 | 没有映射与该用户的属性匹配 |
| 用户获得了错误的角色 | 更早匹配了其他映射,或规则范围过宽 |
| 映射存在,但未生效 | enabled 为 false |
| Mustache 模板生成了错误的角色名称 | 模板语法错误或属性值与预期不符 |
将用户的 authentication_realm.name 和 groups(来自 _authenticate)与每个映射的 rules 进行比较,
找出不匹配之处。
解决
| 原因 | 操作 |
|---|---|
| 没有匹配的规则 | 更新映射规则,使其匹配用户的域和属性。 |
| 映射已禁用 | 在映射上设置 "enabled": true。 |
| 模板错误 | 使用已知属性值测试 Mustache 模板。请参阅 elasticsearch-authz。 |
| 规则范围过宽 | 添加 all / except 条件以缩小匹配范围。请参阅 elasticsearch-authz。 |
Kibana 身份验证问题
缺少 kbn-xsrf 标头
所有会修改数据的 Kibana API 请求都需要 kbn-xsrf 标头:
curl -X PUT "${KIBANA_URL}/api/security/role/my-role" \
<auth_flags> \
-H "kbn-xsrf: true" \
-H "Content-Type: application/json" \
-d '{ ... }'
如果缺少该标头,Kibana 会返回 400 Bad Request,并显示 "Request must contain a kbn-xsrf header"。
SAML/OIDC 重定向循环
常见原因:
elasticsearch.yml中的xpack.security.authc.realms.saml.*.sp.acs或idp.metadata.path配置不正确。- IdP 与 Elasticsearch 节点之间存在时钟偏差(SAML 断言有有效时间窗口)。
- Kibana 的
server.publicBaseUrl与 SAML ACS URL 不匹配。
验证 SAML 域配置:
curl <auth_flags> "${ELASTICSEARCH_URL}/_security/_authenticate"
如果这会通过非 SAML 域返回有效用户,则说明请求未到达 SAML 域。请检查域链顺序。
Kibana 无法连接 Elasticsearch
Kibana 日志显示 Unable to retrieve version information from Elasticsearch nodes。请验证 kibana.yml 中的 elasticsearch.hosts
设置指向可访问的端点,并确认凭据(elasticsearch.username / elasticsearch.password
或 elasticsearch.serviceAccountToken)有效。
许可证过期恢复
付费许可证过期后,集群会进入安全关闭状态:付费域(SAML、LDAP、AD、PKI)将停止工作,通过这些域进行身份验证的用户会被锁定。原生域和文件域仍可正常工作。
快速排查
curl <auth_flags> "${ELASTICSEARCH_URL}/_license"
如果 license.status 为 "expired",请继续进行恢复。
恢复步骤
请按照 elasticsearch-license 技能中的详细恢复工作流操作。关键的第一步取决于 部署类型:
| 部署方式 | 第一步 |
|---|---|
| 自行管理 | 使用基于文件的用户(elasticsearch-users CLI)或原生用户登录。 |
| ECH | 联系 Elastic 支持,或通过 Cloud 控制台续订。 |
| Serverless | 不适用——许可完全由 Elastic 管理。 |
示例
用户查询日志时收到 403
症状:“我搜索 logs-* 时收到 403。”
- 验证身份:
curl -u "joe:${PASSWORD}" "${ELASTICSEARCH_URL}/_security/_authenticate"
响应显示 "roles": ["viewer"]。
- 测试权限:
curl -X POST "${ELASTICSEARCH_URL}/_security/user/_has_privileges" \
-u "joe:${PASSWORD}" \
-H "Content-Type: application/json" \
-d '{"index": [{"names": ["logs-*"], "privileges": ["read"]}]}'
响应为:"has_all_requested": false——viewer 角色不包含对 logs-* 的 read 权限。
- 修复:创建
logs-reader角色并将其分配给 Joe。请参阅 elasticsearch-authz。
API 密钥停止工作
症状:“我的 API 密钥从昨天开始返回 401。”
- 检查密钥:
curl -u "admin:${PASSWORD}" "${ELASTICSEARCH_URL}/_security/api_key?name=my-key"
响应显示 "expiration": 1709251200000——密钥已过期。
- 修复:创建具有合适
expiration的新 API 密钥。请参阅 elasticsearch-authn。
SAML 登录重定向到错误页面
症状:“点击 Kibana 中的 SSO 按钮后,页面重定向到了错误页面。”
- 使用非 SAML 方法进行身份验证,检查 SAML realm 是否可访问:
curl -u "elastic:${PASSWORD}" "${ELASTICSEARCH_URL}/_security/_authenticate"
- 验证 Elasticsearch 节点是否可以访问 IdP 元数据 URL(自行管理):
curl -s "${IDP_METADATA_URL}" | head -5
- 检查时钟偏差——SAML 断言对时间很敏感。确保所有节点都配置了 NTP。
- 验证
kibana.yml中的server.publicBaseUrl是否与 IdP 中配置的 SAML ACS URL 一致。
许可证过期后用户无法登录
症状:“没有人能登录 Kibana。我们使用 SAML。”
- 检查许可证:
curl -u "admin:${PASSWORD}" "${ELASTICSEARCH_URL}/_license"
响应显示 "status": "expired"、"type": "platinum"。
- 付费许可证过期后,SAML realm 会被禁用。请按照 elasticsearch-license 中的恢复步骤操作: 使用基于文件的用户或原生用户登录,然后上传续订后的许可证,或恢复为 basic。
指南
始终从 _authenticate 开始
将 GET /_security/_authenticate 作为第一步诊断操作。一次调用即可显示用户的身份、realm、角色和
身份验证类型。仅凭此响应通常就能发现大多数问题。
尽早检查许可证
在调查 realm 或权限问题之前,使用 GET /_license 验证许可证是否有效。付费许可证过期会禁用 realm 和功能,导致出现类似配置错误的症状。
手动检查前先使用 _has_privileges
不要阅读角色定义并手动推算有效访问权限,而应使用 POST /_security/user/_has_privileges
直接测试特定权限。这样更快,也会考虑角色组合、DLS 和 FLS。
避免使用超级用户凭据
切勿使用内置的 elastic 超级用户进行日常故障排查。创建专用管理员用户或具有
manage_security 权限的 API 密钥。仅在初始设置和紧急恢复时使用 elastic 用户。
不要在生产环境中绕过 TLS
使用 curl -k 或 --insecure 会跳过证书验证,并掩盖真实的 TLS 问题。仅将其用于初步
诊断,然后修复根本的证书问题。
部署兼容性
不同部署类型所提供的诊断工具和 API 各不相同。
| 工具 / API | 自行管理 | ECH | 无服务器 |
|---|---|---|---|
_security/_authenticate | 是 | 是 | 是 |
_security/user/_has_privileges | 是 | 是 | 是 |
_xpack | 是 | 是 | 有限 |
_license | 是 | 是(读取) | 不可用 |
_security/api_key (GET) | 是 | 是 | 是 |
_security/role_mapping | 是 | 是 | 是 |
elasticsearch-users CLI | 是 | 不可用 | 不可用 |
节点上的 openssl s_client | 是 | 不可用 | 不可用 |
| Elasticsearch 日志 | 是 | 通过 Cloud UI | 通过 Cloud UI |
ECH 说明:
- 无法访问节点,因此无法使用
elasticsearch-usersCLI,也无法直接检查日志或证书。 - TLS 由 Elastic 管理 — 证书错误通常表示端点 URL 不正确。
- 使用 Cloud 控制台检查日志和部署配置。
无服务器说明:
- 不提供许可 API,因此不会发生与许可证相关的锁定。
- 不存在原生用户 — 身份验证问题在组织级别处理。
- TLS 完全由系统管理,且对用户透明。