Как хранить токены доступа, созданные другим приложением с помощью Google Cloud KMS?

Я создаю приложение Node.js, которое получает токен долгосрочного доступа от другого приложения, к которому мне нужно получить доступ. Я не хочу хранить эти токены доступа непосредственно в базе данных, поскольку любой, кто имеет доступ к этим токенам, может делать с ним все, что захочет.

Я новичок в облачной KMS и подобных системах в целом, но провел последние несколько часов, изучая ее. Это кажется идеальным решением для решения моей проблемы, но я не совсем уверен, какую стратегию я должен придерживаться, чтобы хранить эти токены доступа:

  1. Должен ли я хранить ключ шифрования в Cloud KMS и использовать этот ключ шифрования с пакетом NPM, подобным этому, для хранения токенов доступа в моей базе данных?
  2. Стоит ли хранить токены доступа в KMS напрямую? Я предполагаю, что у меня будет хранилище ключей, а ключи меняются каждые 14 дней. Всякий раз, когда я получаю токен доступа, я просто шифрую его и сохраняю в KMS. Я храню только зашифрованный текст в своей базе данных. Когда мне нужно получить доступ к токену доступа из KMS, я использую зашифрованный текст для его расшифровки.

Что из перечисленного является правильным способом использования KMS? Если это вариант 2, у меня есть дополнительные вопросы:

  • Могу ли я зашифровать большое количество токенов доступа одним ключом или мне нужно создать новый ключ для каждого токена доступа?
  • Если мне когда-нибудь понадобится изменить токен доступа, зашифрованный в KMS, могу ли я просто изменить его или мне нужно уничтожить старую версию и снова зашифровать?

Спасибо за вашу помощь!

2 ответа

Решение

Я думаю, что вам лучше всего использовать API Node.js, предоставляемый Google, для шифрования токенов и сохранения полученного зашифрованного текста в вашей базе данных.

Когда приложение получает токен от другого приложения, оно зашифровывает его с помощью API и сравнивает с тем, что оно имеет в базе данных, чтобы увидеть, является ли оно действительным, таким образом, простой текстовый токен известен только владельцу.

Могу ли я зашифровать большое количество токенов доступа одним ключом или мне нужно создать новый ключ для каждого токена доступа?

С помощью одного и того же ключа вы можете зашифровать столько токенов, сколько захотите. Создание ключа для каждого токена довольно скоро станет неуправляемым, и, если они сами не введут ключ, он скомпрометирован (что трудно представить, чтобы хранить его только в Google), значительного риска нет.

Если мне когда-нибудь понадобится изменить токен доступа, зашифрованный в KMS, могу ли я просто изменить его или мне нужно уничтожить старую версию и снова зашифровать?

KMS не хранит ваши данные, в зашифрованном виде или в виде обычного текста, он просто хранит ключ, необходимый для шифрования или дешифрования ваших данных.

Следуя методу хранения только зашифрованной версии токенов, когда вам нужно изменить один токен, он должен выглядеть следующим образом:

  • Клиент отправляет вам токен, который необходимо отозвать.
  • Ваше приложение шифрует его и сравнивает с токенами, хранящимися в БД.
  • Новый токен сгенерирован (вашим клиентским приложением я понимаю?)
  • Он отправлен в ваше приложение, которое шифрует его
  • Старая версия токена заменяется новой версией
  • Теперь клиент может использовать новый токен, так как он имеет тот же срок действия, что и предыдущий. Если он попытается использовать старый токен, так как его больше нет в БД, он не будет работать.

Что касается ротации ключей, когда это произойдет, новые токены будут зашифрованы с новыми ключами. Старые токены по-прежнему не будут шифроваться, потому что ваши старые ключи все еще находятся в KMS, но больше не используются для шифрования. Однако, если вы уничтожите ключ, которым они были зашифрованы, они не будут восстановлены.

По состоянию на декабрь 2019 года предпочтительным способом хранения и управления секретами в 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 разрешения по секрету.

Вариант 2 подойдет, если токены доступа достаточно малы для шифрования с помощью API (несколько тысяч байт или меньше). С помощью одного и того же ключа вы можете зашифровать столько токенов, сколько вам нужно, без ущерба для безопасности.

14-дневная ротация клавиш кажется более частой, чем необходимо, если только у вас нет особой необходимости

Я не понимаю ваш вопрос модификации. Если вы изменили токен доступа и хотите сохранить измененную версию, вам, вероятно, следует зашифровать его своим ключом, а затем сохранить зашифрованные данные.