pup*_*eno 20 google-app-engine google-cloud-platform google-cloud-kms google-secret-manager
我的应用程序需要一堆机密才能运行:数据库凭据、API 凭据等。它在 Google App Engine Standard Java 11 中运行。我需要这些机密作为环境变量或作为我应用程序的参数,以便我的框架可以获取它们并相应地建立连接。我的特定框架是 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 那样的环境变量页面。
ldg*_*ldg 14
[更新](截至 2020 年 2 月)GCP 的 Secret Manager处于测试阶段,请参阅:
https://cloud.google.com/secret-manager/docs/overview
对于特定于 Java 的实现,请参阅:https : //cloud.google.com/secret-manager/docs/creating-and-accessing-secrets#secretmanager-access-secret-version-java
您的具体解决方案将取决于您的应用程序的设置方式,但您应该能够访问机密并使用值创建环境变量,或者以其他方式将它们传递给您的应用程序。
您可以使用 GCP IAM 创建服务帐户来管理访问权限或Secret Manager Secret Accessor向现有成员/服务添加类似角色(例如,在本例中,我将该权限添加到App Engine default service account)。
我在 GAE 标准上使用 Node.js 进行了尝试,它似乎运行良好;我没有做任何性能测试,但应该没问题,特别是如果您主要需要应用程序启动时或作为构建过程的一部分的秘密。
对于本地(非 GCP)开发/测试,您可以创建一个具有适当 secret manager 权限的服务帐户并获取 json 服务密钥。然后设置一个命名GOOGLE_APPLICATION_CREDENTIALS为文件路径的环境变量,例如:
export GOOGLE_APPLICATION_CREDENTIALS=/path/to/local_service_key.json
Run Code Online (Sandbox Code Playgroud)
并且在该 shell 会话中运行的应用程序应该无需任何其他身份验证代码即可获取权限。请参阅:https : //cloud.google.com/docs/authentication/getting-started (您可能希望从版本控制中排除密钥文件。)
您可以在构建时将机密作为环境变量传递。此示例检索 Stripe API 密钥并在 Cloud Build 中更新 app.yaml,确保本地文件不会意外签入源代码管理
首先确保 CloudBuild 服务帐户具有 IAM 角色Secret Manager Secret Accessor
runtime: python39
env: standard
instance_class: F4
automatic_scaling:
max_instances: 1
env_variables:
STRIPE_API_KEY: STRIPE_API_VAR
etc
etc
Run Code Online (Sandbox Code Playgroud)
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'
Run Code Online (Sandbox Code Playgroud)
目前,App Engine Standard 标准尚未提供 Google 提供的用于存储应用程序机密的解决方案。
\n\n[更新]
\n\n我注意到您对另一个答案的评论,即您需要环境变量在拥有应用程序控制权之前有效。在这种情况下,您现在无法选择 App Engine。我会部署到更适合您的系统目标的不同服务(Kubernetes),该服务可以提供托管机密。
\n\n[结束更新]
\n\n对于 App Engine Standard,您有两种密钥选择:
\n\n对于这两个选项,您可以通过加密来添加一层安全性。但是,添加加密会添加另一个秘密(解密密钥),您必须以某种方式向应用程序提供该秘密。先有鸡还是先有蛋的情况。
\n\nApp Engine Standard 使用服务帐户。该服务帐户可用作控制对其他资源的访问的身份。其他资源的示例包括 KMS 和云存储。这意味着您可以安全地访问 KMS 或 Cloud Storage,而无需向 App Engine 添加其他密钥。
\n\n假设您的公司希望对所有应用程序机密进行加密。我们可以使用 App Engine 服务帐户作为授权访问 KMS 的单个密钥的身份。
\n\n注意:以下示例使用 Windows 语法。对于 Linux/macOS,将续行替换^为。\\
创建 KMS 密钥环。密钥环无法删除,因此这是一次性操作。
\n\nset GCP_KMS_KEYRING=app-keyring\nset GCP_KMS_KEYNAME=app-keyname\n\ngcloud kms keyrings create\xc2\xa0%GCP_KMS_KEYRING% --location global\nRun Code Online (Sandbox Code Playgroud)\n\n创建 KMS 密钥。
\n\ngcloud kms keys create\xc2\xa0%GCP_KMS_KEYNAME% ^\n--location global ^\n--keyring\xc2\xa0%GCP_KMS_KEYRING% ^\n--purpose encryption\nRun Code Online (Sandbox Code Playgroud)\n\n将服务帐户添加到我们创建的密钥环和密钥的 KMS 策略中。
\n\n这将允许 App Engine 解密数据,而无需 KMS 密钥。服务帐户身份提供访问控制。KMS 不需要任何角色。您需要提供可包含在 app.yaml 中的 KMS 密钥环和密钥名。
\n\nset GCP_SA=<replace with the app engine service acccount email adddress>\nset GCP_KMS_ROLE=roles/cloudkms.cryptoKeyDecrypter\n\ngcloud kms keys add-iam-policy-binding\xc2\xa0%GCP_KMS_KEYNAME% ^\n--location global ^\n--keyring\xc2\xa0%GCP_KMS_KEYRING% ^\n--member serviceAccount:%GCP_SA% ^\n--role\xc2\xa0%GCP_KMS_ROLE%\nRun Code Online (Sandbox Code Playgroud)\n\n对于此示例,我们假设您需要访问 MySQL 数据库。我们将凭证存储在 JSON 文件中并对其进行加密。该文件名为config.json.
{\n "DB_HOST": "127.0.0.1",\n "DB_PORT": "3306",\n "DB_USER": "Roberts",\n "DB_PASS": "Keep-This-Secret"\n}\nRun Code Online (Sandbox Code Playgroud)\n\n使用 Cloud KMS 加密 config.json 并将加密结果存储在 config.enc 中:
\n\ncall gcloud kms encrypt ^\n--location=global ^\n--keyring\xc2\xa0%GCP_KMS_KEYRING% ^\n--key=%GCP_KMS_KEYNAME% ^\n--plaintext-file=config.json ^\n--ciphertext-file=config.enc\nRun Code Online (Sandbox Code Playgroud)\n\n加密后的文件可以存储在云存储中。由于它是加密的,您可以将该文件与构建文件一起存储,但我不建议这样做。
\n\n最后一部分是用 Java 编写代码,该代码是使用 KMS 的程序的一部分,以便使用 KMS 解密文件 config.enc。谷歌有很多KMS解密的例子:
\n\n\n\n\n| 归档时间: |
|
| 查看次数: |
9262 次 |
| 最近记录: |