使用来自 Secret Manager 的 Secret

本页面介绍如何在 Cloud Build 中添加密码和 API 密钥等敏感信息。

Secret Manager 是 Google Cloud 服务,可安全存储 API 密钥、密码和其他敏感数据。 如需在构建中包含敏感信息,您可以将信息存储在 Secret Manager 中,然后将构建配置为从 Secret Manager 中访问信息。

准备工作

  • 启用 Cloud Build and Secret Manager API。

    启用 API

  • 如需使用本指南中的命令行示例,请安装并配置 Google Cloud CLI

  • 确保您已将 Secret 存储在 Secret Manager 中。如需了解相关说明,请参阅创建 Secret

    • 记下 Secret 的 Secret 名称和 Secret 版本。您需要使用此信息将 Cloud Build 配置为访问 Secret。

必需的 IAM 权限

向 Cloud Build 服务帐号授予 Secret 的 Secret Manager Secret Accessor (roles/secretmanager.secretAccessor) IAM 角色:

  1. 在 Google Cloud 控制台中打开 Secret Manager 页面:

    转到 Secret Manager 页面

  2. 选中您要在构建中使用的 Secret 对应的复选框。

  3. 如果面板尚未打开,请点击显示信息面板将其打开。

  4. 在面板中的权限下,点击添加主账号

  5. 新建主账号文本框中,输入 PROJECT_NUMBER@cloudbuild.gserviceaccount.com 形式的 Cloud Build 服务账号的电子邮件地址。PROJECT_NUMBER在其中运行构建的项目的编号。您可以在项目设置页面中找到项目编号。

  6. 选择角色下拉框中,选择 Secret Manager Secret Accessor

  7. 点击保存

配置构建以从 Secret Manager 访问 UTF-8 Secret

  1. 在项目根目录中,创建一个名为 cloudbuild.yamlcloudbuild.json Cloud Build 配置文件。

  2. 在构建配置文件中:

    • 在所有构建 steps 之后,添加 availableSecrets 字段以指定用于密文的密文版本和环境变量。您可以在 secretVersion 字段的值中添加替代变量。您可以在构建中指定多个 Secret。
    • 在您要指定 Secret 的构建步骤中:
      • 添加指向 bashentrypoint 字段,以在构建步骤中使用 bash 工具。这在引用 Secret 的环境变量时必须使用。
      • 添加 secretEnv 字段以指定环境变量。
      • args 字段中,添加 -c 标志作为第一个参数。您在 -c 之后传递的任何字符串均被视为命令。如需详细了解如何使用 -c 运行 bash 命令,请参阅 bash 文档
      • args 字段中指定 Secret 时,请使用前缀为 $$ 的环境变量指定该 Secret。

    以下示例构建配置文件展示了如何使用存储在 Secret Manager 中的 Docker 用户名和密码登录 Docker。

    YAML

    steps:
    - name: 'gcr.io/cloud-builders/docker'
      entrypoint: 'bash'
      args: ['-c', 'docker login --username=$$USERNAME --password=$$PASSWORD']
      secretEnv: ['USERNAME', 'PASSWORD']
    availableSecrets:
      secretManager:
      - versionName: projects/PROJECT_ID/secrets/DOCKER_PASSWORD_SECRET_NAME/versions/DOCKER_PASSWORD_SECRET_VERSION
        env: 'PASSWORD'
      - versionName: projects/PROJECT_ID/secrets/DOCKER_USERNAME_SECRET_NAME/versions/DOCKER_USERNAME_SECRET_VERSION
        env: 'USERNAME'
    

    JSON

    {
      "steps": [
      {
        "name": "gcr.io/cloud-builders/docker",
        "entrypoint": "bash",
        "args": [
          "-c",
          "docker login --username=$$USERNAME --password=$$PASSWORD"
        ],
        "secretEnv": [
          "USERNAME",
          "PASSWORD"
        ]
      }
      ],
      "availableSecrets": {
        "secretManager": [{
          "versionName": "projects/PROJECT_ID/secrets/DOCKER_PASSWORD_SECRET_NAME/versions/DOCKER_PASSWORD_SECRET_VERSION",
          "env": "PASSWORD"
      }, {
        "versionName": "projects/PROJECT_ID/secrets/DOCKER_USERNAME_SECRET_NAME/versions/DOCKER_USERNAME_SECRET_VERSION",
        "env": "USERNAME"
         }]
      }
    }
    

    将上述命令中的占位值替换为以下内容:

    • PROJECT_ID:您存储密钥的 Google Cloud 项目的 ID。
    • DOCKER_USERNAME_SECRET_NAME:与您的 Docker 用户名对应的 Secret 名称。您可以从 Google Cloud 控制台的 Secret Manager 页面获取 Secret 名称。
    • DOCKER_USERNAME_SECRET_VERSION:您的 Docker 用户名的 Secret 版本。您可以在 Google Cloud 控制台的 Secret Manager 页面上点击 Secret 名称来获取 Secret 版本。
    • DOCKER_PASSWORD_SECRET_NAME:与您的 Docker 密码对应的 Secret 名称。您可以从 Google Cloud 控制台的 Secret Manager 页面获取 Secret 名称。
    • DOCKER_PASSWORD_SECRET_VERSION:您的 Docker 密码的 Secret 版本。您可以在 Google Cloud 控制台的 Secret Manager 页面上点击 Secret 名称来获取 Secret 版本。
  3. 使用构建配置文件通过命令行启动构建通过触发器自动执行构建

示例:从脚本和进程访问 Secret

secretEnv 字段会将 Secret 的值添加到环境中,并且您可以通过脚本或进程中的环境变量访问此值:

YAML

steps:
- name: python:slim
  entrypoint: python
  args: ['main.py']
  secretEnv: ['MYSECRET']
availableSecrets:
  secretManager:
  - versionName: projects/$PROJECT_ID/secrets/mySecret/versions/latest
    env: 'MYSECRET'

JSON

{
  "steps": [
  {
    "name": "python:slim",
    "entrypoint": "python",
    "args": [
        "main.py"
    ],
    "secretEnv": [
        "MYSECRET"
    ]
}
],
"availableSecrets": {
  "secretManager": [
    {
        "versionName": "projects/$PROJECT_ID/secrets/mySecret/versions/latest",
        "env": "MYSECRET"
    }
  ]
}
}

main.py 的以下内容会输出 Secret 的前五个字符:

import os
print(os.environ.get("MYSECRET", "Not Found")[:5], "...")

示例:向 Docker 进行身份验证

在某些情况下,在与 Docker 映像交互之前,您的构建需要向 Docker 进行身份验证。例如,构建需要 Docker 身份验证才能拉取私有映像并将私有或公共映像推送到 Docker Hub。在这些情况下,您可以将 Docker 用户名和密码存储在 Secret Manager 中,然后将 Cloud Build 配置为从 Secret Manager 访问用户名和密码。如需了解如何执行此操作,请参阅与 Docker Hub 映像交互

示例:创建 GitHub 拉取请求

另一个您可能需要将构建配置为从 Secret Manager 访问敏感信息的示例是为响应构建创建 GitHub 拉取请求。为此,请按以下说明操作:

  • 创建 GitHub 令牌
  • 将 GitHub 令牌存储在 Secret Manager 中。
  • 在您的构建配置文件中:
    • 在完成所有构建 steps 后,添加 availableSecrets 字段以指定要用于 GitHub 令牌的 Secret 版本和环境变量。
    • 添加构建步骤以调用创建 GitHub 拉取请求的命令
  • 创建 GitHub 应用触发器,并使用构建配置文件来调用此触发器。

以下示例配置文件展示了如何使用 GitHub 令牌创建 GitHub 拉取请求:

YAML

steps:
- name: 'launcher.gcr.io/google/ubuntu1604'
  id: Create GitHub pull request
  entrypoint: bash
  args:
  - -c
  - curl -X POST -H "Authorization:Bearer $$GH_TOKEN" -H 'Accept:application/vnd.github.v3+json' https://api.github.com/repos/GITHUB_USERNAME/REPO_NAME/pulls -d '{"head":"HEAD_BRANCH","base":"BASE_BRANCH", "title":"NEW_PR"}'
  secretEnv: ['GH_TOKEN']
availableSecrets:
  secretManager:
  - versionName: projects/PROJECT_ID/secrets/GH_TOKEN_SECRET_NAME/versions/latest
    env: GH_TOKEN

JSON

{
  "steps": [
  {
    "name": "launcher.gcr.io/google/ubuntu1604",
    "id": "Create GitHub pull request",
    "entrypoint": "bash",
    "args": [
      "-c",
       "curl -X POST -H \"Authorization:Bearer $$GH_TOKEN\" -H 'Accept:application/vnd.github.v3+json' https://api.github.com/repos/GITHUB_USERNAME/REPO_NAME -d '{\"head\":\"HEAD_BRANCH\",\"base\":\"BASE_BRANCH\", \"title\":\"NEW_PR\"}'
    ],
    "secretEnv": ['GH_TOKEN']
}
],
"availableSecrets": {
  "secretManager": [
  {
    "versionName": "projects/PROJECT_ID/secrets/GH_TOKEN_SECRET_NAME/versions/latest",
    "env": "GH_TOKEN"
  }
  ]
}
}

将上述命令中的占位值替换为以下内容:

  • PROJECT_ID:您存储密钥的 Google Cloud 项目的 ID。
  • GITHUB_USERNAME:代码库所有者的 GitHub 用户名。
  • REPO_NAME:GitHub 代码库的名称。
  • HEAD_BRANCH:在其中实现更改的分支的名称。对于同一网络中的跨代码库拉取请求,具有用户的命名空间 head 如下所示:username:branch
  • BASE_BRANCH:您希望将更改拉取到其中的分支的名称。此分支应该是当前代码库中的现有分支。您无法将拉取请求提交到一个请求与另一个代码库合并的代码库。
  • GH_TOKEN_SECRET_NAME:与您的 GitHub 令牌对应的 Secret 名称。
  • NEW_PR:您要创建的新拉取请求。

配置构建以从 Secret Manager 访问非 UTF-8 Secret

  1. 在构建配置文件中,添加构建步骤以访问 Secret Manager 中的密钥版本并将其存储在文件中。执行以下构建步骤可访问 secret-name 并将其存储在名为 decrypted-data.txt 的文件中:

    YAML

    steps:
    - name: gcr.io/cloud-builders/gcloud
      entrypoint: 'bash'
      args: [ '-c', "gcloud secrets versions access latest --secret=secret-name --format='get(payload.data)' | tr '_-' '/+' | base64 -d > decrypted-data.txt" ]
    

    JSON

    {
      "steps": [
      {
        "name": "gcr.io/cloud-builders/gcloud",
        "entrypoint": "bash",
        "args": [
          "-c",
          "gcloud secrets versions access latest --secret=secret-name --format='get(payload.data)' | tr '_-' '/+' | base64 -d > decrypted-data.txt"
        ]
      }
      ]
    }
    
  2. 在构建步骤中使用包含解密后数据的文件。以下代码段使用 decrypted-data.txt 登录到私有 Docker 注册表:

    YAML

    steps:
    - name: gcr.io/cloud-builders/gcloud
      entrypoint: 'bash'
      args: [ '-c', "gcloud secrets versions access latest --secret=secret-name --format='get(payload.data)' | tr '_-' '/+' | base64 -d > decrypted-data.txt" ]
    - name: gcr.io/cloud-builders/docker
      entrypoint: 'bash'
      args: [ '-c', 'docker login --username=my-user --password-stdin < decrypted-data.txt']
    

    JSON

    {
      "steps": [
      {
        "name": "gcr.io/cloud-builders/gcloud",
        "entrypoint": "bash",
        "args": [
          "-c",
          "gcloud secrets versions access latest --secret=secret-name --format='get(payload.data)' | tr '_-' '/+' | base64 -d > password.txt"
         ]
      },
      {
        "name": "gcr.io/cloud-builders/docker",
        "entrypoint": "bash",
        "args": [
          "-c",
          "docker login --username=my-user --password-stdin < decrypted-data.txt"
         ]
      }
      ]
    }
    
  3. 使用构建配置文件通过命令行启动构建通过触发器自动执行构建

后续步骤