如何通过 Cloud Build 访问 GSM 机密并传递给 Cloud Function

Posted

技术标签:

【中文标题】如何通过 Cloud Build 访问 GSM 机密并传递给 Cloud Function【英文标题】:How to access GSM secrets through Cloud Build and pass to Cloud Function 【发布时间】:2020-05-26 04:58:31 【问题描述】:

在使用 Cloud Build 时,如何将密钥从 Google Secrets Manager (GSM) 传递到 Cloud Function?下面的 cloudbuild.yaml 包含三个步骤。此外,我使用volumes 在构建步骤之间创建永久存储。我可以通过 Cloud Build 确认 GSM 检索。但是,当我尝试使用 --env-vars-file 以 yaml 格式传递秘密时,遇到以下错误...

Already have image (with digest): gcr.io/cloud-builders/gcloud
ERROR: gcloud crashed (AttributeError): 'str' object has no attribute 'items'

cloudbuild.yaml:

steps:
  - name: 'gcr.io/cloud-builders/gcloud'
    volumes:
    - name: 'secrets'
      path: '/secrets'
    entrypoint: "bash"
    args:
      - "-c"
      - |
        echo -n 'gsm_secret:' > /secrets/my-secret-file.txt
  - name: 'gcr.io/cloud-builders/gcloud'
    volumes:
    - name: 'secrets'
      path: '/secrets'
    entrypoint: "bash"
    args:
      - "-c"
      - |
        gcloud components update
        gcloud beta secrets versions access --secret=MySecret latest >> /secrets/my-secret-file.txt
        cat /secrets/my-secret-file.txt
  - name: 'gcr.io/cloud-builders/gcloud'
    volumes:
      - name: 'secrets'
        path: '/secrets'
    args: [
      'functions', 'deploy', 'gsm-foobar',
      '--project=[...]',
      '--trigger-http',
      '--runtime=go111',
      '--region=us-central1',
      '--memory=256MB',
      '--timeout=540',
      '--entry-point=GSM',
      '--allow-unauthenticated',
      '--source=https://source.developers.google.com/[...]',
      '--service-account', '[...]@appspot.gserviceaccount.com',
      '--env-vars-file', '/secrets/my-secret-file.txt'
    ]

更新: 不需要使用卷,因为 /workspace 是 Cloud Build 步骤之间的永久存储。此外,gcloud components update 不再需要,因为截至今天,默认的 Cloud SDK 版本为 279.0.0

解决方案:

steps:
  - name: 'gcr.io/cloud-builders/gcloud'
    entrypoint: "bash"
    args:
      - "-c"
      - |
        echo "gsm_secret: $(gcloud beta secrets versions access --secret=MySecret latest)" > /workspace/my-secret-file.txt
        cat /workspace/my-secret-file.txt
  - name: 'gcr.io/cloud-builders/gcloud'
    args: [
      'functions', 'deploy', 'gsm-foobar',
      [...]
      '--entry-point=GSM',
      '--allow-unauthenticated',
      '--source=https://source.developers.google.com/[...]',
      '--service-account', '[...]@appspot.gserviceaccount.com',
      '--env-vars-file=/workspace/my-secret-file.txt'
    ]

【问题讨论】:

我了解到您将您的秘密以纯文本形式作为函数 env var?如果这样做,您的秘密就不再是秘密,您可以在 Cloud Functions 控制台中看到解密后的 env var。如果您想获得更高级别的安全性,请尽可能将您的秘密保密并仅在运行时在您的函数中解密它们。 另一种方法是在每次函数调用时访问 GSM 机密 (secretmanagerpb.AccessSecretVersionRequest)。或者利用 init() 以便冷启动调用将检索 GSM 机密并存储在全局范围变量中,从而在函数调用之间缓存它。 是的,这种替代方案更好,即使冷启动时间稍长。在内存中的秘密存储比在 env var 元数据中更安全。 这能回答你的问题吗? How to specify secretEnv to cloudbuild.yaml via gcloud cli args or environment variables 【参考方案1】:

在第二次阅读时,我意识到您的第二步将秘密值放入文件中。我认为您缺少换行符。

注意我没有亲自尝试过!

确保您的机密文件末尾有一个换行符。

见:https://cloud.google.com/functions/docs/env-var

更新:试过了 ;-)

我认为您的问题是最后的换行符。

在部署之前的步骤中使用以下内容,可以:

echo "gsm_secret: $(gcloud beta secrets versions access --secret=MySecret latest)" > /secrets/my-secret-file.txt

或者,更简单地说,也许:

steps:
  - name: "gcr.io/cloud-builders/gcloud"
    entrypoint: /bin/bash
    args:
      - "-c"
      - |
        gcloud functions deploy ... \
        --set-env-vars=NAME=$(gcloud beta secrets versions access --secret=name latest)

另外,请参阅secretEnv。这是一种更优雅的机制。Google 或许应该增强此功能以支持秘密管理器(除了 KMS)。

【讨论】:

+1 Google 可能会增强此功能以支持密钥管理器(除了 KMS)【参考方案2】:

从 2021 年 2 月 10 日起,您可以使用 availableSecrets 字段直接从 Cloud Build 访问 Secret Manager 机密:

steps:
- id: 'deploy'
  name: 'gcr.io/cloud-builders/gcloud'
  entrypoint: 'bash'
  args:
  - '-c'
  - 'gcloud functions deploy --set-env-vars=SECRET=$$MY_SECRET'
  secretEnv: ['MY_SECRET']
availableSecrets:
  secretManager:
  - versionName: 'projects/my-project/secrets/my-secret/versions/latest'
    env: 'MY_SECRET'

Documentation

【讨论】:

如果您现在也可以通过deploy 命令访问--set-secret,这似乎有点多余。

以上是关于如何通过 Cloud Build 访问 GSM 机密并传递给 Cloud Function的主要内容,如果未能解决你的问题,请参考以下文章

从 Google Cloud Build 访问存储在 Google Secret Manager 中的环境变量

如何通过 Google Cloud Build 中的步骤设置环境或替换变量?

如何禁用对 Google Cloud Build 的 Github 检查

如何使用 googleapis Artifacts API 以编程方式查找和删除通过 Google Cloud Build 构建的容器映像?

Azure VM Cloud - 如何从本地访问 Sitecore 实例

Android的系统属性:build.propSystemProperties