如何使 HTTP 云函数仅可从云端终端访问。
如何使 HTTP 云函数仅可从云端终端访问。
我的架构是:
- 我有一堆云函数(Firebase)
- 我建立了基于ESPv2的云端端点设置,使用云函数作为后端,并与云运行进行了设置
- 我在Firebase托管上运行一个单页面应用程序,该应用程序调用端点(15个API端点)
- 目前,这些API(云端点)通过API密钥进行了安全限制
我想要使云函数受到保护,只有云端点(或项目内的其他服务)才能调用它。
直接调用这些云函数的fqdns应返回403/4xx。
我该如何实现这一点?有没有任何方法?
**我没有组织帐户,因此创建服务范围不是一个选择。
编辑
我接受了guillaume blaquiere的答案作为正确答案。尽管这个答案没有解决我遇到的问题,但它是我所问问题的正确答案。
如果有人遇到类似的问题,我犯了一个很大的错误(我在它身后浪费了一天的时间),就是'x-google-backend > address'的问题。我只使用了云函数的FQDN而不是整个URL。所以
这是错误的:
/myfunction/mymodule1/dosomething:
post:
summary: I command you to do something
operationId: doSomething
x-google-backend:
address: https://xxxxxxxx.cloudfunctions.net
path_translation: APPEND_PATH_TO_ADDRESS
parameters:
- name: someheaderparam
in: header
description: shhh
required: true
type: string
- name: payload
in: body
description: playload
required: false
schema:
type: object
responses:
'200':
description: OK
schema:
type: object
'401':
$ref: '#/responses/UnauthorizedError'
为了使它工作,我需要使用函数的整个URL而不仅仅是FQDN。
在我的情况下,我的Firebase/云函数是一个Express应用程序,我发布函数的方式如下:
exports.myfunction = functions.https.onRequest(app);
所以云函数的名称是myfunction,其基本URL是:
https://xxxxxxxx.cloudfunctions.net/myfunction
使用Express,我添加了几个路径,例如:
app.post('/mymodule1/dosomething', validateToken(), somemethod);
如果我的函数是公开可访问的,为了调用'somemethod'函数,URL将是:
https://xxxxxxxx.cloudfunctions.net/myfunction/mymodule1/dosomething
为了在API网关后面使用openAPI进行映射,规范如下:
/mymodule1/dosomething:
post:
summary: I command you to do something
operationId: doSomething
x-google-backend:
address: https://xxxxxxxx.cloudfunctions.net/myfunction
path_translation: APPEND_PATH_TO_ADDRESS
parameters:
- name: someheaderparam
in: header
description: shhh
required: true
type: string
- name: payload
in: body
description: playload
required: false
schema:
type: object
responses:
'200':
description: OK
schema:
type: object
'401':
$ref: '#/responses/UnauthorizedError'
即使函数不是Express应用程序,这也是正确的。
在openAPI规范中,x-google-backend地址必须是函数的URL,而不仅仅是云函数的FQDN。
如何使HTTP云函数只能从云端点访问的方法
要实现这一点,您需要两件事情:
1. 首先限制对您的云函数的访问
2. 然后,只允许云端点访问您的函数
这样,函数将可以从互联网访问,但只有授权的服务(ESPv2)才能调用它们。
首先,以私有模式部署您的函数(在部署时添加--no-allow-unauthenticated参数)。
接下来,进行以下操作:
1. 创建一个专用于ESPv2服务的服务帐户(如果尚未创建)。
2. 使用此自定义服务帐户重新部署ESPv2服务。
3. 授予服务帐户roles/cloudfunctions.invoker权限,可以在以下两个层次进行授权:
- 在项目级别,这意味着服务帐户将能够调用项目中的任何函数。
- 或在函数级别,以允许服务帐户仅调用函数子集。当所有函数不在同一个项目中时,这是特别有趣的。
感谢您的建议。我从一个云函数中删除了"allUsers"成员身份。ESPv2已经部署了一个特定的服务帐户"apigatewwaysa.iam.gserviceaccount.com",该帐户具有cloudfunctions.invoker角色。但这仍然不起作用。当我调用"https://xxx-xxxx-uc.a.run.app/api/myapiname"时,我收到401 "Error: Unauthorized"的错误。当我直接调用云函数的URL时,我收到403 "Error: Forbidden"的错误。我还可以尝试什么?
我在这篇文章中介绍了如何做到这一点。应该按照这样的方式工作!检查授权和角色。它应该可以工作!!
我按照您的教程进行了设置。我重新阅读了它。仍然没有成功。您的教程和我的实现之间唯一的区别是:我部署了Firebase云函数,然后从权限中删除了allUsers(使其--no-allow-unauthenticated),我使用的是ESPv2,可以在此处找到:cloud.google.com/endpoints/docs/openapi/get-started-cloud-run 。我可以确认端点可以调用一个-no-allow-unauthenticated的云运行(具有云运行调用者角色),没有问题。只有Firebase云函数会出现问题(即使具有云函数调用者角色)。
我还查看了这个:stackoverflow.com/questions/46358013/… (查看第一个答案)。我的设置与此相同,只是我从云端点调用它,而不是从云调度器。但有一件事我不确定的是"允许OIDC标头"部分。它是如何工作的?对于云运行/云端点,ESPv2是否需要允许Authorization标头?
除非云函数不在与ESPv2相同的项目中,否则没有其他原因。您是否已经检查过这一点?您能在项目中看到您的函数吗?
谢谢您的回答。结果发现我错误地将云函数添加为后端。您的答案是正确的。