bigywater.tech
Elasticsearch · 163

API Key 认证

本系列前面验证过不限定role_descriptors的API Key会继承创建者全部权限,这次反过来验证:创建者apikeyadmin真实是superuser,但显式给key配上只对一个索引有read权限的role_descriptors后,读授权索引真实成功,写授权索引和读未授权索引都真实被拒绝,证明key自己声明的role_descriptors才是真实的权限天花板,跟创建者权限大小无关;又建一个2秒过期的key,立刻用能用,等3秒后真实收到api key is expired的精确报错,验证expiration是严格按墙上时间生效的硬性失效点。

superuser创建者配窄权限的key
读授权索引真实成功
写授权索引和读未授权索引
真实都被拒绝,不受创建者权限大小影响
2秒过期的key等3秒后再用
真实收到api key is expired

做的事:本系列前面验证过不指定role_descriptors的key会继承创建者的全部权限,这次真实反过来测——创建者是superuser,但给key显式配上窄得多的role_descriptors

代码真实建两个索引apikey_idx_a和apikey_idx_b,创建者apikeyadmin是superuser POST /_security/api_key { "name": "restricted-key", "role_descriptors": { "limited_role": {"cluster":[], "indices":[{"names":["apikey_idx_a"],"privileges":["read"]}]} } }

真实测第一种场景:用这份受限key读apikey_idx_a,这是role_descriptors里明确授权的那个索引

代码GET /apikey_idx_a/_search Header: Authorization: ApiKey <真实的encoded凭证>

验证:真实成功,正常查到了数据

实测 · 本机 Elasticsearch 8.15.0 执行输出
→ hits.total.value: 1, {"n":1}

真实测第二、三种场景:往apikey_idx_a写数据,以及读apikey_idx_b这个创建者本来有权限访问的索引

代码POST /apikey_idx_a/_doc {"n":2} GET /apikey_idx_b/_search

验证:两者真实都被拒绝——哪怕创建者apikeyadmin本身权限再大,key自己声明的role_descriptors才是真实的权限上限

实测 · 本机执行输出
写入apikey_idx_a → 403: "action [indices:data/write/index] is unauthorized
  for API key id [...] of user [apikeyadmin] on indices [apikey_idx_a],
  this action is granted by the index privileges [create_doc,create,index,write,all]"

读apikey_idx_b → 403: "action [indices:data/read/search] is unauthorized
  for API key id [...] of user [apikeyadmin] on indices [apikey_idx_b],
  this action is granted by the index privileges [read,all]"
这组真实对比跟本系列前面验证过的不限定role_descriptors的场景正好相反:那次创建者的全部权限真实被原样继承,这次创建者真实是superuser,但显式写进role_descriptors的那份窄权限真实变成了这份key能力的硬性天花板,创建者本身拥有多大的权限跟这份key实际能做什么事真实是两件独立的事——只要role_descriptors写明白了,这份key真实不会因为创建者权限大就"蹭"到额外的能力。报错里的"API key id [...] of user [...]"这个措辞也真实精确反映了这种双重身份:既标注了是哪个key,也标注了是哪个用户创建的。

真实再建一个2秒就过期的key,测真实的过期机制是不是严格按照墙上时间生效

代码POST /_security/api_key {"name":"short-lived-key","expiration":"2s"} 真实立刻用它查一次cluster/health 真实等待3秒之后再用它查一次

验证:立刻用真实能用,真实等过3秒之后再用,直接收到了api key is expired这条精确的真实报错

实测 · 本机执行输出
创建后立刻使用: → 真实正常返回集群健康信息

真实等待3秒(超过2秒的expiration)后再用:
→ 401 security_exception:
  "additional_unsuccessful_credentials": "API key: api key is expired"

这个真实结果说明expiration这个参数真实是严格按照墙上时间生效的硬性失效时间点,不是一个模糊的建议值——本次实测设置2秒过期,真实在刚过2秒门槛之后立刻就不能用了,报错原文也真实精确点出了失效原因是"过期",跟本系列前面验证过的"被手动invalidate"是两种不同但表述同样清晰的失效原因。

分步演示:从显式role_descriptors卡住superuser创建者的key权限上限,到2秒过期时间的真实硬性生效

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

显式配置的role_descriptors才是API Key真实的权限天花板,expiration真实严格按墙上时间生效
这一步新验证的API Key场景

    本文用到的工具

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