一个 Metabase 神秘事件
公共链接、公共嵌入和签名嵌入有什么区别?
参加我们在Metabase中关于面向客户的分析的网络研讨会。
假设你在Metabase中工作在一个有趣的分析上,你需要分享你的工作——首先,为了获得反馈,然后,作为一个成品。
公共链接和嵌入,以及静态嵌入都是免费的开源方式,让你可以将Metabase工件(如图表和仪表板)与没有Metabase账户或权限访问你的原始数据的人分享。
在选择这些数据共享选项时,你将需要考虑
- 你需要多快地分享结果
- 您想添加多少上下文
- 您数据的安全性级别
您能帮助我们找到隐藏的信息吗?
在本教程中,我们将从 Metabase 数据分析师的角度,探讨一系列数据共享用例。我们的任务是调查一位队友留下的谜团,这位队友在即将解决 Metabase 最古老的错误时神秘消失了。
我们收到一条匿名线索,称我们队友的 git 提交信息中可能隐藏着信息,因此我们希望分析数据,寻找任何异常或可疑之处。当然,我们还想与我们的社区分享调查结果(毕竟我们是开源的)。
如果您想跳过前面的内容
仅供内部使用
在我们将正在进行中的调查结果公开之前,我们希望从团队那里获得一些反馈,并确保我们没有暴露任何个人信息(PII)。初步分析(图 1)位于我们内部的 Metabase 实例中——这个版本将仅与我们的团队共享。
分享 Metabase 仪表板的 URL
创建一个公共链接到我们的仪表板。
您可以将公共链接实时调查仪表板添加到书签。我们决定以汇总的方式显示提交数据,以便更容易阅读分析。我们还设置了自定义目的地,以便人们可以查看仪表板上显示的每个统计信息相关的完整提交信息。随着我们继续调查,我们可以将我们的更改发布到公共链接,以显示最新的分析。
线索 1
在我们的探索性数据分析中,我们查看了 git 提交信息长度的分布。一个异常值(最长的信息)包含以下信息
update the database sync event publication so that we can actually
track start & END as separate events but part of the same activity.
to do so we add a :tracking-hash to the events when they are published
which is meant to remain consistent throughout the sync, then we
implement our activity tracking code so that we can lookup an existing
activity item and update it based on the custom hash.
我们不确定为什么这里的“END”是大写的。这可能没有什么意义,但我们会继续寻找……
下一步:线索 2。
将 Metabase 仪表板添加到网站中
接下来,我们希望显示我们的实时调查仪表板和评论的网页表单,以便我们的社区可以前往一个地方贡献调查。为此,我们将设置一个新网站,并将仪表板和表单作为内嵌的 iframe 添加。
设置网站最简单的方法是使用免费网站构建器。这里,我们使用Google Sites。如果您不使用 Google Workspace,您可以使用 Squarespace 或 Webflow 等工具。
接下来,我们将回到 Metabase 仪表板上的共享选项,并复制 公共嵌入 下的代码。我们将向 Google Site 添加一个嵌入元素,并将代码片段粘贴在那里
然后,我们将创建一个公共 Google 表单并将其保存在 Google Drive 中。要将表单添加到我们的 Google Site,我们可以滚动到 插入 菜单(如图 2 所示)并选择 表单。
现在,我们有一个实时调查网站,它显示了我们的 Metabase 仪表板以及一个用于评论的表单。我们的社区将能够
- 通过我们的 Metabase 仪表板的公共嵌入访问最新的数据和线索。
- 使用嵌入的 Google 表单参与搜索。
线索 2
由于我们已经查看最大异常值,因此查看具有最小消息长度的提交也很有意义。最短的信息只有三个字符长,并且再次大写
LAG
下一步:线索 3。
限制对嵌入的 Metabase 仪表板的访问
今天早上,有人攻击了我们的Metabase公共嵌入,使用了成千上万次对不存在的查询参数filter=some_spooky_nonsense
的请求。为了保护线索不落入错误之手,我们想确保只有经过验证的用户才能访问包含线索的行。
我们可以通过将公共嵌入更改为静态嵌入来添加这额外的安全层。我们希望我们的仪表板静态嵌入显示
- 未登录的人没有数据。
- 受限制的数据(除了线索之外的一切)供登录的人查看。
- 秘密数据(线索)供使用秘密密码登录的人查看。
静态嵌入不支持Google Sites之类的网站生成器,因为我们需要运行自己的Web服务器来生成签名令牌,以保护我们的数据。如果您想继续完成静态嵌入教程的其余部分,您将需要
- 您自己的Metabase实例(以及相关的嵌入密钥)。
- 嵌入参考应用存储库的副本(我们将修改Node示例)。
metabase-mystery
数据的副本。
设置登录页面
首先,我们需要某种方式来验证试图访问我们的实时调查网站的人的身份。通常,这是通过一个由认证服务(如Google登录)驱动的登录页面来完成的,这样
- 登录成功后,我们的Web服务器将向我们的Metabase仪表板的过滤器发送一个查询参数,如
user=verified
,从而揭示线索。 - 登录失败时,Metabase仪表板过滤器不会从Web服务器收到正确的参数,从而隐藏线索,并显示其余数据。
为了演示基于登录显示和隐藏数据,我们将从定义在login.pug
中的简单认证流程开始(这肯定证明了您的真实性和无嫌疑)。
form(method="POST" action="/login")
input(type="text" name="username" value="metabot")
input(type="password" name="password" value="unverified")
input(type="hidden" name="redirect" value=redirectUrl)
p Can you be trusted?
button(type="submit" class="primary") Yes
根据登录情况将人们重定向到不同的URL
为了跟踪一个人的登录信息,我们将修改index.js
中的服务器代码,使用一个名为messageType
的变量。
function checkAuth(req, res, next) {
const messageType = req.session.messageType;
if (messageType) {
return next();
}
req.session.redirectTo = req.path;
return res.redirect("/login");
}
然后,我们将设置一些逻辑来处理不同类型的登录。存储在messageType
中的值将用于过滤在静态嵌入URL上显示的数据。
if (username === "metabot" && password === "regularPassword") {
// require a login to view the commit messages
req.session.messageType = "not secret";
res.redirect(req.session.redirectTo);
} else if (username === "metabot" && password === "secretPassword") {
// require a login with the secret password to view the clues
req.session.messageType = "secret";
res.redirect(req.session.redirectTo);
} else {
// allow people without logins to submit comments
res.redirect("/");
}
生成静态嵌入URL
现在,我们可以更新index.js
中的服务器代码,为每个登录的人动态生成静态嵌入的URL。这些URL是安全的,因为它们是用我们的嵌入密钥签名的。服务器还将传递messageType
的值(“secret”或“not secret”)到我们的Metabase仪表板上的过滤器,以便隐藏或显示数据中的线索。我们将在下一步设置此过滤器。
app.get("/signed_dashboard/:id", checkAuth, (req, res) => {
const messageType = req.session.messageType;
const unsignedToken = {
resource: { dashboard: DASHBOARD_ID },
params: { keep_secret: messageType },
exp: Math.round(Date.now() / 1000) + 10 * 60, // 10 minute expiration
};
// sign the JWT token with our secret key
const signedToken = jwt.sign(unsignedToken, MB_EMBEDDING_SECRET_KEY);
// construct the URL of the iframe to be displayed
const iframeUrl = `${MB_SITE_URL}/embed/dashboard/${signedToken}`;
res.render("dashboard", { messageType: req.params.id, iframeUrl: iframeUrl });
});
使用锁定参数限制数据
为了指定根据个人登录应显示的数据行,我们将回到我们的git提交数据,并添加一个名为消息类型的自定义列,该列使用case表达式将带有线索的行设置为“secret”,其余数据设置为“not secret”。
然后,为了确保我们可以限制我们实时调查仪表板上的所有数据,我们需要为仪表板上的每个问题创建一个消息类型列。
一旦数据设置完成,我们将在实时调查仪表板上添加一个过滤器,并将该过滤器链接到我们每个问题的所有消息类型列。我们还将“非机密”置于默认值下,以便默认显示非线索行。
现在,我们可以在仪表板上启用静态嵌入并设置一个锁定参数。在登录流程中(取决于使用的密码),锁定参数将从网络服务器接收“secret”或“not secret”的messageType
值。这个锁定参数将在结果在静态嵌入URL显示之前,将“secret”或“not secret”的值应用于我们原始仪表板上的过滤器。
查看不同访问级别的静态嵌入
一旦我们用静态嵌入的前端代码更新了layout.pug
,我们就可以运行我们的服务器代码来构建一个本地网站,该网站包含指向我们的实时调查仪表板的链接以及嵌入的Google表单进行评论。
点击链接将提示人们登录查看数据。我们迄今为止发现的线索默认是隐藏的。
要获取带有线索的行的访问权限,人们必须提供秘密密码。
如果您没有有效的登录,可以通过表单请求访问权限(或者只是作为一个热心的评论者参与谜题)。
线索 3
分布中隐藏的另一个线索——这次是在中等消息长度。
fixes mobile password reSET and confirmation #869
游戏开始了
我们需要来自我们数据朋友的更多帮助。到目前为止,我们发现了END、LAG和SET这些线索。我们的队友试图告诉我们什么?获取数据并进行实验,看看你是否能解开谜题。
点击这里获取提示。
尝试使用提交消息长度计算其他汇总统计。解决方案不是由Metabase功能付费墙(这将使这个谜题有点太恐怖)所屏蔽,但如果你想使用Metabase探索数据集,你可以
- 将CSV文件上传到Google表单,并将Metabase连接到Google Drive,或者
- 直接将CSV同步到与Metabase连接的数据库或数据仓库。
进一步阅读
下一节:多租户自助分析
嵌入整个Metabase应用程序(包括查询构建器),以给人提供安全、个性化的数据访问。