OpenDistro Security 中 backend_roles 的设计哲学
- [1.OpenDistro Security 的特殊设计 🔍](#1.OpenDistro Security 的特殊设计 🔍)
-
- [为内部用户 "模拟" 外部用户的组关系](#为内部用户 "模拟" 外部用户的组关系)
- 2.为什么这样设计?🤔
- [3.实际使用场景对比 📊](#3.实际使用场景对比 📊)
-
- [3.1 场景一:标准 Elasticsearch 做法](#3.1 场景一:标准 Elasticsearch 做法)
- [3.2 场景二:OpenDistro 做法](#3.2 场景二:OpenDistro 做法)
- [4.权限计算流程 🔄](#4.权限计算流程 🔄)
- [5.OpenDistro vs 原生 Elasticsearch 对比 ⚖️](#5.OpenDistro vs 原生 Elasticsearch 对比 ⚖️)
- [6.OpenDistro 设计的优点与缺点 🎯](#6.OpenDistro 设计的优点与缺点 🎯)
- 7.实际用例:为什么需要这个功能?💡
- [8.混合使用模式 🛠️](#8.混合使用模式 🛠️)
- [9.关键理解要点 📌](#9.关键理解要点 📌)
- [10.一句话总结 🎓](#10.一句话总结 🎓)
- [11.实战验证 ✨](#11.实战验证 ✨)
-
- [场景一:用户 → Roles,用户 → Backend roles → Roles](#场景一:用户 → Roles,用户 → Backend roles → Roles)
- [场景二:用户 → Roles,用户 → Backend roles ❌ Roles](#场景二:用户 → Roles,用户 → Backend roles ❌ Roles)
- [场景三:用户 → Roles,用户 ❌ Backend roles → Roles](#场景三:用户 → Roles,用户 ❌ Backend roles → Roles)
- [场景四:用户 → Roles,用户 ❌ Backend roles ❌ Roles](#场景四:用户 → Roles,用户 ❌ Backend roles ❌ Roles)
- [场景五:用户 ❌ Roles,用户 → Backend roles → Roles](#场景五:用户 ❌ Roles,用户 → Backend roles → Roles)
- [场景六:用户 ❌ Roles,用户 ❌ Backend roles → Roles](#场景六:用户 ❌ Roles,用户 ❌ Backend roles → Roles)
OpenDistro Security 的 backend_roles 字段设计比较特殊,与原生 Elasticsearch 的行为有所不同。
1.OpenDistro Security 的特殊设计 🔍
在 OpenDistro Security(现在叫 OpenSearch Security)中,backend_roles 字段的作用是:
为内部用户 "模拟" 外部用户的组关系
角色映射配置
OpenDistro Security 设计
外部系统(实际不存在)
假装来自外部系统
假装来自外部系统
匹配规则1
匹配规则2
内部用户配置
backend_roles 字段
(手工填写组名)
角色映射引擎
想象中的LDAP组:captains
想象中的LDAP组:starfleet
角色映射规则匹配
规则1: captains → command_role
规则2: starfleet → officer_role
用户获得 command_role
最终权限 = 直接角色 + 映射角色
2.为什么这样设计?🤔
设计目的:让内部用户也能利用角色映射机制
在标准的 Elasticsearch 中:
- 内部用户 → 直接分配角色
- 外部用户 → 通过后端角色映射角色
OpenDistro 的想法:"为什么不让内部用户也能享受角色映射的灵活性?"
3.实际使用场景对比 📊
3.1 场景一:标准 Elasticsearch 做法
json
// 内部用户:直接分配角色
PUT /_security/user/kirk
{
"password": "kirkpass",
"roles": ["command_officer", "starship_captain"]
// 没有 backend_roles 字段
}
3.2 场景二:OpenDistro 做法
json
// 内部用户:利用角色映射
PUT _opendistro/_security/api/internalusers/kirk
{
"password": "kirkpass",
"backend_roles": ["captains", "starfleet"],
"attributes": {
"rank": "captain",
"assignment": "enterprise"
}
// 不直接分配角色!
}
// 角色映射配置
PUT _opendistro/_security/api/rolesmapping/command_role
{
"backend_roles": ["captains"]
}
PUT _opendistro/_security/api/rolesmapping/officer_role
{
"backend_roles": ["starfleet"]
}
4.权限计算流程 🔄
角色映射引擎 OpenDistro Security 用户 kirk 角色映射引擎 OpenDistro Security 用户 kirk 找到: captains → command_role starfleet → officer_role 最终权限 = command_role + officer_role 登录 (kirk/kirkpass) 验证内部用户密码 获取 kirk 的 backend_roles ["captains", "starfleet"] 查找映射规则 返回角色:[command_role, officer_role] 认证成功,授予权限
5.OpenDistro vs 原生 Elasticsearch 对比 ⚖️
| 特性 | OpenDistro Security | 原生 Elasticsearch |
|---|---|---|
backend_roles 字段 |
内部用户可以设置,用于角色映射 | 内部用户通常不设置(只在角色映射 API 中使用) |
| 权限管理方式 | 鼓励使用角色映射,统一权限管理 | 内部用户直接分配,外部用户通过映射 |
| 灵活性 | 内部用户权限可通过映射规则统一调整 | 内部用户需要逐个修改 |
| 混淆度 | 容易混淆内部/外部用户边界 | 概念清晰,职责分离 |
6.OpenDistro 设计的优点与缺点 🎯
- 优点
- ✅ 统一管理:所有用户都通过角色映射管理权限。
- ✅ 动态调整:修改映射规则,影响所有相关用户。
- ✅ 属性扩展 :可以结合
attributes字段做更复杂的映射。
- 缺点
- ❌ 概念混淆:模糊了内部用户和外部用户的界限。
- ❌ 安全性 :手工填写
backend_roles可能出错。 - ❌ 维护复杂:需要维护额外的映射关系。
7.实际用例:为什么需要这个功能?💡
用例:批量权限调整
yaml
# 场景:所有"舰长"需要新权限
# 传统方式:修改每个舰长用户的角色
- 用户 kirk: 添加 "new_command_privileges"
- 用户 picard: 添加 "new_command_privileges"
- 用户 sisko: 添加 "new_command_privileges"
# ... 需要修改几十个用户!
# OpenDistro 方式:修改一条映射规则
角色映射规则:
- captains → command_role, new_command_privileges
# 所有 backend_roles 包含 "captains" 的用户自动获得新权限
8.混合使用模式 🛠️
OpenDistro 还支持混合模式:
json
PUT _opendistro/_security/api/internalusers/spock
{
"password": "spockpass",
"opendistro_security_roles": ["science_officer"], // 直接分配
"backend_roles": ["starfleet", "vulcan"], // 映射分配
"attributes": {
"species": "vulcan",
"logic_level": "high"
}
}
权限计算 = science_officer + (starfleet 映射的角色) + (vulcan 映射的角色)
9.关键理解要点 📌
- 不是真正的 "后端" :OpenDistro 中的
backend_roles并不真的来自后端系统,而是 手工配置的标签。 - 两层角色分配 :
- 第一层:
opendistro_security_roles(直接分配) - 第二层:
backend_roles→ 通过映射间接分配
- 第一层:
- 设计哲学差异 :
- Elasticsearch:内部用户和外部用户应该分开管理。
- OpenDistro:所有用户都应该能用统一的方式管理权限。
10.一句话总结 🎓
在 OpenDistro Security 中,内部用户的 backend_roles 是一个 "虚拟标签",让它能够像外部用户一样通过角色映射机制获得权限,从而实现更灵活的统一权限管理。
这种设计与原生 Elasticsearch 不同,是 OpenDistro/OpenSearch 团队为了简化权限管理而做出的设计选择。
11.实战验证 ✨
本小节针对下面 6 种场景进行验证。

场景一:用户 → Roles,用户 → Backend roles → Roles



用户 xiaoming-01 会获得 test-02 的权限,可以读 log- 开头的索引。

但没有权限读非 log- 开头的索引,会报错:no permissions for [indices:data/read/search] and User [name=xiaoming-01, backend_roles=[apple-01], requestedTenant=null]。

场景二:用户 → Roles,用户 → Backend roles ❌ Roles



虽然 apple-01 未与 test-02 关联,但 xiaoming-01 直接与 test-02 关联,仍然拥有权限读取 log- 开头的索引。

场景三:用户 → Roles,用户 ❌ Backend roles → Roles



虽然 xiaoming-01 未与 apple-01 关联,但 xiaoming-01 直接与 test-02 关联,仍然拥有权限读取 log- 开头的索引。


场景四:用户 → Roles,用户 ❌ Backend roles ❌ Roles



相当于没有 Backend roles,用户 xiaoming-01 直接与 test-02 关联,拥有读取 log- 开头索引的权限。

场景五:用户 ❌ Roles,用户 → Backend roles → Roles



虽然用户 xiaoming-01 没有直接与 test-02 关联,但是他们通过 apple-01 作为 "桥梁" 进行了关联,用户 xiaoming-01 将拥有读取 log- 开头索引的权限。


场景六:用户 ❌ Roles,用户 ❌ Backend roles → Roles



此种情况下,用户 xiaoming-01 根本没有与 test-02 关联起来,自然是没有权限的。
