在HTTP Google Cloud Function(NodeJS)中同步加载机密

时间:2019-07-11 10:01:40

标签: node.js google-cloud-functions google-cloud-storage google-cloud-kms

我有一个提供登录API端点的Google Cloud Function。该功能使用私钥对JWT进行签名。

现在,在部署功能时,我需要安全地加载用于签名JWT的私钥。我当然不能使用环境变量,也不能将其嵌入代码的任何部分,因为任何在gcloud中读取该函数的人都可以看到。

我考虑的选项是:

  1. 为此功能创建专用的服务帐户,以及仅该服务帐户可以访问的GCS存储桶,并将机密信息以纯文本格式存储在其中。加载函数后,加载秘密(await loadMySecrets(...))并继续。

  2. 推荐的方法:创建一个KMS密钥,用该密钥加密秘密,然后将密文和功能代码一起上传。在运行时,要求KMS解密密钥(await decryptSecret(...))。

问题是:据我所知,当加载HTTP函数时,整个加载过程必须是同步的

您的函数返回一个请求处理程序,然后GCF执行该请求处理程序。在返回请求处理程序之前,没有机会await进行Promise,并且GCF不支持HTTP函数的返回Promises。 GCS和KMS API是基于Promise的,不支持*Sync()调用。

其他人如何解决这个问题?我无法同步等待Promise解决(例如,通过sleep()),因为那样会阻塞Node事件循环。我是否被迫以某种方式同步提供机密,或者有一种方法可以使其与GCF完美兼容?

注意:这是普通的Google Cloud Functions,不是 Firebase。

注2:有一个核心选​​择,即将异步方面转移到Express中间件中。我真的非常不想这样做,因为我不得不包装cookie-parserpassport之类的东西,它们期望在初次创建中间件时可以在秘密的中间件中加载秘密然后代表。丑陋,可能会影响性能。

1 个答案:

答案 0 :(得分:1)

您可以使整个函数处理程序异步(需要节点8 +):

const decrypt = async (ciphertext) => {
  result = await client.decrypt({
      name: cryptoKeyID,
      ciphertext: ciphertext,
  });
  return result.plaintext;
}

exports.F = async (req, res) => {
  const username = await decrypt(process.env.DB_USER);
  const password = await decrypt(process.env.DB_PASS);
  res.send(`${username}:${password}`)
}

我看到了您关于中间件的说明。如果您发布代码示例,我将尝试对其进行更新以使其更好地匹配。