GAE:如何使用秘密部署各种环境?

时间:2018-04-24 20:04:14

标签: google-app-engine ansible

我在App Engine上有一个暂存和生产项目,每个项目有6个服务。

目前,我们使用开发人员计算机进行部署 gcloud app deploy app.staging.yaml --project staging-project

gcloud app deploy app.production.yaml --project production-project

它可以工作,但它会导致环境变量问题,尤其是秘密问题。

我们的应用程序从环境变量中获取Api密钥,数据库凭据和其他内容 - 这使我们可以在Docker容器或App Engine中本地运行完全相同的应用程序,而无需知道它的部署位置。

如果我按照文档方式进行部署,我们的app.yaml文件将如下所示:

app.production.yaml

runtime: nodejs
env: flex

manual_scaling:
  instances: 1
env_variables:
  DATABASE_PASSWORD: "topsecret"
  MY_API_KEY: "ultrasecret"

我认为每个人都很容易理解为什么将它存储在Git存储库中是个坏主意。

目前,我们有一个每个开发人员必须在部署之前填写的影子文件

app.production.yaml.shadow

runtime: nodejs
env: flex

manual_scaling:
  instances: 1
env_variables:
  DATABASE_PASSWORD: "set me"
  MY_API_KEY: "set me"

但随着团队的发展,我们希望每个人都能够在登台时进行部署,为每个开发人员和每项服务设置正确的设置变得越来越困难。

我找到了3个解决方法,以及他们不使用的原因:

  • 使用Google KMS - 允许我们将加密的秘密直接放入项目中,但它要求我们在我们的应用中放置自定义代码来解密它们。它在本地,登台和生产之间创建了不同的环境管理。由于复杂性,它增加了错误的风险。
  • Store secrets in Google Datastore - 我尝试过,我创建了一个帮助程序,在proccess.ENV中搜索env变量,然后在缓存中搜索,最后在Datastore中搜索。但是像KMS一样,它会增加复杂性。
  • 将秘密存储在JSON file and put in on Google Cloud Storage 中:再次,它需要通过检查env变量的帮助程序加载env变量,然后加载文件等...

最终,我们正在探索使用由开发人员或持续集成触发的部署服务器的可行性,并在部署到App Engine时处理所有秘密注入。但是像 Ansible ,Salt,Puppet,Chef这样的工具只有Compute Engine的插件,不支持App Engine。

+-------------------------+    +-------------------+   +---------------------+
|                         |    |                   +--->                     |
| Developer workspace     |    |    Ansible        |   | App Engine STAGING  |
|                         +---->   (or other)      |   |                     |
+-------------------------+    |                   |   +---------------------+
                               |                   |
+-------------------------+    |                   |   +---------------------+
|                         +---->   Injects secrets |   |                     |
| Continous Integration        |                   |   | App Engine PROD.    |
|                         |    |                   +--->                     |
+-------------------------+    +-------------------+   +---------------------+

这引出了3个问题:

  • 您认为使用带App Engine的部署服务器是个好主意吗?
  • 如何确保生产和暂存机密保持同步,以便开发人员的部署始终正确?
  • 有没有办法在App Engine上使用经典环境变量来保密?

3 个答案:

答案 0 :(得分:4)

我强烈建议您考虑使用KMS和云存储的组合,因为Google概述了here

你是对的,设置它可能会有点痛苦,但一旦它到位,它就很容易使用。我们为每个环境设置单独的密钥环(devteststagingprod),然后为每个应用程序分隔密钥,并编写一个命令行实用程序,使其变得微不足道我们团队中的任何开发人员都要将秘密写入秘密商店(同时阻止他们阅读生产秘密)。

最终,秘密管理仍然是一个难题。随着团队的发展,管理多个应用程序/环境的秘密非常困难。但我真的很鼓励你只需付出前期投资KMS这样的费用,因为这样可以让你的生活更加轻松,并且真正降低你不小心摔倒脚的风险。

答案 1 :(得分:1)

正如您所说,使用App Engine无法使用这些解决方案(Ansible,Salt等)。如果您要使用它们,则必须转移到GCE。谷歌有一些official tutorials关于如何开始使用这两种技术。

如果您继续使用App Engine,您可以使用上述解决方案之一,KMS更适合此目的。

另一种可能的解决方案是迁移到自定义运行时。根据您的应用程序,您可以使用以下命令生成Dockerfile:

$ gcloud beta app gen-config --custom

您的Dockerfile将如下所示:

FROM gcr.io/google_appengine/nodejs
RUN /usr/local/bin/install_node '>=4.3.2'
COPY . /app/
RUN npm install --unsafe-perm || \
  ((if [ -f npm-debug.log ]; then \
      cat npm-debug.log; \
    fi) && false)
CMD npm start

然后,您可以修改它以包含存储在您的环境变量中的密钥,其中包含如何在您的文件中输入密钥的示例:

sed 's/topsecret/'"$KEY_1"'/g;s/ultrasecret/'"$KEY_2"'/g' app.production.yaml.shadow > app.production.yaml

请注意在KEY_1和KEY_2之前和之后使用单打和双打引号,因为您需要它们to enter environment variables using sed

答案 2 :(得分:0)

几次后,我可以就此问题说些什么:

  • 为每个环境创建一个app.yaml。您可以根据环境指定在部署时使用的app.yaml文件。
  • 在env_variables部分中放置您的非秘密环境参数(例如端点url)。
  • 对于您的秘密(api密钥,秘密令牌...),请使用专用工具,例如Hashicorp VaultAWS Secrets Manager。这样一来,您就可以在项目之间共享它们,并处理团队中哪些人可以访问它们。