Как обрабатывать секреты в Google App Engine?
Моему приложению требуется набор секретов для запуска: учетные данные базы данных, учетные данные API и т. Д. Оно работает в стандартной Java 11 Google App Engine. Мне нужны эти секреты как переменные среды или как аргументы для моего приложения, чтобы моя структура могла их подобрать. и соответственно установите соединения. Моя конкретная среда - Spring Boot, но я считаю, что Django, Rails и многие другие используют те же методы.
Как лучше всего это сделать?
Один из ответов, который я получаю на этот вопрос, - использовать Google Cloud Key Management, что выглядит многообещающим, но я не могу понять, как превратить эти значения в переменные среды в App Engine. Является ли это возможным? Я прочитал " Настройка аутентификации для серверных и серверных производственных приложений", но я не вижу никаких указаний на то, как превратить секреты в переменные среды в App Engine (мне это не хватает?)
Другие альтернативы, которые я видел, включают их жесткое кодирование в app.yaml
или другой файл, который никогда не фиксируется и живет на моей машине, что означает, что я единственный, кто может развернуть... Я даже не могу развернуть с другой машины. Для меня это проблематично.
Еще одно потенциальное решение, которое я видел, - делегировать проблему Google Cloud Build, чтобы он извлекал значение / файл из CKM и отправлял его в App Engine ( 1, 2). Я не использую GCB и сомневаюсь, что буду использовать его, поскольку он настолько прост.
Я действительно хотел бы, чтобы в App Engine была страница переменных среды, как в Heroku.
6 ответов
[Обновление] (по состоянию на февраль 2020 г.) Секретный менеджер GCP находится на стадии бета-тестирования, см.:
https://cloud.google.com/secret-manager/docs/overview
Информацию о реализации для Java см. На https://cloud.google.com/secret-manager/docs/creating-and-accessing-secrets.
Ваше конкретное решение будет зависеть от того, как настроено ваше приложение, но вы должны иметь доступ к секретам и создавать переменные среды со значениями или иным образом передавать их в свое приложение.
Вы можете использовать GCP IAM для создания учетных записей служб для управления доступом или добавления роли, например Secret Manager Secret Accessor
существующему члену / службе (например, в этом случае я добавил это разрешение в App Engine default service account
).
Я попробовал это с Node.js по стандарту GAE, и, похоже, он работает хорошо; Я не проводил никаких тестов производительности, но все должно быть в порядке, особенно если вам в первую очередь нужны секреты при запуске приложения или как часть процесса сборки.
Для локальной (не-GCP) разработки / тестирования вы можете создать учетную запись службы с соответствующими разрешениями секретного менеджера и получить служебный ключ js on. Затем вы устанавливаете переменную среды с именемGOOGLE_APPLICATION_CREDENTIALS
на путь к файлу, например:
export GOOGLE_APPLICATION_CREDENTIALS=/path/to/local_service_key.json
и приложение, работающее в этом сеансе оболочки, должно получать разрешения без какого-либо дополнительного кода аутентификации. См. https://cloud.google.com/docs/authentication/getting-started(вы бы хотели исключить ключевой файл из контроля версий.)
Вы можете передавать секреты как переменные env во время сборки. В этом примере извлекается ключ Stripe API и обновляется app.yaml в Cloud Build, чтобы локальный файл не был случайно возвращен в систему управления версиями.
Сначала убедитесь, что учетная запись службы CloudBuild имеет роль IAM.
Secret Manager Secret Accessor
файл app.dev.yaml с заполнителем для переменной env
runtime: python39
env: standard
instance_class: F4
automatic_scaling:
max_instances: 1
env_variables:
STRIPE_API_KEY: STRIPE_API_VAR
etc
etc
Cloudbuild.yaml для извлечения секрета и вставки во время сборки.
steps:
- name: 'gcr.io/google.com/cloudsdktool/cloud-sdk'
entrypoint: 'bash'
args:
- -c
- |
echo 'my api key from secret manager is '$$STRIPE_API_VAR
sed -i "s|STRIPE_API_VAR|$$STRIPE_API_VAR|g" app.dev.yaml
cat app.dev.yaml # you can now see the secret value inserted as the env variable
gcloud app deploy --appyaml=app.dev.yaml # deploy with the updated app.yaml, the local copy of the file is not changed
secretEnv: ['STRIPE_API_VAR']
availableSecrets:
secretManager:
- versionName: projects/$PROJECT_ID/secrets/stripe-api-key/versions/latest
env: 'STRIPE_API_VAR'
На данный момент в App Engine Standard Standard нет решения Google для хранения секретов приложений.
[ОБНОВИТЬ]
Я заметил ваш комментарий к другому ответу о том, что вам нужно, чтобы переменные среды были действительными, прежде чем вы получите управление приложением. В таком случае сегодня у вас нет вариантов для App Engine. Я бы развернул его в другом сервисе (Kubernetes), лучше подходящем для ваших системных целей, который может предоставлять управляемые секреты.
[КОНЕЦ ОБНОВЛЕНИЯ]
У вас есть два варианта секретов для App Engine Standard:
- Храните секреты как переменные среды в app.yaml
- Храните секреты в другом месте.
Для обоих вариантов вы можете добавить уровень безопасности, зашифровав их. Однако добавление шифрования добавляет еще один секрет (ключ дешифрования), который вы должны каким-то образом предоставить своему приложению. Ситуация с курицей или яйцом.
В App Engine Standard используется учетная запись службы. Эту учетную запись службы можно использовать в качестве удостоверения для управления доступом к другим ресурсам. Примеры других ресурсов: KMS и Cloud Storage. Это означает, что вы можете безопасно получить доступ к KMS или облачному хранилищу, не добавляя еще один секрет в App Engine.
Предположим, ваша компания хочет, чтобы все секреты приложений были зашифрованы. Мы можем использовать учетную запись службы App Engine в качестве идентификатора, авторизованного для доступа к KMS для одного ключа.
Примечание. В следующих примерах используется синтаксис Windows. Заменить продолжение строки^
с \
для Linux/macOS.
Создайте связку ключей KMS. Связки ключей удалить нельзя, так что это разовая операция.
set GCP_KMS_KEYRING=app-keyring
set GCP_KMS_KEYNAME=app-keyname
gcloud kms keyrings create %GCP_KMS_KEYRING% --location global
Создайте ключ KMS.
gcloud kms keys create %GCP_KMS_KEYNAME% ^
--location global ^
--keyring %GCP_KMS_KEYRING% ^
--purpose encryption
Добавьте учетную запись службы в политику KMS для созданного нами набора ключей и ключа.
Это позволит App Engine расшифровывать данные, не требуя секретов для KMS. Удостоверение учетной записи службы обеспечивает контроль доступа. Для KMS роли не требуются. Вам нужно будет предоставить KMS Keyring и Keyname, которые можно включить в app.yaml.
set GCP_SA=<replace with the app engine service acccount email adddress>
set GCP_KMS_ROLE=roles/cloudkms.cryptoKeyDecrypter
gcloud kms keys add-iam-policy-binding %GCP_KMS_KEYNAME% ^
--location global ^
--keyring %GCP_KMS_KEYRING% ^
--member serviceAccount:%GCP_SA% ^
--role %GCP_KMS_ROLE%
В этом примере предположим, что вам нужен доступ к базе данных MySQL. Мы сохраним учетные данные в файле JSON и зашифруем его. Файл называетсяconfig.json
.
{
"DB_HOST": "127.0.0.1",
"DB_PORT": "3306",
"DB_USER": "Roberts",
"DB_PASS": "Keep-This-Secret"
}
Зашифруйте config.json с помощью Cloud KMS и сохраните зашифрованные результаты в config.enc:
call gcloud kms encrypt ^
--location=global ^
--keyring %GCP_KMS_KEYRING% ^
--key=%GCP_KMS_KEYNAME% ^
--plaintext-file=config.json ^
--ciphertext-file=config.enc
Зашифрованный файл можно сохранить в облачном хранилище. Поскольку он зашифрован, вы можете сохранить файл вместе со своими файлами сборки, но я не рекомендую это делать.
Последний этап - написать код на Java, который является частью вашей программы, которая использует KMS для расшифровки файла config.enc с помощью KMS. У Google есть несколько примеров расшифровки KMS:
Что касается секретного управления, я лично фанат проекта Berglas. Он основан на KMS и, кроме того, управляет DEK и KEK
Сегодня он пишется на Go и несовместим с Java. Я написал библиотеку Python для некоторых коллег. Я могу написать пакет Java, если вы планируете его использовать. Это не очень сложно.
Дайте мне знать
Берглас выглядит интересно.
Другой вариант - поместить секреты в файл (ы) app.yaml (у вас может быть несколько) и зашифровать его, прежде чем передавать в систему контроля версий.
Существует множество инструментов для шифрования секретов перед их передачей в систему контроля версий, например https://github.com/StackExchange/blackbox.
Плюсы:
- Очень универсальный
- Я считаю это простым для понимания по сравнению с другими вариантами
- Легко начать
Минусы:
- Вы не можете полностью удалить доступ для человека (поскольку файл всегда можно скопировать), поэтому иногда у вас есть ротация секретов
- Может быть сложно сохранить незашифрованные файлы из репозитория. Если вы привыкли к нему и игнорируете файлы и / или скрипты, это обычно нормально.
Варианты более или менее совпадают с тем, что вы упомянули. Google Cloud Key Management - отличный способ работы с учетными данными и секретной информацией в целом. У него есть REST API с методами, которые необходимо использовать для достижения ваших целей. Например, у вас есть метод get для получения криптоключей, связок ключей, криптоключей и т. Д.
Например, здесь есть руководство по настройке аутентификации для вашего приложения. Здесь также есть хороший пример кода на github.
Если вы считаете, что требуется дополнительная безопасность, вы также можете использовать технику секретной ротации.
Жесткое кодирование значений в app.yaml также является вариантом, хотя это не рекомендуется как лучшая практика. App.yaml не будет жить только на вашей машине. Он также будет развернут, и вы даже можете увидеть его из движка приложения, панель "Версии" -> "Конфигурация" в консоли GCP. Так что вам не о чем беспокоиться.