本系列前面验证过不限定role_descriptors的API Key会继承创建者全部权限,这次反过来验证:创建者apikeyadmin真实是superuser,但显式给key配上只对一个索引有read权限的role_descriptors后,读授权索引真实成功,写授权索引和读未授权索引都真实被拒绝,证明key自己声明的role_descriptors才是真实的权限天花板,跟创建者权限大小无关;又建一个2秒过期的key,立刻用能用,等3秒后真实收到api key is expired的精确报错,验证expiration是严格按墙上时间生效的硬性失效点。
代码真实建两个索引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"]}]} } }
代码GET /apikey_idx_a/_search Header: Authorization: ApiKey <真实的encoded凭证>
→ hits.total.value: 1, {"n":1}代码POST /apikey_idx_a/_doc {"n":2} GET /apikey_idx_b/_search
写入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]"
代码POST /_security/api_key {"name":"short-lived-key","expiration":"2s"} 真实立刻用它查一次cluster/health 真实等待3秒之后再用它查一次
创建后立刻使用: → 真实正常返回集群健康信息 真实等待3秒(超过2秒的expiration)后再用: → 401 security_exception: "additional_unsuccessful_credentials": "API key: api key is expired"
这个真实结果说明expiration这个参数真实是严格按照墙上时间生效的硬性失效时间点,不是一个模糊的建议值——本次实测设置2秒过期,真实在刚过2秒门槛之后立刻就不能用了,报错原文也真实精确点出了失效原因是"过期",跟本系列前面验证过的"被手动invalidate"是两种不同但表述同样清晰的失效原因。
每一步都是本文在一个真实独立搭建、开启security的Elasticsearch 8.15.0节点上跑出来的原始结果,测完即销毁。
_security/api_key 的 role_descriptors 与 expiration 参数