安全性
编辑安全性
编辑Kibana 通常能够对核心和插件开发者透明地实现安全性,并且这种情况在很大程度上仍然如此。Kibana 依赖 Elasticsearch Cluster
提供的两种方法:callWithRequest
和 callWithInternalUser
。
callWithRequest
使用 Kibana 最终用户的身份验证凭据对 Elasticsearch 执行请求。因此,如果您以用户 foo
身份登录 Kibana,当使用 callWithRequest
时,Kibana 将以用户 foo
的身份对 Elasticsearch 执行请求。从历史上看,callWithRequest
已被广泛用于执行由 Kibana 最终用户发起的动作。
callWithInternalUser
使用 Kibana 内部服务器用户对 Elasticsearch 执行请求,并且历史上一直用于执行非 Kibana 最终用户发起的动作;例如,创建初始的 .kibana
索引或对 Elasticsearch 执行健康检查。
但是,随着基于角色的访问控制 (RBAC) 引入的更改,这种情况不再那么简单。Kibana 现在要求所有对 .kibana
索引的访问都必须通过 SavedObjectsClient
。这曾经是一种最佳实践,因为 SavedObjectsClient
负责在 Elasticsearch 中存储的文档和保存的对象之间进行转换,但 RBAC 现在正在利用此抽象来实现访问控制,并确定何时使用 callWithRequest
与 callWithInternalUser
。
基于角色的访问控制
编辑Kibana 中的基于角色的访问控制 (RBAC) 依赖于 Elasticsearch 公开的应用程序权限。这使 Kibana 能够定义 Kibana 希望授予用户的权限,使用角色将其分配给相关用户,然后授权用户执行特定操作。这在 SavedObjectsClient
的安全实例中处理,并且在使用 request.getSavedObjectsClient()
或 savedObjects.getScopedSavedObjectsClient()
时对使用者透明可用。
Kibana 权限
编辑当 Kibana 首次启动时,它会对 Elasticsearch 执行以下 POST
请求。这将权限的定义与稍后用于授权用户的各种 actions
同步
POST /_security/privilege Content-Type: application/json Authorization: Basic {kib} changeme { "kibana-.kibana":{ "all":{ "application":"kibana-.kibana", "name":"all", "actions":[ "version:7.0.0-alpha1-SNAPSHOT", "action:login", "action:*" ], "metadata":{} }, "read":{ "application":"kibana-.kibana", "name":"read", "actions":[ "version:7.0.0-alpha1-SNAPSHOT", "action:login", "saved_object:dashboard/get", "saved_object:dashboard/bulk_get", "saved_object:dashboard/find", ... ],"metadata":{}} } }
该应用程序是通过将 kibana-
的前缀与 kibana.yml
中的 kibana.index
值连接而创建的,因此不同的 Kibana 租户彼此隔离。
分配 Kibana 权限
编辑Kibana 权限使用 applications
元素分配给特定角色。例如,以下角色将 all 权限分配给 *
resources
(将来将用于保护空间)分配给默认的 Kibana application
"new_kibana_user": { "applications": [ { "application": "kibana-.kibana", "privileges": [ "all" ], "resources": [ "*" ] } ] }
授予 Kibana 权限的角色应使用角色 API 或 管理 → 安全性 → 角色页面进行管理,而不是直接使用 Elasticsearch 角色管理 API。然后可以使用 Elasticsearch 用户管理 API 将此角色分配给用户。
授权
编辑Elasticsearch has privileges API 确定用户是否有权执行特定操作
POST /_security/user/_has_privileges Content-Type: application/json Authorization: Basic foo_read_only_user password { "applications":[ { "application":"kibana-.kibana", "resources":["*"], "privileges":[ "saved_object:dashboard/save", ] } ] }
Elasticsearch 检查是否向用户授予了特定操作。如果向用户分配了授予权限的角色,Elasticsearch 将使用Kibana 权限定义将其与操作关联,这使得以编程方式授权用户更加直观和灵活。
一旦我们授权用户执行特定操作,我们就可以使用 callWithInternalUser
执行请求。
插件功能注册
编辑如果您的插件将与 Kibana 的默认发行版一起使用,那么您可以注册您的插件提供的功能。功能通常是 Kibana 中的应用程序;注册后,您可以通过空间切换它们,并在启用安全性时通过角色保护它们。
UI 功能
编辑注册功能还使您的插件可以访问“UI 功能”。这些功能是布尔标志,您可以根据当前用户的权限有条件地渲染界面。例如,如果当前用户未获得授权,则可以隐藏或禁用“保存”按钮。
注册功能
编辑功能注册通过内置的 features
插件控制。要注册功能,请从插件的 setup
生命周期函数中调用 features
的 registerKibanaFeature
函数,并提供相应的详细信息
setup(core, { features }) { features.registerKibanaFeature({ // feature details here. }); }
功能详细信息
编辑注册功能包括以下字段。有关更多信息,请查阅功能注册接口。
字段名称 | 数据类型 | 示例 | 描述 |
---|---|---|---|
|
|
|
您的功能的唯一标识符。通常,您的插件的 ID 就足够了。 |
|
|
|
您的功能的人类可读名称。 |
|
|
最能代表您的功能的 |
|
|
|
|
此功能启用的应用程序数组。通常,此处会包括您的所有插件的应用程序(来自 |
|
此功能正常运行所需的权限集。 |
||
|
请参阅示例 3 |
一组子功能,可以实现比 |
|
|
|
|
默认 |
使用 UI 功能
编辑UI 功能可用于您的公共(客户端)插件代码。这些功能是只读的,用于通知 UI。此对象按功能 ID 命名。例如,如果您的功能 ID 为“foo”,则您的 UI 功能存储在 uiCapabilities.foo
。可以通过插件的 start
生命周期从 core.application
服务访问功能
public start(core) { const { capabilities } = core.application; const canUserSave = capabilities.foo.save; if (canUserSave) { // show save button } }
示例 1:Canvas 应用程序
编辑public setup(core, { features }) { features.registerKibanaFeature({ id: 'canvas', name: 'Canvas', category: DEFAULT_APP_CATEGORIES.kibana, app: ['canvas', 'kibana'], catalogue: ['canvas'], privileges: { all: { savedObject: { all: ['canvas-workpad'], read: ['index-pattern'], }, ui: ['save'], }, read: { savedObject: { all: [], read: ['index-pattern', 'canvas-workpad'], }, ui: [], }, }, }); }
这显示了 Canvas 应用程序如何将自己注册为 Kibana 功能。请注意,它为每个权限指定了不同的 savedObject
访问级别
- 具有读/写权限(
all
权限)的用户需要能够读取/写入canvas-workpad
保存的对象,并且他们需要对index-pattern
保存的对象具有只读访问权限。 - 具有只读权限(
read
权限)的用户不需要对任何保存的对象具有读/写权限,而是获得对index-pattern
和canvas-workpad
保存的对象的只读访问权限。
此外,Canvas 还注册了 canvas
UI 应用程序和 canvas
目录条目。这告诉 Kibana,这些实体可供具有 read
或 all
权限的用户使用。
all
权限定义了单个“保存”UI 功能。要在 UI 中访问此功能,Canvas 可以
public start(core) { const { capabilities } = core.application; const canUserSave = capabilities.canvas.save; if (canUserSave) { // show save button } }
因为 read
权限没有定义 save
功能,所以具有只读权限的用户的 uiCapabilities.canvas.save
标志将设置为 false
。
示例 2:开发工具
编辑public setup(core, { features }) { features.registerKibanaFeature({ id: 'dev_tools', name: i18n.translate('xpack.features.devToolsFeatureName', { defaultMessage: 'Dev Tools', }), category: DEFAULT_APP_CATEGORIES.management, app: ['kibana'], catalogue: ['console', 'searchprofiler', 'grokdebugger'], privileges: { all: { api: ['console'], savedObject: { all: [], read: [], }, ui: ['show'], }, read: { api: ['console'], savedObject: { all: [], read: [], }, ui: ['show'], }, }, privilegesTooltip: i18n.translate('xpack.features.devToolsPrivilegesTooltip', { defaultMessage: 'User should also be granted the appropriate {es} cluster and index privileges', }), }); }
与 Canvas 示例不同,开发工具不需要访问任何保存的对象即可正常运行。但是,开发工具确实指定了 API 端点。配置此选项后,安全插件将自动授权访问任何标记有 access:console
的服务器 API 路由,类似于以下内容
server.route({ path: '/api/console/proxy', method: 'POST', config: { tags: ['access:console'], handler: async (req, h) => { // ... } } });
示例 3:Discover
编辑Discover 利用子功能权限来实现细粒度的访问控制。在此示例中,定义了两个子功能权限:“创建短 URL”和“生成 PDF 报告”。这些允许用户授予对此功能的访问权限,而不必向 Discover 授予 all
权限。换句话说,您可以授予对 Discover 的 read
访问权限,并授予创建短 URL 或生成 PDF 报告的功能。
请注意,“生成 PDF 报告”子功能权限有一个附加的 minimumPrivilege
选项。只有在满足许可证要求的情况下,Kibana 才会提供此子功能权限。
public setup(core, { features }) { features.registerKibanaFeature({ { id: 'discover', name: i18n.translate('xpack.features.discoverFeatureName', { defaultMessage: 'Discover', }), order: 100, category: DEFAULT_APP_CATEGORIES.kibana, app: ['kibana'], catalogue: ['discover'], privileges: { all: { app: ['kibana'], catalogue: ['discover'], savedObject: { all: ['search', 'query'], read: ['index-pattern'], }, ui: ['show', 'save', 'saveQuery'], }, read: { app: ['kibana'], catalogue: ['discover'], savedObject: { all: [], read: ['index-pattern', 'search', 'query'], }, ui: ['show'], }, }, subFeatures: [ { name: i18n.translate('xpack.features.ossFeatures.discoverShortUrlSubFeatureName', { defaultMessage: 'Short URLs', }), privilegeGroups: [ { groupType: 'independent', privileges: [ { id: 'url_create', name: i18n.translate( 'xpack.features.ossFeatures.discoverCreateShortUrlPrivilegeName', { defaultMessage: 'Create Short URLs', } ), includeIn: 'all', savedObject: { all: ['url'], read: [], }, ui: ['createShortUrl'], }, ], }, { groupType: 'independent', privileges: [ { id: 'pdf_generate', name: i18n.translate( 'xpack.features.ossFeatures.discoverGeneratePDFReportsPrivilegeName', { defaultMessage: 'Generate PDF Reports', } ), minimumLicense: 'platinum', includeIn: 'all', savedObject: { all: [], read: [], }, api: ['generatePDFReports'], ui: ['generatePDFReports'], }, ], }, ], }, ], } }); }