上一篇剖析了 Task Manager 如何在多节点 Kibana 中调度后台作业。这一篇转入访问控制层面,核心问题是:Kibana 的 Spaces 提供怎样的隔离边界,RBAC 角色如何精确到"能在某个 Space 里看到哪些 Feature"这一粒度,以及 Saved Object 的空间归属在存储层怎么表达。

隔离需求的来源

一个 Elasticsearch 集群承载多个团队的数据是常态。但 Kibana 默认只有一个全局视图——所有 Dashboard、Index Pattern、Saved Search 堆在一起。团队 A 看到团队 B 的运维面板,不是安全问题(数据权限可以通过 ES 索引级别的角色控制),而是噪音问题。Spaces 的出发点是 UI 级别的组织隔离,不是数据安全隔离。安全隔离由 RBAC 叠加在 Spaces 之上实现。

架构总览

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
┌─────────────────────────────────────────────────┐
│ Kibana Server │
├─────────────────────────────────────────────────┤
│ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ Space: A │ │ Space: B │ │ Default │ │
│ │ │ │ │ │ Space │ │
│ │ namespace│ │ namespace│ │ namespace│ │
│ │ = "a" │ │ = "b" │ │ = (none) │ │
│ └────┬─────┘ └────┬─────┘ └────┬─────┘ │
│ │ │ │ │
├───────┼──────────────┼──────────────┼───────────┤
│ ▼ ▼ ▼ │
│ ┌─────────────────────────────────────────┐ │
│ │ Saved Object Repository │ │
│ │ type + id + namespace → unique key │ │
│ └─────────────────────────────────────────┘ │
│ │ │
├──────────────────────┼──────────────────────────┤
│ RBAC Layer │ │
│ role → [space_a:read, space_b:all, ...] │
│ Feature Controls → per-space feature toggle │
└──────────────────────┼──────────────────────────┘

.kibana index (ES)

三个层次各管一件事:Spaces 管命名空间隔离,RBAC 管谁能进哪个 Space 做什么操作,Feature Controls 管进了 Space 之后能看到哪些功能入口。

Spaces:命名空间与 Saved Object 归属

Spaces 在 Kibana 6.5 引入。每个 Space 有唯一 ID(小写字母、数字、连字符),URL 路由体现为 /s/{space-id}/app/...。Default Space 的 ID 是 default,URL 不带 /s/ 前缀。

Saved Object 归属到 Space 的机制是 namespace 字段。一个 Dashboard 的存储记录在 .kibana 索引中大致是:

1
2
3
4
5
6
7
8
9
{
"type": "dashboard",
"id": "revenue-overview",
"namespace": "team-sre",
"attributes": { "title": "SRE Revenue Overview", "..." : "..." },
"references": [
{ "type": "index-pattern", "id": "logs-*", "name": "..." }
]
}

Default Space 的对象 namespace 字段不存储(undefined)。这意味着老版本升级上来的 Saved Object 自动落入 Default Space,无需迁移。

命名空间隔离的边界:同一个 type + id 在不同 namespace 下是独立对象。Space A 里的 dashboard:revenue 与 Space B 里的 dashboard:revenue 互不影响。但某些 Saved Object 类型被标记为 namespaceType: 'agnostic'——比如 config(全局配置)和 space 自身——这类对象全局唯一,不受 Space 隔离。

还有一类是 namespaceType: 'multiple',可以同时存在于多个 Space 中(如 8.x 中的某些共享对象),通过 namespaces: ["space-a", "space-b"] 数组表达归属。

RBAC:Elasticsearch 原生安全的延伸

Kibana 的 RBAC 不是自建的权限系统,而是 Elasticsearch 安全机制(原 X-Pack Security,7.x 起进入 Basic 许可)在 Kibana 层的投射。一个 Elasticsearch 角色定义包含三组权限:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
role: sre_viewer
cluster_privileges: [monitor]
index_privileges:
- indices: [logs-*, metrics-*]
privileges: [read]
kibana_privileges:
- spaces: [team-sre]
feature:
discover: [read]
dashboard: [read]
maps: [all]
- spaces: [*]
feature:
stackMonitoring: [read]

kibana_privileges 是 Kibana 特有的扩展,由 Kibana 的 Security 插件注册到 Elasticsearch。它表达的语义是:这个角色在 team-sre 这个 Space 里对 Discover 和 Dashboard 有只读权限,对 Maps 有完全权限;在所有 Space 里对 Stack Monitoring 有只读权限。

权限粒度三级递进:Space → Feature → 操作(read / all)。all 包含 read、write、create、delete 的语义。部分 Feature 还支持子特权(sub-feature privileges),在 8.x 中由插件通过 registerKibanaFeature 声明。

认证流程:用户登录时 Kibana 向 ES 发 _security/_authenticate,拿到用户的角色列表。后续每个请求经过 Kibana 的 Authorization Service,根据请求目标 Space + Feature + 操作类型做权限裁决。裁决结果缓存在会话中,不会逐请求查询 ES。

Feature Controls:Space 级别的功能开关

Feature Controls 在 7.2 引入,解决的问题是:即使角色允许访问某个 Space,管理员可能希望这个 Space 里根本不出现某些功能入口。典型场景是给业务团队创建一个"干净"的 Space,只开放 Dashboard 和 Discover,隐藏 Dev Tools、Stack Management 等运维功能。

Feature Controls 是 Space 维度的配置,存储在 Space 的 Saved Object 中:

1
2
3
4
5
6
7
8
{
"type": "space",
"id": "business-analytics",
"attributes": {
"name": "Business Analytics",
"disabledFeatures": ["dev_tools", "advancedSettings", "indexPatternManagement"]
}
}

被禁用的 Feature 在该 Space 中完全不渲染:侧边栏不显示入口,直接访问 URL 返回 404。Feature Controls 与 RBAC 是正交的——RBAC 决定"你有没有权限",Feature Controls 决定"这个 Space 有没有这个功能"。两者取交集:一个功能必须在 Space 中启用且用户角色拥有对应权限,才能实际访问。

多租户模型的组合

把三层叠在一起,Kibana 的多租户模型是:

控制维度 配置位置
Spaces 哪些 Saved Object 可见 Space 定义(管理员 UI 或 API)
Feature Controls 哪些功能入口存在 Space 的 disabledFeatures
RBAC 谁能做什么 ES 角色定义

一个典型多租户部署:每个产品线一个 Space,每个 Space 只开放该产品线需要的 Feature,角色按照职能(开发、运维、产品)分配不同 Space 的不同权限。

实现细节:Authorization Service

Kibana 的 Security 插件在 server 端提供 AuthorizationService,核心方法是 checkPrivilegesAtSpacecheckPrivilegesGlobally。插件在处理 HTTP 请求时调用它做权限裁决:

1
2
3
4
5
请求进入
→ 解析目标 Space(从 URL 中的 /s/{id} 或 Default Space)
→ 解析目标 Feature + 操作(从路由注册的 access tag)
→ AuthorizationService.checkPrivilegesAtSpace(spaceId, actions)
→ 返回 authorized / unauthorized

路由注册时通过 options.tags 声明所需权限:

1
2
3
4
router.get(
path: '/api/my-plugin/data',
options: { tags: ['access:myPlugin-read'] }
)

Security 插件根据 tag 前缀映射到对应的 Kibana privilege,再查用户角色是否持有该 privilege。

版本演进

版本 变化
6.5 Spaces 引入,命名空间隔离 Saved Object
7.0 RBAC 正式可用,Security 功能进入 Basic 许可
7.2 Feature Controls 引入,Space 级功能开关
7.7 Saved Object 支持 namespaceType: 'multiple',对象可跨 Space 共享
8.0 旧平台移除,Security 插件完全迁入 New Platform 架构
8.x Sub-feature privileges,更细粒度的操作级权限声明

常见误解

Space 不等于安全边界。没有开启 Elasticsearch Security 的集群,Space 只是视觉分区——任何人可以切换到任何 Space。安全隔离的前提是启用 Security 并配置 RBAC。

Feature Controls 不替代 RBAC。禁用某个 Feature 只是隐藏 UI 入口,不阻止 API 级别的访问(如果用户有对应角色权限,仍可通过 API 操作数据)。真正的权限屏障来自 RBAC 的 privilege 检查。

小结与导航

Spaces 把 Saved Object 按 namespace 分区,RBAC 在 Elasticsearch 层统一管理"谁能在哪个 Space 做什么",Feature Controls 在 Space 维度裁剪功能入口。三层正交叠加,构成 Kibana 的访问控制体系。

下一篇进入 Kibana 的插件体系——New Platform 的 setup/start 生命周期如何解决旧平台的循环依赖和类型安全问题。


参考资料


上一篇:深入 Kibana 12 - Task Manager 与后台作业调度
下一篇:深入 Kibana 14 - 插件体系:New Platform 的 setup/start 生命周期