如何从 Google App Engine 调用 Google 云函数?

How can I call a Google Cloud Function from Google App Engine?

我有一个 App Engine 项目。

我还有一个 Google 云功能。

我想从 App Engine 项目调用 Google 云函数。我似乎无法让它发挥作用。

是的,如果我使函数完整 public(即将 Cloud Function 设置为 'allow all traffic' 并且 为 'allUsers' 创建一个规则允许调用函数)它的工作原理。但是如果我限制这两个设置中的任何一个,它会立即停止工作并且我得到 403。

App 和 Function 在同一个项目中,所以我至少假设将 Function 设置为 'allow internal traffic only' 应该可以正常工作,前提是我有 'allUsers' 的规则允许调用函数。

这是如何运作的?人们通常如何从 Google App Engine 调用(非 public)Google 云函数?

您需要身份验证 header 才能对函数 url 执行 ping 操作。它应该看起来像:

headers = {
    ....
    'Authorization': 'Bearer some-long-hash-token'
}

获取令牌的方法如下:

import requests
token_response = requests.get(
    'http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/identity?audience=' +
    'https://[your zone]-[your app name].cloudfunctions.net/[your function name]', 
    headers={'Metadata-Flavor': 'Google'})
    
return token_response.content.decode("utf-8")

'Allow internal traffic only' 没有按预期工作。我的 App Engine 应用程序与 Functions 在同一个项目中,但它不起作用。我不得不打开 'Allow all traffic',并使用 header 方法。

示例:

def get_access_token():
    import requests
    token_response = requests.get(
        'http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/identity?audience=' +
        'https://us-central1-my_app.cloudfunctions.net/my_function', 
        headers={'Metadata-Flavor': 'Google'})
        
    return token_response.content.decode("utf-8")
    
def test():
    url_string = f"https://us-central1-my_app.cloudfunctions.net/my_function?message=it%20worked"
    
    access_token = get_access_token()
    

    print(
        requests.get(url_string, headers={'Authorization': f"Bearer {access_token}"}
    )

docs 中所述,仅允许内部流量 提到以下内容:

Only requests from VPC networks in the same project or VPC Service Controls perimeter are allowed. All other requests are rejected.

请注意,由于 App Engine Standard 是无服务器产品,它不是 VPC 的一部分,因此从该产品发出的请求不被视为“内部”调用,实际上调用是从 Public IPs of the instances,因此您会收到 HTTP 403 错误消息。

同样使用 VPC Serverless Connector 也行不通,因为这更多是连接 VPC 中的资源(如 VM 或 Memorystore 实例)的桥梁,而不是 Cloud Function,因为这也是一个无服务器产品,而且它确实在 VPC 中没有 IP。

我认为这里有三个选项:

  1. 使用 App Engine Flex:

    由于 App Engine Flex 使用 VM 实例,这些实例将成为 VPC 的一部分,即使设置了“仅允许内部流量”选项,您也可以访问函数。

  2. 使用虚拟机作为代理:

    您可以创建一个 VPC Serverless Connector 并将其分配给 App Engine 中的应用程序。然后您可以创建一个 VM 并使用 VM 作为代理来访问该功能。由于成本原因,这不是最佳选择,但最终是一个选择。

  3. 最后一个选项认为函数可以使用Allow All Traffic选项:

    您可以在 Cloud Function 上设置一些安全性以仅允许特定的服务帐户,并且您可以使用 this sample code 进行身份验证。

    已编辑:

    @gaefan 在 .

    中分享了此选项的一个很好的代码示例

@GAEfan 说的对

作为补充:我使用官方 Google Auth 库给我必要的 headers。

const {GoogleAuth} = require('google-auth-library');
// Instead of specifying the type of client you'd like to use (JWT, OAuth2, etc)
// this library will automatically choose the right client based on the environment.
const googleCloudFunctionURL = 'https://europe-west1-project.cloudfunctions.net/function';
(async function() {
  const auth = new GoogleAuth();
  let googleCloudFunctionClient = await auth.getIdTokenClient(googleCloudFunctionURL);
  console.log(await googleCloudFunctionClient.getRequestHeaders(googleCloudFunctionURL));
})();