bigywater.tech
Elasticsearch · 158

Elasticsearch 用户认证

本机真实开启security用file realm建一个用户,_authenticate确认它真实通过default_file这个realm认证且角色为superuser;真实创建一份API Key并用Authorization:ApiKey头认证成功,但_authenticate返回的roles字段真实是空的[];真实拿这个看起来无权限的key去建索引却成功了,因为没指定role_descriptors的API Key会原样继承创建者的全部权限;最后真实invalidate这个key,再认证时报错明确点名是哪个key失效,揭示了API Key认证结果展示与实际有效权限之间容易被误判的真实差异。

file realm用户认证
_authenticate真实确认走default_file这个realm
用API Key认证
真实成功但roles字段真实是空的[]
拿空roles的key建索引
真实成功,因为继承了创建者的全部权限

做的事:本机真实开启security,用file realm建一个真实的用户,查_security/_authenticate确认它是通过哪个真实的realm认证的

代码真实用elasticsearch-users工具建用户: authuser / superuser角色 真实用基本认证访问: GET /_security/_authenticate

验证:真实确认这个用户是通过default_file这个realm认证的,角色真实精确显示为superuser

实测 · 本机 Elasticsearch 8.15.0 执行输出
{"username":"authuser","roles":["superuser"],
 "authentication_realm":{"name":"default_file","type":"file"},
 "authentication_type":"realm"}

这个真实结果说明_security/_authenticate这个接口不只是简单地告诉你"认证成功了",真实还会把这次认证走的是哪个realm(本次是基于本地文件的file realm)、真实匹配到了哪些角色都原样返回,方便排查"这次请求到底是用什么身份、什么权限在执行"。

真实用这个用户创建一份API Key,拿到真实的encoded凭证之后,改用Authorization: ApiKey这个头去认证

代码POST /_security/api_key {"name":"test-api-key"} → 真实返回encoded凭证 GET /_security/_authenticate Header: Authorization: ApiKey <真实的encoded凭证>

验证:真实认证成功了,但_authenticate返回的roles字段真实是空的[],看起来好像这个key啥权限都没有

实测 · 本机执行输出
{"username":"authuser","roles":[],   ← 真实是空的
 "authentication_type":"api_key",
 "api_key":{"name":"test-api-key","id":"NXMB-qAB818s1njuIAEY"}}

真实没有轻信这个空列表,直接拿这个key去建一个索引,看它到底有没有真实的权限

代码PUT /apikey_test Header: Authorization: ApiKey <真实的encoded凭证>

验证:真实成功了——因为没指定role_descriptors的API Key真实会原样继承创建者的全部权限,roles:[]这个空列表真实不代表没有权限

实测 · 本机执行输出
→ {"acknowledged":true,"shards_acknowledged":true,"index":"apikey_test"}
  真实建索引成功,哪怕_authenticate返回的roles真实是空的
这是一个真实容易造成误判的点:API Key真实有自己独立的权限模型,分成key自带的role_descriptors和创建者权限上限limited_by_role_descriptors这两层,本次实测创建key的时候没有指定任何role_descriptors,按照真实的默认规则,这意味着这份key真实不会被额外收窄权限,而是原样继承了创建者authuser的全部superuser权限——但_authenticate这个接口展示的roles字段真实只反映key自己声明的那部分,不包含继承自创建者的部分,所以真实看起来是空的,但实际权限真实完全不是空的。如果真实想审查一个API Key到底有什么权限,不能只看_authenticate返回的roles这一个字段就下结论,必须真实结合它的创建方式(有没有显式限制过role_descriptors)一起判断。

真实验证失效流程:把这个key真实invalidate掉,看拿它再认证会发生什么

代码DELETE /_security/api_key {"ids":["NXMB-qAB818s1njuIAEY"]} 真实拿失效后的key再认证: GET /_cluster/health

验证:拿它再认证真实立刻被拒绝,报错原文直接点名是哪个key被真实invalidate了

实测 · 本机执行输出
invalidate响应: {"invalidated_api_keys":["NXMB-qAB818s1njuIAEY"],"error_count":0}

再次认证: → 401 security_exception
  "additional_unsuccessful_credentials":
    "API key: api key [NXMB-qAB818s1njuIAEY] has been invalidated"

这个真实报错把失效原因交代得非常具体——不是笼统的"认证失败",而是真实明确点名了是这个特定的key因为被invalidate而失效,这对排查"某个集成突然连不上了"这类问题真实很有帮助,不需要靠猜测。

分步演示:从file realm用户认证,到API Key的roles空列表陷阱,再到真实的invalidate失效流程

每一步都是本文在一个真实独立搭建、开启security的Elasticsearch 8.15.0节点上跑出来的原始结果,测完即销毁。

API Key的roles字段看起来是空的不代表真实没有权限,要结合创建方式一起判断
这一步新验证的用户认证场景

    本文用到的工具

    • 真实独立搭建的Elasticsearch 8.15.0节点(开启security,测完即销毁)
    • 真实的 _security/_authenticate 与 _security/api_key API
    京ICP备2026067502号-1京公网安备11010502063487号