Безсерверная структура и служба управления ключами (KMS)
В основном я использую serverless
фреймворк безсерверный для функции, которая позволяет мне отправлять / получать электронную почту с помощью mailgun.
Для этого у меня есть config.js
файл установлен в моей безсерверной папке. это config.js
содержит все мои ключи API, адрес электронной почты, логин и т. д. для моей функции "mailgun".
Я хочу использовать Google Cloud KMS для шифрования ресурса config.js
, потому что я боюсь, что мои чувствительные данные будут украдены и неправильно использованы. Зашифрованный файл config.js.enc
, google_key_management_service
Но serverless deploy
не расшифровывает мой config.js.enc
, Это бросает мне ошибку ресурса / синтаксиса...
Любые решения / идеи, как я могу заставить KMS работать на мой config.js
файл в моем serverless
фреймворк?
Я также добавил теги AWS, потому что они имеют KMS, аналогичную Google Cloud. Но на самом деле я думаю, что настоящая проблема с serverless
рамки и заставить зашифрованные файлы работать при развертывании без сервера с sls deploy
команда, но я могу ошибаться.
1 ответ
Похоже, что серверная структура включает в себя встроенные функции AWS SSM:
functions:
myfunc:
# other config
environment:
TWITTER_ACCESS_TOKEN: ${ssm:myFunc}
Однако, как вы заметили, в GCP подобной функциональности нет, поэтому вам нужно будет выполнить некоторые действия самостоятельно. Возможно, вас заинтересуют некоторые из стратегий, изложенных в разделе "Секреты без серверов":
Вам нужны секреты?
Всегда важно спросить - нужны ли мне эти секреты? Могли бы вы использовать облачный провайдер IAM (или даже кросс-облачный OIDC) вместо введения секретов в мое приложение? По возможности старайтесь использовать решение IAM, предоставляемое различными облаками. Очевидно, есть еще немало случаев, когда требуется секрет.
Зашифрованные переменные среды
Перед запуском функции вы шифруете секреты открытого текста локально в зашифрованный текст (зашифрованные строки). Вот пример с gcloud, но вы также можете использовать API или другие инструменты, такие как HashiCorp Vault:
$ gcloud kms encrypt \
--ciphertext-file=- \
--plaintext-file=/path/to/my/secret \
--key=my-kms-key \
--key-ring=my-kms-keyring \
--location=us-east4 \
| base64
Это выведет зашифрованную строку, которую вы затем сохраните в своем config.js
:
CiQAePa3VBJLbunLSqIJT+RS4nYiKdIaW6U69Y...
При запуске настройте ваше приложение на:
- Base64 декодирует строку
- Расшифровать зашифрованный текст с помощью Cloud KMS
- Храните открытый текст в памяти до тех пор, пока необходим секрет
Я не уверен, какой язык (языки) вы используете, но вот пример nodejs. Вы можете найти намного больше примеров на GitHub на https://github.com/sethvargo/secrets-in-serverless:
const cryptoKeyID = process.env.KMS_CRYPTO_KEY_ID;
const kms = require('@google-cloud/kms');
const client = new kms.v1.KeyManagementServiceClient();
let username;
client.decrypt({
name: cryptoKeyID,
ciphertext: process.env.DB_USER,
}).then(res => {
username = res[0].plaintext.toString().trim();
}).catch(err => {
console.error(err);
});
let password;
client.decrypt({
name: cryptoKeyID,
ciphertext: process.env.DB_PASS,
}).then(res => {
password = res[0].plaintext.toString().trim();
}).catch(err => {
console.error(err);
});
exports.F = (req, res) => {
res.send(`${username}:${password}`)
}
Google Cloud Storage
Поскольку вы находитесь в GCP, другой вариант - использовать Google Cloud Storage (GCS) напрямую для хранения секретов. Это уберет вашу связь с безсерверной средой.
Сделать ведро:
$ gsutil mb gs://${GOOGLE_CLOUD_PROJECT}-serverless-secrets
Сделайте ведро приватным:
$ gsutil defacl set private gs://${GOOGLE_CLOUD_PROJECT}-serverless-secrets $ gsutil acl set -r private gs://${GOOGLE_CLOUD_PROJECT}-serverless-secrets
Запишите некоторые секреты в ведро. Даже при том, что они передаются в виде открытого текста, они зашифрованы в состоянии покоя, и доступ строго контролируется через IAM.
$ gsutil -h 'Content-Type: application/json' cp - gs://${GOOGLE_CLOUD_PROJECT}-serverless-secrets/app1 <<< '{"username":"my-user", "password":"s3cr3t"}'
Затем создайте служебную учетную запись, у которой есть разрешение на чтение из корзины, и назначьте эту служебную учетную запись своим функциям.
Наконец, прочитайте из корзины при запуске функции (на этот раз пример Python):
import os
import json
from google.cloud import storage
blob = storage.Client() \
.get_bucket(os.environ['STORAGE_BUCKET']) \
.get_blob('app1') \
.download_as_string()
parsed = json.loads(blob)
username = parsed['username']
password = parsed['password']
def F(request):
return f'{username}:{password}'