保护嵌入式Metabase
如何在不同类型的嵌入中隐藏和保护敏感数据。
加入我们的网络研讨会,了解Metabase中的面向客户的分析。
使用身份验证和授权保护嵌入
在互联网上保护东西有两种基本方法
- 身份验证关注的是某人是谁(使用如JWT或SAML等标准)。
- 授权关注的是某人可以访问什么(使用如OAuth 2.0等标准)。
公共嵌入
公共嵌入不涉及任何身份验证或授权。一个公共嵌入显示一个带有唯一字符串的公共链接,如下所示
http://my-metabase.com/public/dashboard/184f819c-2c80-4b2d-80f8-26bffaae5d8b
该字符串(在此示例中:184f819c-2c80-4b2d-80f8-26bffaae5d8b
)唯一标识您的Metabase问题或仪表板。由于公共嵌入不进行任何身份验证或授权,任何拥有URL的人都可以查看数据。
示例:公共链接中的过滤器不保证数据安全
那么,有人如何利用公共嵌入呢?比如说我们有一个显示账户数据的仪表板
账户ID | 计划 | 状态 |
---|---|---|
1 | 基本 | 活动 |
2 | 基本 | 活动 |
3 | 基本 | 非活动 |
4 | 高级 | 非活动 |
5 | 高级 | 活动 |
我们想要添加一个“状态 = 活动状态”的过滤器,并在嵌入中显示仪表板的公共链接
账户ID | 计划 | 状态 |
---|---|---|
1 | 基本 | 活动 |
2 | 基本 | 活动 |
5 | 高级 | 活动 |
为了应用并隐藏“状态 = 活动状态”的过滤器,我们将在我们的嵌入中公共链接的末尾添加查询参数
http://my-metabase.com/public/dashboard/184f819c-2c80-4b2d-80f8-26bffaae5d8b?status=active#hide_parameters=status
尽管我们已经从嵌入中隐藏了过滤器,但有人可以取走嵌入中使用的公共链接,并移除查询参数?status=active
http://my-metabase.com/public/dashboard/184f819c-2c80-4b2d-80f8-26bffaae5d8b
不带有查询参数的公共链接将会移除数据中的“状态 = 活动状态”过滤器。此人将能够访问原始的账户数据,包括非活动的账户的行。
静态嵌入使用JWT进行授权
静态嵌入使用JWT授权流程来完成两项工作
- 对资源(例如,图表或仪表板的URL)进行签名,以确保只有您的嵌入应用程序可以请求Metabase中的数据。
- 对参数(例如,仪表板过滤器)进行签名,以防止人们更改过滤器并访问其他数据。
静态嵌入没有用户会话
静态嵌入不在Metabase侧对人们的身份进行身份验证,因此人们可以在不创建Metabase账户的情况下查看静态嵌入。然而,如果没有Metabase账户,Metabase将无法记住用户或其会话,这意味着
- Metabase的权限和数据沙箱将不起作用——如果您需要锁定敏感数据,您必须为每个静态嵌入设置锁定参数。
- 静态嵌入中的任何过滤器选择将在签名的JWT过期后重置。
- 所有静态嵌入的使用情况将在“外部用户”下使用分析中显示。
静态嵌入安全与交互式嵌入安全
静态嵌入仅保证授权访问您的Metabase数据(您决定什么可访问)。
如果您想根据某人的身份(您决定谁可以访问什么)来保护您的静态嵌入,您需要设置自己的身份验证流程,并手动将其连接到每个静态嵌入上的锁定参数。请注意,锁定参数本质上相当于过滤器,因此您只能在静态嵌入中设置行级别的限制。
如果您想更轻松地将不同客户的数据视图嵌入到不同的客户中(同时不允许客户看到彼此的数据),请了解如何在单个流程中通过交互式嵌入验证和授权人员。
使用JWT授权的静态嵌入
此图说明了如何通过签名JWT来保护嵌入
- 访客到来:您的前端收到显示Metabase 嵌入URL的请求。
- 签名请求:您的后端生成带有签名JWT的Metabase嵌入URL。签名JWT应编码您用于过滤数据的任何查询参数。
- 响应:您的Metabase后端根据签名JWT中编码的查询参数返回数据。
- 成功:您的前端显示带有正确数据的嵌入Metabase页面。
示例:使用静态嵌入上的锁定参数保护数据
在公共嵌入示例中,我们向您展示了(可能不明智)如何通过编辑查询参数来利用唯一的公共链接。
让我们回到我们的“账户”示例
账户ID | 计划 | 状态 |
---|---|---|
1 | 基本 | 活动 |
2 | 基本 | 活动 |
3 | 基本 | 非活动 |
4 | 高级 | 非活动 |
5 | 高级 | 活动 |
记住,我们可以在公共嵌入中通过在嵌入URL末尾包含查询参数来过滤数据
http://my-metabase.com/public/dashboard/184f819c-2c80-4b2d-80f8-26bffaae5d8b?status=active
账户ID | 计划 | 状态 |
---|---|---|
1 | 基本 | 活动 |
2 | 基本 | 活动 |
5 | 高级 | 活动 |
对于静态嵌入,我们可以通过将查询参数编码到签名JWT中来“锁定”过滤器。例如,假设我们将“状态 = Active”过滤器设置为锁定参数。查询参数?status=active
将被编码到签名JWT中,因此它不会从静态嵌入URL中可见或可编辑
http://my-metabase.com/dashboard/your_signed_jwt
如果有人尝试像这样在静态嵌入URL的末尾添加一个(未签名)查询参数
http://my-metabase.com/dashboard/your_signed_jwt?status=inactive
Metabase将拒绝此未授权的数据请求,因此非活动账户行将保持对嵌入不可见。
示例:向锁定参数发送用户属性
假设我们想公开账户表,以便客户可以根据账户ID查找行。
账户ID | 计划 | 状态 |
---|---|---|
1 | 基本 | 活动 |
2 | 基本 | 活动 |
3 | 基本 | 非活动 |
4 | 高级 | 非活动 |
5 | 高级 | 活动 |
如果我们想避免为每个客户创建Metabase登录,我们需要
该流程可能如下所示
- 客户登录我们的Web应用程序。
- 我们的应用程序后端根据登录过程中使用的账户电子邮件查找客户的
account_id
。 - 我们的应用程序后端使用Metabase的密钥来生成嵌入URL,并通过签名JWT进行加密。签名的JWT将查询参数编码,以在
Account ID = account_id
上过滤账户仪表板。 - Metabase在静态嵌入URL返回过滤后的仪表板。
- 我们的应用程序前端在iframe中显示过滤后的仪表板。
有关代码示例,请参阅静态嵌入参考应用程序。
交互式嵌入在一个流程中验证和授权人员
交互式嵌入与SSO(JWT或SAML)集成,以在一个流程中验证和授权人员。认证集成使得将用户属性(如人员的角色或部门)映射到细粒度数据访问级别变得简单,包括
SSO交互式嵌入
此图展示了交互式嵌入如何通过SSO进行安全保护
- 访客到达:您的前端收到显示所有内容的请求,包括Metabase组件(如React组件)。
- 加载嵌入:您的组件使用您的嵌入URL加载Metabase前端。
- 检查会话:为了在嵌入URL上显示数据,您的Metabase后端会检查有效会话(登录访客)。
- 如果没有有效会话:
- 重定向到SSO:您的Metabase前端将访客重定向到您的SSO登录页面。
- SSO认证:您的SSO流程验证访客并根据其身份生成会话。会话信息应包含用户属性,例如组成员资格和数据沙箱权限。
- 重定向到Metabase:您的SSO流程将带有会话信息的访客重定向到您的Metabase前端。
- 请求:您的Metabase前端将数据请求发送到Metabase后端,并附带会话信息。
- 响应:您的Metabase后端根据会话信息中编码的用户属性返回数据。
- 成功:您的组件将显示嵌入的Metabase页面,并显示登录访客的正确数据。
步骤4的机制将根据您是否使用JWT或SAML进行SSO而略有不同。
示例:使用SSO和数据沙箱保护数据
在我们的静态嵌入示例中,我们使用锁定参数来显示安全过滤的账户表视图。
交互式嵌入和SSO集成的好处是,我们不必为每个嵌入手动管理锁定参数。相反,我们可以将身份提供者(IdP)中的用户属性映射到Metabase中的权限和数据沙箱。人们可以在他们的第一次登录时获得对特定数据子集的认证和授权。
让我们扩展我们的账户示例,包括租户ID。租户ID代表一组客户的父组织
租户ID | 账户ID | 计划 | 状态 |
---|---|---|---|
999 | 1 | 基本 | 活动 |
999 | 2 | 基本 | 活动 |
999 | 3 | 基本 | 非活动 |
777 | 4 | 高级 | 非活动 |
777 | 5 | 高级 | 活动 |
我们仍然想向我们的客户公开账户表,但有一些额外的要求
- 个别客户只能查看他们自己的账户ID的数据。
- 租户可以查看他们所有子账户的数据(但不能查看其他租户的数据)。
为了设置这些多租户权限,我们需要
- 在我们的IdP中创建一个
primary_id
属性,以唯一标识所有租户和客户。 - 在我们的身份提供者(IdP)中创建一个名为
role
的用户属性,并将其设置为tenant
或customer
,以便每个将使用 Metabase 的人。 - 在 Metabase 中创建两个组:租户和客户。
- 在 Metabase 和我们的身份提供者之间同步组成员资格,以便
- 拥有
role=tenant
的人被分配到租户组。 - 拥有
role=customer
的人被分配到客户组。
- 拥有
- 为每个组设置账户表的沙盒视图
- 对于客户组,账户表将沙盒化(过滤)为
Account ID = primary_id
。 - 对于租户组,账户表将沙盒化为
Tenant ID = primary_id
。
- 对于客户组,账户表将沙盒化(过滤)为
当租户 A 首次使用 SSO 登录时
- Metabase 将为他们创建一个账户。
- 我们的身份提供者将发送
role=tenant
和primary_id=999
属性到 Metabase。 - Metabase 将自动将租户 A 分配到租户组。
- 租户 A 将获得租户组的权限(包括数据沙盒)。
- 租户 A 将在 Metabase 的每个地方看到账户表的沙盒视图
租户ID | 账户ID | 计划 | 状态 |
---|---|---|---|
999 | 1 | 基本 | 活动 |
999 | 2 | 基本 | 活动 |
999 | 3 | 基本 | 非活动 |
当客户 1 登录时,他们将会看到基于他们的 role
和 primary_id
属性的不同过滤版本的账户表
租户ID | 账户ID | 计划 | 状态 |
---|---|---|---|
A | 1 | 基本 | 活动 |