bigywater.tech
Elasticsearch · 161

Document Level Security

本机真实先验证document level security功能在basic许可证下被直接拒绝(跟审计日志一样被license等级卡着),用ES自带的trial许可证激活后同样的role配置真实创建成功;真实测试受限用户的search和count都只能看到授权范围内的文档,最关键的发现是直接用id去GET一条被过滤的文档,返回的是found:false而不是403,对比管理员账号确认该文档真实存在,揭示了DLS刻意让被过滤文档对受限用户表现得如同不存在,避免通过拒绝响应泄露数据存在性这个真实的安全设计细节。

直接建DLS role
真实被basic许可证拒绝
激活trial许可证后重建role
真实创建成功
直接GET被过滤的hr1文档
真实返回found:false不是403

做的事:本机真实先尝试直接建一个带document level security的role,看默认的许可证能不能用

代码PUT /_security/role/sales_only_role { "indices": [{"names":["dls_test"],"privileges":["read"], "query":{"term":{"department":"sales"}}}] }

验证:真实被拒绝,跟本系列前面验证审计日志时一样,这个功能也被license许可证限制住了,报错原文直接点名了具体是哪个功能

实测 · 本机 Elasticsearch 8.15.0 执行输出
→ 403 security_exception:
  "current license is non-compliant for [field and document level security]"

这个真实报错再次印证了本系列前面得到的结论:Elasticsearch的不少安全相关功能真实都被license许可证等级卡着,默认的basic许可证真实用不了document level security这类功能,不是配置写对了就一定能生效。

真实用ES自带的30天trial许可证激活(不需要任何外部密钥),重新创建同样的role

代码POST /_license/start_trial?acknowledge=true 真实重新PUT同样的role

验证:trial许可证真实激活成功,同样的role这次真实创建成功了

实测 · 本机执行输出
{"acknowledged":true,"trial_was_started":true,"type":"trial"}
真实再PUT role: {"role":{"created":true}}

真实往索引写了sales和hr两个部门的文档,给用户绑定这个只能看department:sales的role,真实测search、count和直接GET这三种访问方式

代码真实写入department:sales和department:hr两条文档 真实用绑定了sales_only_role的salesuser分别测: GET /dls_test/_search GET /dls_test/_count GET /dls_test/_doc/hr1 # 直接用hr那条文档的真实id去查

验证:search和count真实都只看到sales那一条;最关键的真实发现是直接GET hr1,返回的是found:false,不是403

实测 · 本机执行输出
search: hits.total.value:1, 真实只有department:sales那一条
count: {"count":1}   ← 真实精确对应可见的那1条

直接GET /dls_test/_doc/hr1:
→ {"_index":"dls_test","_id":"hr1","found":false}   ← 真实是found:false,不是403!

对比用dlsadmin(不受DLS限制)查同一个id:
→ {"found":true,"_source":{"department":"hr","amount":200}}   ← 真实确认这条数据本来是存在的
这是document level security最关键的真实设计细节:被DLS过滤掉的文档,对受限用户来说真实表现得就像这条数据压根不存在一样——返回的是跟"真的没有这个id"完全相同的found:false,而不是一个会暴露"这里其实有数据,只是你看不到"这个信息的403拒绝。这个真实设计是刻意的:如果返回403,相当于真实间接告诉了调用方"这个id对应的文档确实存在于这个索引里,只是权限不够",这本身就是一种真实的信息泄露;DLS选择的做法是让受限用户完全感知不到这份数据的存在,从查询接口、统计接口到直接按id查询,三种方式真实表现得完全一致。

分步演示:从basic许可证下DLS功能真实被拒绝,到激活trial许可证后被过滤文档伪装成不存在的完整验证

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

DLS功能真实被license卡着,激活后被过滤的文档会伪装成found:false而不是403
这一步新验证的DLS场景

    本文用到的工具

    • 真实独立搭建的Elasticsearch 8.15.0节点(开启security,测完即销毁)
    • 真实的 _license/start_trial 与role的 query 字段(Document Level Security)
    京ICP备2026067502号-1京公网安备11010502063487号