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

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

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

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

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

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

启用 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 更简单,因为 Secret 数据会自动编码为 base-64 字符串,这是 addVersion 所必需的。

使用 Secret Manager 连接器检索 Secret

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

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}"
      ]
    }
  }
]

后续步骤