我应该如何使用 Google Cloud KMS 存储由另一个应用程序生成的访问令牌?

Posted

技术标签:

【中文标题】我应该如何使用 Google Cloud KMS 存储由另一个应用程序生成的访问令牌?【英文标题】:How should I store access tokens generated by another application using Google Cloud KMS? 【发布时间】:2018-07-24 23:52:54 【问题描述】:

我正在构建一个 Node.js 应用程序,该应用程序从我需要访问的另一个应用程序接收长期访问令牌。我不想将这些访问令牌直接存储在数据库中,因为有权访问这些令牌的任何人基本上都可以用它做任何他们想做的事情。

我是 Cloud KMS 和一般此类系统的新手,但我花了最后几个小时学习它。这似乎是解决我的问题的理想解决方案,但我不完全确定应该遵循什么策略来存储这些访问令牌:

    我是否应该将加密密钥存储在 Cloud KMS 中,并使用该加密密钥与 this one 之类的 NPM 包一起在我的数据库中存储访问令牌? 我应该将访问令牌直接存储在 KMS 中吗?我的假设是我将拥有一个密钥库,并且每 14 天轮换一次密钥。每当我收到访问令牌时,我只需对其进行加密并将其存储在 KMS 中。我只将密文存储在我的数据库中。当我需要从 KMS 访问访问令牌时,我使用密文对其进行解密。

以上哪项是使用 KMS 的正确方法?如果是选项 2,我还有其他问题:

能否使用单个密钥加密大量访问令牌,还是需要为每个访问令牌创建一个新密钥? 如果我需要修改在 KMS 加密的访问令牌,我可以简单地修改它还是需要销毁旧版本并重新加密?

感谢您的帮助!

【问题讨论】:

【参考方案1】:

您的选项 2 很好,只要访问令牌足够小,可以使用 API 加密(几千字节或更小)。您可以使用相同的密钥加密任意数量的令牌,而不会影响安全性。

除非您有特殊需要,否则 14 天密钥轮换似乎比必要更频繁。

我不明白你的修改问题。如果您修改了访问令牌并希望保存修改后的版本,您可能应该使用您的密钥对其进行加密,然后保存加密的数据。

【讨论】:

感谢您的回复。访问令牌 是的,如果您需要保存更新的访问令牌,您应该对其进行加密并将其存放在您的存储中。【参考方案2】:

我认为您最好的选择是使用Node.js API provided by Google 来加密令牌并将生成的密文存储在您的数据库中。

当应用程序从其他应用程序接收到令牌时,它会使用 API 对其进行加密并与数据库中的内容进行比较以查看它是否有效,这样纯文本令牌只有所有者知道。

我可以使用单个密钥加密大量访问令牌,还是需要为每个访问令牌创建一个新密钥?

您可以使用相同的密钥加密任意数量的令牌。为每个令牌创建一个密钥很快就会变得难以管理,除非他们自己密钥,否则它会被泄露(很难想象只存储在 Google 中)没​​有重大风险。

如果我需要修改在 KMS 加密的访问令牌,我可以简单地修改它还是需要销毁旧版本并重新加密?

KMS 不会存储您的数据,无论是加密的还是纯文本的,它只是存储加密或解密数据所需的 KEY。

按照只存储加密版本令牌的方法,当你需要修改一个令牌时,应该是这样的:

客户端向您发送需要撤销的令牌。 您的应用程序对其进行加密并将其与存储在数据库中的令牌进行比较 新令牌已生成(我理解是由您的客户端应用程序生成的?) 它被发送到您的应用程序,它会对其进行加密 新版本替换旧版本令牌 客户端现在可以使用新令牌,因为它与以前的令牌具有相同的有效性。如果它尝试使用旧令牌,因为它不再在数据库中,它将无法工作。

关于密钥轮换,当它发生时,新令牌将使用新密钥加密。旧令牌仍然无法加密,因为您的旧密钥仍在 KMS 上,只是不再用于加密。 但是,如果您销毁用于加密它们的密钥,它们将无法恢复。

【讨论】:

【参考方案3】:

截至 2019 年 12 月,在 Google Cloud 上存储和管理机密的首选方式是Secret Manager:

$ echo -n "my-access-token" | gcloud beta secrets create "access-token" \
  --data-file=- \
  --replication-policy "automatic"

然后您可以从您的应用程序中访问机密。以下是 Node 的示例:

function getSecret() 
  const [version] = await client.accessSecretVersion(
    name:"projects/<YOUR-PROJECT-ID>/secrets/access-token/versions/1",
  );

  const auth = version.payload.data.toString('utf-8');

  // auth is "my-access-token"
  return auth

任何需要访问密钥的服务都需要对密钥的roles/secretmanager.secretAccessor 权限。

【讨论】:

以上是关于我应该如何使用 Google Cloud KMS 存储由另一个应用程序生成的访问令牌?的主要内容,如果未能解决你的问题,请参考以下文章

Google Cloud KMS:无法解密

Google Cloud KMS App Engine 加密不起作用

Google Cloud KMS 错误 - 您所在地区无法访问此 API。 (HTTP 状态 - 403)

您可以在具有服务角色的项目之间共享 Google Cloud KMS 密钥吗?

关于使用 Cloud KMS 进行签名验证的问题

Cloud Function 使用 KMS 密钥解密的权限被拒绝