使用 Secret Manager 连接器安全地存储敏感数据

Secret Manager 是一个安全便捷的存储系统,用于存储 API 密钥、密码、证书和其他敏感数据。Secret Manager 提供了一个集中、单一的数据源,便于您管理、访问和审核 Google Cloud 中的 Secret。

您可以使用 Workflows 的 Secret Manager API 连接器在工作流中访问 Secret Manager。这样可以简化集成,因为连接器会处理请求的格式,并提供方法和参数,这样您就无需了解 Secret Manager API 的详细信息。该连接器还具有用于处理重试和长时间运行的操作的内置行为。如需详细了解如何使用 Workflows 连接器,请参阅了解连接器

向 Workflows 服务账号授予对 Secret Manager 的访问权限

Secret Manager 使用 Identity and Access Management (IAM) 进行访问权限控制。如需创建、管理、列出或访问密文,必须在项目级和各个资源级授予适当的 IAM 权限。如需了解详情,请参阅使用 IAM 进行访问权限控制

Workflows 使用服务账号向工作流授予对 Google Cloud 资源的访问权限。如需访问密文版本,您必须向服务账号授予对密文、项目、文件夹或组织的 Secret Manager Secret Accessor 角色 (roles/secretmanager.secretAccessor)。详细了解如何使用用户代管式服务账号部署工作流

启用 API

在将 Workflows 连接器用于 Secret Manager API 之前,请确保您已启用 Secret Manager 和 Workflows API。

控制台

启用 API

gcloud

  gcloud services enable secretmanager.googleapis.com workflows.googleapis.com

调用连接器调用

与调用 HTTP 端点类似,连接器调用需要 callargs 字段。如需了解详情,请参阅调用连接器调用

除了使用调用步骤之外,您还可以在表达式中调用辅助方法,如下所示:

${googleapis.secretmanager.v1.projects.secrets.versions.accessString(secret_id, version, project_id)}

例如,您可以使用辅助方法 accessString 以字符串形式检索 Secret 数据。这比使用 access API 更简单,因为系统会自动将 Secret 数据解码为字符串格式。

您还可以使用辅助方法 addVersionString 向现有 Secret 添加新的 Secret 值。这比使用 addVersion API 更简单,因为系统会自动将秘密数据编码为 addVersion 所需的 base-64 字符串。

使用 Secret Manager 连接器检索 Secret

以下工作流演示了如何使用 Secret Manager 连接器检索密文。

YAML

# This workflow demonstrates how to use the Secret Manager connector:
# Retrieve a secret using three different methods
# Expected output: the secret data (thrice)
- init:
    assign:
      - project_id: ${sys.get_env("GOOGLE_CLOUD_PROJECT_ID")}
      - secret_id: "test-secret"  # Make sure you have this secret and it has a version of 1.
      - version: "1"
# Add data to an existing secret without base-64 encoding
- add_version_string:
    call: googleapis.secretmanager.v1.projects.secrets.addVersionString
    args:
      secret_id: ${secret_id}
      project_id: ${project_id}
      data: "a new secret"
# Retrieve the secret in string format without base-64 decoding and assume
# that the secret data is a valid UTF-8 string; if not, raise an error
- access_string_secret:
    call: googleapis.secretmanager.v1.projects.secrets.versions.accessString
    args:
      secret_id: ${secret_id}
      version: ${version}  # if not set, "latest" is used
      project_id: ${project_id}
    result: str_secret
# Retrieve the secret in string format without base-64 decoding
- access_secret:
    call: googleapis.secretmanager.v1.projects.secrets.versions.access
    args:
      name: ${"projects/" + project_id + "/secrets/" + secret_id + "/versions/" + version}
    result: base64_encoded_secret
# Retrieve the secret using positional arguments in an expression
- expression:
    assign:
      - secret_str_from_exp: ${googleapis.secretmanager.v1.projects.secrets.versions.accessString(secret_id, version, project_id)}
- the_end:
    return:
      - ${str_secret}
      - ${text.decode(base64.decode(base64_encoded_secret.payload.data))}
      - ${secret_str_from_exp}

JSON

[
  {
    "init": {
      "assign": [
        {
          "project_id": "${sys.get_env(\"GOOGLE_CLOUD_PROJECT_ID\")}"
        },
        {
          "secret_id": "test-secret"
        },
        {
          "version": "1"
        }
      ]
    }
  },
  {
    "add_version_string": {
      "call": "googleapis.secretmanager.v1.projects.secrets.addVersionString",
      "args": {
        "secret_id": "${secret_id}",
        "project_id": "${project_id}",
        "data": "a new secret"
      }
    }
  },
  {
    "access_string_secret": {
      "call": "googleapis.secretmanager.v1.projects.secrets.versions.accessString",
      "args": {
        "secret_id": "${secret_id}",
        "version": "${version}",
        "project_id": "${project_id}"
      },
      "result": "str_secret"
    }
  },
  {
    "access_secret": {
      "call": "googleapis.secretmanager.v1.projects.secrets.versions.access",
      "args": {
        "name": "${\"projects/\" + project_id + \"/secrets/\" + secret_id + \"/versions/\" + version}"
      },
      "result": "base64_encoded_secret"
    }
  },
  {
    "expression": {
      "assign": [
        {
          "secret_str_from_exp": "${googleapis.secretmanager.v1.projects.secrets.versions.accessString(secret_id, version, project_id)}"
        }
      ]
    }
  },
  {
    "the_end": {
      "return": [
        "${str_secret}",
        "${text.decode(base64.decode(base64_encoded_secret.payload.data))}",
        "${secret_str_from_exp}"
      ]
    }
  }
]

后续步骤