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

How should I store access tokens generated by another application using Google Cloud KMS?

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

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

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

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

感谢您的帮助!

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

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

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

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

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

Can I encrypt a large number of access tokens with a single key or do I need to create a new key for every access token?

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

If I ever need to modify the access token encrypted at KMS, can I simply modify it or do I need to destroy the old version and encrypt again?

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

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

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

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

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

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

然后您可以从您的应用程序访问机密。这是节点的示例:

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 权限。