Edge Functions 安全模型
使您的函数、代码和秘密保密的规则,以及您负责的地方。
1. 按键及作用
| 角色 | 钥匙 | 可以做 |
|---|---|---|
anon | 公钥,在浏览器中安全 | 调用函数 |
authenticated | 公钥加上登录用户的 JWT | 使用用户身份调用函数 |
service_role | 密钥,仅 服务器 | 一切:部署、读取代码和机密、作业、cron、警报 |
admin | Studio 中的控制台会话 | 一切都来自工作室 |
该角色来自平台验证的密钥和令牌。客户端无法选择它:使用公钥和标头 x-aura-role: service_role 的调用仍然会以 anon形式到达您的函数。
每个路由及其角色都在 HTTP API 参考中列出。
2. 为什么只有调用是公开的
公钥发布在您的网络或移动应用程序中,因此任何人都可以读取它。无论它允许什么,每个人都被允许。调用函数是为此而设计的一种操作:您的代码决定调用者可以执行的操作。
读取函数的 定义 是不同的。它包含源代码和环境变量,这些变量通常包含秘密。列出作业和警报会显示您的数据。将作业加入队列会根据您的配额运行您的代码。这些都不能公开,并且对于任何不是 service_role的密钥,平台都会使用 403 拒绝它们。
其他地方也存在同样的分裂。 Supabase 在 Edge Function 默认运行 (verify_jwt = true) 之前验证用户的 JWT ,并通过其 CLI 和平台部署函数 (docs)。 Firebase 通过 Admin SDK 将任务从受信任的服务器环境排队,并具有 IAM 权限 (docs)。 Cloudflare 仅允许 Worker 通过绑定(docs)发送到队列。
该服务的早期版本对任意键应答 GET /v1/functions 和 GET /v1/functions/{name}。如果您的项目在此修复之前的部署上运行,请将函数的代码和变量视为公开的,并轮换它们包含的机密。请参阅 升级到 0.6。
3、身份不可伪造
您的函数从 x-aura-role、 x-aura-user-id 和 x-aura-project-id读取调用者。平台在验证密钥和令牌后设置它们。
- 呼叫者无法提供它们。平台会丢弃
authorization、apikey、x-request-id以及在调用的headers中发送的任何x-aura-*标头,无论其情况如何。在实际测试中,使用x-aura-role: service_role和伪造的authorization进行的调用以role: "anon"的形式到达函数,但没有authorization。 - 其他自定义标头保持不变。将它们视为用户输入。
- 作业和 cron 触发到达您的函数 ,而无需 身份标头。它们是由平台触发的,而不是由用户触发的。
因此,对 x-aura-role 和 x-aura-user-id进行授权,而不是对正文中的值进行授权:
4. 沙箱
该平台为您提供什么:
- 每个调用都在自己的 V8 隔离中运行,具有自己的内存限制和挂钟超时。一个调用中的崩溃或无限循环不会影响另一个调用。
- 主机的环境变量是不可见的:
Deno.env.get('PATH')在实际运行中返回undefined。仅存在函数的变量和平台的AURABASE_*变量。 - 一个项目的代码无法被另一个项目读取:为其提供服务的服务需要内部令牌。
- 可以运行脚本的响应使用沙箱内容安全策略,并且函数中的
Set-Cookie和 CORS 标头将被删除。请参阅 响应。
而不是 会给你带来什么:
- 除非你加以限制,否则出站网络是开放的。 当
permissions.allow_net列出至少一个主机时,运行时会拒绝向其他任何主机发起fetch(Requires net access to "host:443")。默认的空列表不做任何限制。请列出函数需要的每个主机;如果它会调用平台,也要包含你的项目 URL。即使设置了列表,也要校验来自用户输入的任何 URL。 - 日志中不保护您自己的秘密。 函数使用
console.log写入的任何内容都会进入运行时日志。 - 每个用户没有限制。 调用速率限制是每个客户端 IP。如果一个用户不得多次调用某个函数,请添加您自己的检查。
5. 清单
service_role密钥仅存在于您的服务器和 CI 机密中。- 浏览器捆绑包仅包含公钥。默认情况下,SDK 拒绝浏览器中的
service_role密钥。 - 每个函数在执行任何敏感操作之前都会检查
x-aura-role。 - 秘密是函数的变量,永远不会出现在
index.ts中。 - 调用外部 URL 的函数会验证目标。
- 您可以通过在 Studio 中创建新密钥、将其部署为机密、然后撤销旧密钥来轮换密钥。