Google云端功能 - 如何在使用Google Source Repository时安全地存储服务帐户私钥?

时间:2018-02-03 22:05:21

标签: security google-cloud-functions google-cloud-source-repos

我使用Google Source Repository来存储我的Google Cloud Functions。 (Git repo由Google主持,基本上)

我的一个功能是需要访问私人Google表格文件,因此我创建了一个服务帐户。 (权利太多,因为很难理解我们应该给服务帐户的确切权限,以后很难更新,但我离题了)

现在,由于显而易见的原因,显然不建议将服务帐户JSON文件存储在git存储库中。这是它的样子(从值中剥离)

{
  "type": "service_account",
  "project_id": "",
  "private_key_id": "",
  "private_key": "",
  "client_email": "",
  "client_id": "",
  "auth_uri": "",
  "token_uri": "",
  "auth_provider_x509_cert_url": "",
  "client_x509_cert_url": ""
}

我一直在寻找环境变量来配置一个函数或类似的东西,但没有找到任何东西。跟踪密钥(因此可能在几个存储库上复制该文件)确实听起来不是一个好主意。但我还没有找到任何“适当”的方法来做到这一点。由于Google Functions的工作方式,除了env变量外,我无法想到任何其他内容。

6 个答案:

答案 0 :(得分:2)

将云功能与服务帐户一起使用时,我的解决方案是:

  1. 使用Cloud KMS / vault加密您的服务帐户凭据json文件,并将其上传到Cloud Storage。
  2. 从Cloud Storage中获取服务帐户凭据json文件,并使用具有加密/解密权限的Cloud KMS服务帐户对其进行解密。

  3. 在运行时解析服务帐户凭据json文件,并获取GSM Mobile Application Component: returnResultLast (2) returnResultLast invokeID: 0 resultretres opCode: localValue (0) localValue: sendAuthenticationInfo (56) authenticationSetList: quintupletList (1) quintupletList: 1 item AuthenticationQuintuplet rand: 7a0e1fef7377beb09d6f2313fbc232a6 xres: 65da191e184b0499 ck: 47e13682e9b3f35476671de4ed25c876 ik: 371d8082deec7051c6cd08c93064c654 autn: 82bc2ddb1d92823455bceb8772f390ce private_keyclient_email

  4. 将这三个秘密变量传递给客户端库

我们将配置变量存储为云函数的环境变量,它们是纯文本格式,但是可以。因为它们不是秘密的东西。

我们绝不能存储诸如纯文本之类的秘密内容,例如云函数环境变量。

答案 1 :(得分:2)

截至2020年1月,Google已发布Secret Manageris described as

Secret Manager是一项新的Google Cloud服务,它提供了一种安全便捷的方法来存储API密钥,密码,证书和其他敏感数据。 Secret Manager提供了一个集中的地方和单一的真理来源,可以跨Google Cloud管理,访问和审计秘密。

对于Cloud Functions,有一个教程here,介绍了如何创建秘诀然后从云函数中检索秘密。

答案 2 :(得分:0)

您可以上传服务帐户文件以及您的功能,并在代码中使用它。它将保持安全。大多数开发人员将使用.gitignore或等效机制来防止该文件被添加到源代码控制中。有一个从Firebase samples加载服务帐户凭据的示例。 (如果您未使用Firebase SDK,则必须注意将功能定义转换为云样式。

您也可以使用env var,但是您必须特别注意引用和转义值以确保它们正确地运行您的函数。这是一种麻烦,但可行。

答案 3 :(得分:0)

Here您可以使用环境变量GOOGLE_APPLICATION_CREDENTIALS找到如何为您的应用提供凭据。

答案 4 :(得分:0)

这就是我解决此问题的方法。首先在keys.js文件中创建逻辑,以确定您是在开发还是生产中(并创建相应的./dev.js和./prod.js文件,您应在.ignore文件中包括./dev.js,以确保它没有上传到您的github远程):

function useCustomHook() {
  if (Math.random() > 0.5){
    const [a, setA] = useState(0)
  }
}

第二,您需要上述逻辑所在的keys.js文件,并根据从keys.js接收的数据创建凭证对象:

function MyComponent() {
  if (Math.random() > 0.5){
    const [a, setA] = useState(0)
  }
  return null
}

现在,对于每个Google Cloud Service,您都可以使用以下示例模式:

if (process.env.NODE_ENV === "production") {
  module.exports = require("./prod");
} else {
  module.exports = require("./dev");
}

答案 5 :(得分:0)

我认为您实际上不需要在代码中存储任何密钥文件。

您的功能使用指定的服务帐户(通常是“ App Engine默认服务帐户”,但您可以在“高级设置”中进行更改)运行。如果有特定需求,则应创建一个针对您的功能的服务帐户,并为其授予所有所需的权限。

在您的函数中,身份验证将自动使用Application Default Credentials进行,因此您不必关心任何事情(不必理会环境变量,密钥文件或其他任何东西)。只要确保您使用的语言是Google Cloud Client库,它们就会为您隐式处理一切。

我特别避免像@ slideshowp2那样提出创造性的解决方案。但我同意它们的用途(例如,假设我需要存储GCP范围之外的外部系统的凭据。在这种情况下,他的解决方案可能是一种可行的方式),但是仅使用Google服务,让我们保留它简单。