Firebase可调用云函数HTTPS端点可被外部直接访问的资源消耗与权限配置疑问
首先直接给你明确答案:你的IAM观察完全正确,移除allUsers权限正是解决冷启动资源浪费问题的核心方案。下面我一步步拆解你的疑问:
1. 为什么端点还能被公开访问?
你在Cloud Console看到的警告——allUsers被授予了函数权限——就是问题的根因。虽然你在函数代码里加了身份验证检查,也启用了App Check,但IAM是GCP最底层的权限控制层,优先级远高于你在函数内部或Firebase层面的配置。
哪怕你开启了「Require authentication」选项,只要allUsers有调用权限,任何互联网用户都能发送请求到你的函数端点。这些请求哪怕最终被代码里的Auth逻辑拒绝,也已经触发了函数的冷启动,导致资源消耗和成本增加。
2. 移除allUsers后,能在冷启动前拦截无效请求吗?
绝对可以!这正是你需要的前置防护手段:
- 移除
allUsers的cloudfunctions.functions.invoke权限后,GCP会在函数实例启动前就拦截所有未授权的请求,不会产生任何冷启动资源消耗,从根源上杜绝DoS式的成本攻击。 - 不过要注意:移除
allUsers后,你需要给合法的调用者授权。对于你的Flutter app场景,应该添加allAuthenticatedUsers(所有经过Firebase Auth认证的用户)的cloudfunctions.functions.invoke权限。这样只有携带有效Firebase Auth令牌的请求能通过IAM检查,到达函数。
配合你已启用的App Check,就能形成完美的双重防护:IAM确保请求来自已认证用户,App Check确保请求来自你的合法app,两者结合彻底锁死无效请求。
3. 为什么代码层的Auth检查还会产生容器实例计数?
你提到即使无效请求被Auth检查拒绝,容器实例计数还是会到1——这是因为代码层的检查是在函数实例启动后才执行的。当请求到达函数端点(因为IAM允许allUsers调用),GCP已经启动了函数实例,之后代码里的检查才会拒绝请求,但冷启动的资源消耗已经产生了。
而IAM层面的拦截是在函数实例启动前完成的,所以不会有任何资源消耗,这才是真正的前置防护。
另外补充一点:App Check本身不会阻止请求到达函数实例,它只是让你能在代码层验证请求是否来自你的合法app。只有结合IAM的权限控制,才能在最底层拦截无效请求。
具体操作建议
- 打开Google Cloud Console → Cloud Functions → 你的目标函数 → 权限页面。
- 找到
allUsers的权限条目,移除它的cloudfunctions.functions.invoke权限(或者直接删除allUsers的所有权限)。 - 添加新的权限:主体选择
allAuthenticatedUsers,角色选择「Cloud Functions Invoker」(对应cloudfunctions.functions.invoke权限)。 - 保留你代码里的Auth检查和已启用的App Check,作为额外的安全层。
这样配置后,只有来自你的Flutter app的已认证用户能正常调用函数,所有无效请求都会在IAM层被直接拦截,不会触发冷启动,彻底解决资源被滥用的问题。
内容来源于stack exchange

