我成功了!这是我学到的。
我使用 IAM 服务帐户将 Firebase Cloud Function 连接到 Google Cloud Translate。这些说明也适用于 Google Cloud Functions 和其他 Google Cloud 服务。
概述保护云功能说云功能安全可以是基于身份的 or 基于网络的。在基于身份的类别中,您可以使用用户帐号(用户名和密码)或服务帐户。服务帐户似乎是首选方法,因此在这个答案中我将只讨论服务帐户。
IAM 和服务账户
Google Cloud Console 一开始可能会让人不知所措。您从一个用户帐户开始,这可能是您的 Gmail 地址。然后你创建一个组织,并在你的组织中创建一个项目。
然后寻找IAM & Admin
. IAM
代表身份访问管理。服务帐户看起来像电子邮件地址。这提供了一个identity到 Googleverse 中的云功能。换句话说,为您的 Cloud Functions 创建服务帐户使其能够与 Google Cloud 中的其他内容进行交互。该文件函数恒等式讨论服务帐户的这个方面。
服务帐户有校长 and roles。您的服务帐户之一应该是您的电子邮件地址以及您的姓名和角色Owner。该文件使用 IAM 授权访问s 显示如何向服务帐户授予主体和角色。
将其他服务帐户视为您的仆从,他们听从您的命令。有些是在您注册 Google Cloud 服务时自动创建的。
当您想做一些事情时,您可以创建新的服务帐户。例如,我编写了一个将英语翻译成西班牙语的 Firebase Cloud Function。我希望这个函数调用 Google Cloud Translate。服务帐户旨在完成一件事。服务帐户是以以下结尾的电子邮件地址iam.gserviceaccount.com
.
因为服务帐户执行某些操作,所以您可以将角色分配给服务帐户。在本例中,我的服务帐户调用 Google Cloud Translate,因此我为其分配角色Cloud Translation API User
.
因为服务帐户确实只有一件事你分配一个作用有限到服务帐户。例如,我的翻译服务帐户无法在 Google Cloud Dataplex 中执行操作。它也不会成为Cloud Translation API Editor
or Admin
。这只是一个Cloud Translation API User
minion.
建立一个服务帐户
在您的 Google Cloud Console 下IAM & Admin
寻找Service Accounts
在左侧边栏中。在顶部栏中查找+ CREATE SERVICE ACCOUNT
.
您可以为您的服务帐户命名任何您想要的名称。我建议将其命名为您的 Firebase 云函数的名称。这清楚地表明了服务帐户的用途。为了更加清楚地写在Service account description
就像是This service account hooks up the Firebase Cloud Function SuperTranslator to Google Cloud Translate.
在将来的某个时候,您将拥有太多的服务帐户,并且您会想要删除一些。
Click DONE
.
将角色分配给服务帐户
现在点击IAM
under IAM & Admin
在左侧边栏中。您的服务帐户应该在那里,因为服务帐户是一种特殊类型的 IAM。
在右侧单击与您的服务帐户关联的铅笔。在下面Assign roles
滚动浏览数百个选项,找到您希望服务帐号使用的 Google Cloud 产品或服务。选择产品或服务后,选择角色。
正如我之前提到的,分配使您的功能能够正常工作的最低角色。就我的翻译功能而言,有四种选择:Admin
, Editor
, User
, and Reader
。卑微者Reader
Minions 只允许阅读策略和组织描述。User
Minions 可以访问 Google Cloud 服务。这就是我希望我的服务帐户执行的操作。Editor
可以编辑政策和组织描述以及Admin
拥有对政策和组织描述的完全访问权限。我不希望这个服务帐户做那些事情。
回到你的IAM
页面,您会在右侧注意到每个 IAM 的计数多余的权限(穿蓝色衣服)。这可能是一个Admin
仅被要求执行的角色User
级别的东西。单击蓝色三角形有时会建议您采取一些措施来减少多余的权限。换句话来说,IAM 的目的是给予每个 Minion 足够的权限来完成其工作,而不是更多。
下载您的服务帐户 JSON 文件
现在您将把凭据下载到您的计算机上。在您的 Google Cloud Console 中,转到IAM and admin
, then Service accounts
。单击您想要的服务帐户。
选择KEYS
标签。点击ADD KEYS
按钮并选择Create new key
。选择JSON
单选按钮。将打开一个模式窗口,询问您将密钥下载到哪里。我有一个用于存放服务帐户密钥的文件夹:
ProjectDirectory/environments/service_account_keys
如果您打开密钥文件,您将看到:
{
"type": "service_account",
"project_id": "my-project",
"private_key_id": "12345abcde",
"private_key": "-----BEGIN PRIVATE KEY-----\n1673randomcharacters...=\n-----END PRIVATE KEY-----\n",
"client_email": "[email protected]",
"client_id": "12345",
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
"token_uri": "https://oauth2.googleapis.com/token",
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
"client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/google-cloud-service%40my-project.iam.gserviceaccount.com",
"universe_domain": "googleapis.com"
}
不要尝试获取现有密钥的服务帐户密钥 JSON。据我所知,这是不可能的。如果您需要下载服务帐户密钥,请创建一个新密钥。他们是免费的。
将您的云功能连接到您的服务帐户密钥
这是疯狂的、未记录的部分。 Google Cloud 支持人员甚至不知道这一点。
将您的 Cloud Function 连接到您的服务帐户密钥以在Firebase 模拟器, 做一个TranslationServiceClient(options)
object:
const options = {
keyFilename: '/Users/TDK/VisualStudioCodeProjects/MyProjectDirectory/environments/service_account_keys/my-project-12345.json',
};
import { TranslationServiceClient } from '@google-cloud/translate';
const translationClient = new TranslationServiceClient(options);
您将服务帐户密钥的路径作为参数传递TranslationServiceClient(options)
. Your options
对象具有单一属性,keyFilename
。该属性的值是您的服务帐户密钥的路径。我更喜欢绝对路径,但如果您愿意,也可以使用相对路径。
这是文档为了TranslationServiceClient
类型。您可以看到还有更多属性。看起来你可以使用credentials
属性将服务帐户电子邮件及其私钥放入您的云功能中。这将是一个坏主意,因为您可能会无意中将您的云功能上传到不安全的存储库并将您的私钥暴露给公众。
将您的 Cloud Function 连接到您的服务帐户密钥以在Firebase 云, 做一个GOOGLE_APPLICATION_CREDENTIALS
持续的:
import { TranslationServiceClient } from '@google-cloud/translate';
const translationClient = new TranslationServiceClient();
export const GOOGLE_APPLICATION_CREDENTIALS = '/Users/TDK/VisualStudioCodeProjects/MyProjectDirectory/environments/service_account_keys/my-project-12345.json';
不要问我花了多长时间才发现 Firebase 模拟器和云需要不同的代码。
使用服务帐户部署您的云功能
通常我们像这样部署 Firebase Cloud Functions:
firebase deploy --only functions:myAwesomeFunction
还有另一种部署 Cloud Functions 的方法,它允许您连接服务帐户:
gcloud functions deploy myAwesomeFunction --service-account [email protected]
如果您使用以下方式部署云功能gcloud
并且您不需要在代码中连接凭据密钥文件的服务帐户。这很容易并且看起来安全性更高。
然而......上次我尝试这样做时,我收到一个错误,说它找不到lib/index.js
文件。这是指定的文件main
财产在functions/package.json
。当你跑步时npm run build
在部署 Cloud Function 之前,TypeScript 会将您的代码转换为 JavaScript,从src/index.ts
to lib/index.js
. gcloud
以前可以找到JavaScript文件,但现在不能了。
而 Firebase 团队从未实现过这一点。你不能这样做:
firebase deploy --only functions:myAwesomeFunction --service-account [email protected]
显然这不建议用于 Firebase Cloud Functions。
我没有看到这个答案中引用的文档。因此,这可能不是保护服务帐户访问的最佳方法。
测试你的功能
调用您的函数并查看日志,您应该会看到 Firebase Cloud 函数执行。
请记住使用以下命令转译你的 TypeScriptnpm run build
在模拟器中调用函数之前。
使用服务帐户修复 CORS 错误
有时,您在调用云函数时会遇到 CORS 错误。您可以使用服务帐户来修复 CORS 错误。选择您的项目服务帐户([email protected]
),创建一个新密钥,并将其保存到您的environments
。采取apiKey
属性,将其作为参数传递defineSecret()
,然后使用以下命令调用云函数apiKey
:
import { defineSecret } from "firebase-functions/params";
const apiKey = defineSecret("12345");
export const CallUppercase = onCall({ secrets: [apiKey] }, (request) => {
...
});
通常,这些不是 CORS 错误,而是其他错误,例如您没有将 Cloud Function 部署到云,或者在模拟器中调用 Cloud Function 之前没有对其进行转译。
工作负载身份联合
当您创建服务帐户密钥时,您会看到一个框,上面写着
如果服务帐户密钥遭到泄露,可能会带来安全风险。我们
建议您避免下载服务帐户密钥,而是
使用工作负载身份联合。您可以了解更多有关
在 Google Cloud 上验证服务帐号的最佳方式here.
后一个链接转到博客文章选择在 Google Cloud 上使用和验证服务帐号的最佳方式。这篇博文讨论了四个用例:
-
将服务帐号附加到 Cloud Functions、Cloud Run 以及 Google Cloud 上部署的其他应用程序
-
将服务帐户附加到 Kubernetes Pod
-
将服务帐号附加到未在 Google Cloud 上运行的应用
-
下载服务帐户密钥
我们只是做了后者,只有当前者选项不可用时才建议这样做。第一个选项似乎是谷歌推荐的。这工作负载身份联合文档讨论了 Amazon AWS、Microsoft Azure 和其他云计算平台,但没有讨论 Google Cloud Functions。这保护云功能文档是关于授权谁可以调用您的 Cloud Functions,而不是授权您的 Cloud Functions 调用其他 Google Cloud 服务。我找不到比下载的服务帐户密钥更好的连接 Cloud Functions for Cloud Services 的文档。