bigywater.tech
Elasticsearch · 160

Index Privileges

本机真实只给一个用户create_doc这一个索引权限,验证用POST新建全新文档真实成功,但用PUT覆盖已存在的文档真实被拒绝(需要create/index/write/all,create_doc不在名单里),删除文档同样被拒绝;最后用带op_type=create参数的PUT创建全新id真实也成功了,证明create_doc这个权限判定的是真实的操作语义(确保只有文档不存在时才创建)而不是HTTP方法本身。

只给create_doc权限新建文档
真实成功
用PUT覆盖已存在的文档
真实被拒绝,create_doc不在授权名单里
用op_type=create的PUT创建新id
真实成功,证明卡的是操作语义不是HTTP方法

做的事:本机真实给一个用户只授予create_doc这一个权限,不给index、write、delete,真实测它到底能做什么不能做什么

代码PUT /_security/role/create_only_role { "cluster": [], "indices": [{"names":["priv_test"],"privileges":["create_doc"]}] } 真实建用户createonlyuser绑定这个role 真实预先存在一条文档: PUT /priv_test/_doc/existing1

真实测第一种场景:用POST新建一条全新的文档(不指定id)

代码POST /priv_test/_doc {"n":2,"text":"brand new"}

验证:真实成功了,create_doc权限确实能新建文档

实测 · 本机 Elasticsearch 8.15.0 执行输出
→ {"result":"created", "_id":"CtUG-qAB5oeo0rbm7JJi"}

真实测第二种场景:用PUT去覆盖一条已经存在的文档existing1

代码PUT /priv_test/_doc/existing1 {"n":99,"text":"overwritten attempt"}

验证:真实被拒绝,报错里的内部action名真实是indices:data/write/index:op_type/index,需要的权限真实是create/index/write/all这几个,create_doc压根不在名单里

实测 · 本机执行输出
→ 403 security_exception:
  "action [indices:data/write/index:op_type/index] is unauthorized ...
   this action is granted by the index privileges [create,index,write,all]"

这个真实报错精确区分出了ES内部对"创建"和"覆盖写入"这两个语义完全不同的内部action——哪怕HTTP层面都是PUT请求,create_doc这个权限真实只认"保证文档此前不存在才允许创建"这一种语义,覆盖一条已经存在的文档真实需要的是create/index/write/all里的某一个,create_doc真实不在这个名单里。

真实测第三种场景:用DELETE删掉existing1这条文档

代码DELETE /priv_test/_doc/existing1

验证:真实也被拒绝,需要delete/write/all这几个权限

实测 · 本机执行输出
→ 403 security_exception:
  "action [indices:data/write/delete] is unauthorized ...
   this action is granted by the index privileges [delete,write,all]"

真实测第四种场景:用PUT配上显式的?op_type=create参数,去创建一个全新的id(不是覆盖已有文档)

代码PUT /priv_test/_doc/brandnew1?op_type=create {"n":3,"text":"new via PUT with op_type=create"}

验证:这次真实成功了,证明create_doc这个权限真实卡的不是HTTP方法本身,而是真实的操作语义

实测 · 本机执行输出
→ {"result":"created", "_id":"brandnew1"}   ← 真实用PUT也能创建,只要明确是create语义
这4次真实测试完整勾勒出了create_doc这个权限的真实判定边界:它真实不关心请求走的是POST还是PUT这个HTTP层面的区别,真实只关心这次操作的内部语义是不是"确保只有在文档不存在时才创建"——只要满足这一条,不管是不指定id的POST,还是带上op_type=create参数的PUT,都真实会被放行;一旦这次操作真实可能覆盖一条已经存在的文档(普通的PUT,不带op_type=create),哪怕表面上看起来"也是在写入数据",也真实不在create_doc的授权范围内,必须额外真实授予index、write或者all这几个权限之一才能通过。

分步演示:从create_doc能新建文档,到覆盖和删除被精确拒绝,再到op_type=create的PUT同样被放行的完整边界

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

create_doc权限真实判定的是操作语义而不是HTTP方法,只认准创建不认覆盖
这一步新验证的索引权限场景

    本文用到的工具

    • 真实独立搭建的Elasticsearch 8.15.0节点(开启security,测完即销毁)
    • 真实的 create_doc 索引权限与 op_type 参数
    京ICP备2026067502号-1京公网安备11010502063487号