1. 简介
概览
Cloud Run 函数是一个轻量级计算解决方案,可供开发者创建单一用途的独立函数,这些函数可使用 HTTPS 触发或响应 CloudEvents,而无需管理服务器或运行时环境。如需详细了解 Cloud Run 函数,请参阅我们的博文。
您可以通过两种主要方法控制对 Cloud Run 函数的调用:基于身份保障访问权限和使用基于网络的访问权限控制保障访问权限。此 Codelab 重点介绍了第一种方法,并将引导您完成 3 种基于身份安全地调用函数的场景:
- 使用 gcloud 身份令牌调用函数以进行本地开发和测试
- 在本地开发和测试时模拟服务账号,以使用与正式版相同的凭据
- 使用 Google 客户端库处理对 Google Cloud API 的身份验证,例如在服务需要调用函数时
学习内容
- 如何在 Cloud Run 函数上配置身份验证,以及如何验证身份验证是否已正确配置
- 通过为您的 gcloud 身份提供令牌,从本地开发环境调用经过身份验证的函数
- 如何创建服务账号并向其授予调用函数的适当角色
- 如何从具有调用函数所需适当角色的本地开发环境中冒充服务
2. 设置和要求
前提条件
- 您已登录 Cloud 控制台
- 您之前部署了一个 HTTP 触发的 Cloud Run 函数。查看快速入门示例。
- (可选)对于第 3 种场景,本 Codelab 使用 Node.js 和 npm 作为示例,但您可以使用 Google 身份验证客户端库支持的任何运行时。
激活 Cloud Shell
- 在 Cloud Console 中,点击激活 Cloud Shell
。
如果这是您首次启动 Cloud Shell,系统会显示一个中间屏幕,介绍 Cloud Shell 是什么。如果系统显示中间屏幕,请点击继续。
预配和连接到 Cloud Shell 只需花几分钟时间。
此虚拟机已加载所需的所有开发工具。它提供了一个持久的 5 GB 主目录,并且在 Google Cloud 中运行,大大增强了网络性能和身份验证。您在此 Codelab 中的大部分(甚至全部)工作都可以使用浏览器完成。
连接到 Cloud Shell 后,您应该会看到自己已通过身份验证,并且项目已设置为您的项目 ID。
- 在 Cloud Shell 中运行以下命令以确认您已通过身份验证:
gcloud auth list
命令输出
Credentialed Accounts ACTIVE ACCOUNT * <my_account>@<my_domain.com> To set the active account, run: $ gcloud config set account `ACCOUNT`
- 在 Cloud Shell 中运行以下命令,以确认 gcloud 命令了解您的项目:
gcloud config list project
命令输出
[core] project = <PROJECT_ID>
如果不是上述结果,您可以使用以下命令进行设置:
gcloud config set project <PROJECT_ID>
命令输出
Updated property [core/project].
3. 创建和测试经过身份验证的 Cloud Run 函数
需要身份验证意味着调用函数的主账号必须具有 Cloud Run Invoker 角色;否则,该函数将返回 403 Forbidden 错误。此 Codelab 将介绍如何向正文授予适当的调用方角色。
为简化版 gcloud 命令设置本地环境变量
首先,您要创建一些环境变量,以提高此 Codelab 中使用的 gcloud
命令的可读性。
REGION=us-central1 PROJECT_ID=$(gcloud config get-value project)
创建函数的源代码
虽然本 Codelab 使用的是 Node.js,但您也可以使用 Google Auth 客户端库支持的任何运行时。
首先,创建一个目录并通过 cd 命令进入该目录。
mkdir auth-function-codelab && cd $_
然后,创建 package.json 文件。
touch package.json echo '{ "dependencies": { "@google-cloud/functions-framework": "^3.0.0" } } ' > package.json
接下来,创建 index.js 源文件。
touch index.js echo 'const functions = require("@google-cloud/functions-framework"); functions.http("helloWorld", (req, res) => { res.send(`Hello ${req.query.name || req.body.name || "World"}!`); });' > index.js
创建经过身份验证的函数
以下是针对 nodejs20 运行时创建经过身份验证的函数的步骤。不过,您可以使用 Google Auth 客户端库支持的任何运行时。
FUNCTION_NAME=authenticated-function-codelab ENTRY_POINT=helloWorld
如需将 Cloud Run 函数直接部署到 Cloud Run,请运行以下命令:
gcloud beta run deploy $FUNCTION_NAME \ --source . \ --function helloWorld \ --region $REGION \ --no-allow-unauthenticated
然后,您可以将函数网址保存为环境变量以供日后使用。
FUNCTION_URL="$(gcloud run services describe $FUNCTION_NAME --region $REGION --format 'value(status.url)')"
如果您想以 Cloud Functions (第 2 代) 的形式进行部署,请使用以下命令:
gcloud functions deploy nodejs-http-function \ --gen2 \ --runtime=nodejs20 \ --region=$REGION \ --source=. \ --entry-point=helloWorld \ --trigger-http \ --no-allow-unauthenticated
然后,您可以将函数网址保存为环境变量供日后使用。
FUNCTION_URL="$(gcloud functions describe $FUNCTION_NAME --gen2 --region us-central1 --format='get(serviceConfig.uri)')"
尝试以匿名调用者身份调用该函数,验证该函数是否需要身份验证
您将在不进行身份验证的情况下调用该函数,以验证是否会收到预期的 403 错误。
在命令行中,运行以下 curl
命令:
curl -i $FUNCTION_URL
您将看到以下结果:
<html><head> <meta http-equiv="content-type" content="text/html;charset=utf-8"> <title>403 Forbidden</title> </head> <body text=#000000 bgcolor=#ffffff> <h1>Error: Forbidden</h1> <h2>Your client does not have permission to get URL <code>/</code> from this server.</h2> <h2></h2> </body></html>
现在,您可以浏览 3 种场景,了解如何通过提供身份验证来调用函数。
4. 场景 1:使用 gcloud 身份令牌
作为开发者,您需要一种方法来在本地开发函数时对其进行测试。在本部分中,您将执行一项快速测试,以验证该函数是否已使用您自己的身份正确进行身份验证。
通过运行以下命令,验证您是否已使用 gcloud
进行身份验证:
gcloud auth list
您应该会在您的活跃身份旁边看到一个星号,例如:
Credentialed Accounts ACTIVE ACCOUNT * <my_account>@<my_domain.com> To set the active account, run: $ gcloud config set account `ACCOUNT`
如需详细了解如何设置 gcloud init 和 gcloud auth login,请参阅文档。
接下来,调用函数并向其传递您的身份令牌。
curl $FUNCTION_URL -H "Authorization: bearer $(gcloud auth print-identity-token)"
现在,您将看到结果:
Hello World!
问题排查
如果您收到 403 Forbidden 错误,请确保您的身份具有 Cloud Run Invoker 角色。您可以使用 IAM 控制台验证授予主账号的角色。
虽然使用自己的身份令牌是在开发期间快速测试函数的一种方法,但经过身份验证的函数的调用方需要具有适当的角色;否则,调用方会收到 403 Forbidden 错误。
您需要遵循最小权限原则,限制具有调用函数角色的身份和服务账号的数量。在下一个场景中,您将了解如何创建新的服务账号并向其授予适当的角色,以便调用函数。
5. 场景 2:冒充服务账号
在这种情况下,您需要模拟(即假定服务账号的权限)服务账号,以便在本地进行开发和测试时调用函数。通过模拟服务账号,您可以使用在生产环境中所用的凭据对函数进行测试。
这样一来,您不仅可以验证角色,还可以遵循最小权限原则,而无需仅出于本地测试目的向其他身份授予 Cloud Functions Invoker 角色。
在本 Codelab 中,您将创建一个新服务账号,该账号仅具有调用您在本 Codelab 中创建的函数的角色。
创建新服务账号
首先,您需要创建另外几个环境变量,用于表示 gcloud 命令中使用的服务账号。
SERVICE_ACCOUNT_NAME="invoke-functions-codelab" SERVICE_ACCOUNT_ADDRESS=$SERVICE_ACCOUNT_NAME@$PROJECT_ID.iam.gserviceaccount.com
接下来,您需要创建服务账号。
gcloud iam service-accounts create $SERVICE_ACCOUNT_NAME \ --display-name="Cloud Run function Authentication codelab"
并向服务账号授予 Cloud Run Invoker 角色:
gcloud run services add-iam-policy-binding $FUNCTION_NAME \ --region=us-central1 \ --member serviceAccount:$SERVICE_ACCOUNT_ADDRESS \ --role='roles/run.invoker'
通过模拟服务账号来调用函数
为此,您需要获取新创建的服务账号的 ID 令牌,以便模拟该服务账号。
添加所需的角色以进行冒充
要模拟服务账号,您的用户账号需要具有 Service Account Token Creator (roles/iam.serviceAccountTokenCreator) 角色,才能为服务账号生成 ID 令牌。
您可以运行以下命令,向有效的用户账号授予此角色:
ACCOUNT_EMAIL=$(gcloud auth list --filter=status:ACTIVE --format="value(account)") gcloud iam service-accounts add-iam-policy-binding $SERVICE_ACCOUNT_ADDRESS \ --member user:$ACCOUNT_EMAIL \ --role='roles/iam.serviceAccountTokenCreator'
使用服务账号的 ID 令牌
请等待几分钟,让权限传播完毕。现在,您可以通过传递服务账号的 ID 令牌来调用函数。
curl $FUNCTION_URL -H "Authorization: bearer $(gcloud auth print-identity-token --impersonate-service-account $SERVICE_ACCOUNT_ADDRESS)"
您将看到以下内容:
WARNING: This command is using service account impersonation. All API calls will be executed as [invoke-functions-codelab@<project-id>.iam.gserviceaccount.com]. Hello World!
6. 场景 3:使用 Google 客户端库
在本 Codelab 的最后一部分,您将在本地运行一项小型服务,为服务账号生成 ID 令牌,然后使用 Google Auth 客户端库和应用默认凭据 (ADC) 以编程方式调用该函数。如需详细了解 Google 客户端库,请参阅文档的客户端库说明部分。
如果您想在本地(例如在笔记本电脑上、Cloud Shell 中等)编写和测试函数,同时与其他 Google Cloud 资源(例如 Cloud Storage、Vision API 等)进行交互,使用 ADC 尤为重要在本例中,您将了解如何让服务调用另一个需要进行身份验证的函数。如需详细了解 ADC 和本地开发,请参阅博文 如何在本地开发和测试 Cloud Functions 函数 | Google Cloud 博客
运行 gcloud 命令以冒充服务账号
ADC 会根据应用环境自动查找凭据,并使用这些凭据向 Google Cloud API 进行身份验证。借助 –impersonate-service-account 标志,您可以使用服务账号的身份对 Google Cloud API 进行身份验证,从而模拟该服务账号。
如需冒充服务账号,您可以运行以下命令:
gcloud auth application-default login --impersonate-service-account=$SERVICE_ACCOUNT_ADDRESS
现在,您将以该服务账号(而非您的身份)运行 gcloud 命令。
创建并运行服务以调用经过身份验证的函数
每个运行时都有自己的 Google Auth 客户端库,您可以安装该库。此 Codelab 将指导您在本地创建和运行 Node.js 应用。
针对 Node.js 的步骤如下:
- 创建新目录
mkdir local-dev && cd $_
- 创建新的 Node.js 应用
npm init -y
- 安装 Google Auth 客户端库
npm install google-auth-library
- 创建
index.js
文件 - 检索 Cloud Run 函数的网址,以在下一步中将其添加到代码中。
echo $FUNCTION_URL
- 将以下代码添加到 index.js。请务必将 targetAudience 变量更改为您的 Cloud Run 函数网址。
index.js
// Cloud Functions uses your function's url as the `targetAudience` value
const targetAudience = '<YOUR-CLOUD-RUN-FUNCTION-URL>';
// For Cloud Functions, endpoint(`url`) and `targetAudience` should be equal
const url = targetAudience;
const { GoogleAuth } = require('google-auth-library');
const auth = new GoogleAuth();
async function request() {
console.info(`request ${url} with target audience ${targetAudience}`);
// this call retrieves the ID token for the impersonated service account
const client = await auth.getIdTokenClient(targetAudience);
const res = await client.request({ url });
console.info(res.data);
}
request().catch(err => {
console.error(err.message);
process.exitCode = 1;
});
- 运行应用
node index.js
您应该会看到生成的“Hello World!”
问题排查
如果您看到“系统拒绝对资源授予权限‘iam.serviceAccounts.getOpenIdToken’(或该权限可能不存在)”错误,请等待几分钟,以便 Service Account Token Creator 角色传播。
如果您收到“无法在此环境中提取 ID 令牌”错误,请使用 GCE 或将 GOOGLE_APPLICATION_CREDENTIALS 环境变量设置为服务账号凭据 JSON 文件,那么您可能忘了运行该命令
gcloud auth application-default login --impersonate-service-account=$SERVICE_ACCOUNT_ADDRESS
7. 恭喜!
恭喜您完成此 Codelab!
建议您查看有关如何保护 Cloud Run 函数的文档。
我们还建议您参阅这篇关于使用 Cloud Run 函数进行本地开发的博文,了解如何在本地开发者环境中开发和测试 Cloud Run 函数。
所学内容
- 如何对 Cloud Run 函数配置身份验证并验证是否已正确配置身份验证
- 通过为您的 gcloud 身份提供令牌,从本地开发环境调用经过身份验证的函数
- 如何创建服务账号并向其授予调用函数的适当角色
- 如何从具有调用函数所需适当角色的本地开发环境中冒充服务
8. 清理
为避免产生意外费用(例如,此 Cloud Functions 函数被意外调用的次数超过免费层级每月 Cloud Run 函数调用次数),您可以删除该 Cloud Functions 函数或删除您在第 2 步中创建的项目。
如需停止模拟服务账号,您可以使用自己的身份重新登录:
gcloud auth application-default login
如需删除 Cloud Run 函数,请前往 Cloud Run 函数 Cloud 控制台 (https://console.cloud.google.com/functions/)。确保您在第 2 步中创建的项目是当前所选项目。
选择您之前部署的 my-authenticated-function。然后点击删除。
如果您选择删除整个项目,可以前往 https://console.cloud.google.com/cloud-resource-manager,选择您在第 2 步中创建的项目,然后选择“删除”。如果您删除该项目,则需要在 Cloud SDK 中更改项目。您可以通过运行 gcloud projects list
来查看所有可用项目的列表。