Protege y almacena datos sensibles con el conector de Secret Manager

Secret Manager es un sistema de almacenamiento seguro y conveniente para guardar claves de API, contraseñas, certificados y otros datos sensibles. Secret Manager proporciona una ubicación central y una fuente de información única para administrar, acceder y auditar secretos en Google Cloud.

Puedes usar el conector de Workflows para la API de Secret Manager para acceder a Secret Manager dentro de un flujo de trabajo. Esto simplifica la integración, ya que el conector controla el formato de las solicitudes y proporciona métodos y argumentos para que no necesites conocer los detalles de la API de Secret Manager. El conector también tiene un comportamiento integrado para controlar reintentos y operaciones de larga duración. Para obtener más información sobre el uso de conectores de Workflows, consulta Descripción de los conectores.

Otorga a la cuenta de servicio de Workflows acceso a Secret Manager

Secret Manager usa Identity and Access Management (IAM) para el control de acceso. Para crear, administrar, enumerar o acceder a un secreto, se deben otorgar los permisos de IAM adecuados a nivel del proyecto y del recurso individual. Para obtener más información, consulta Control de acceso con IAM.

Workflows usa cuentas de servicio para otorgarles acceso a los recursos de Google Cloud. Para acceder a una versión del secreto, debes otorgarle a la cuenta de servicio el rol de descriptor de acceso a secretos (roles/secretmanager.secretAccessor) en el secreto, el proyecto, la carpeta o la organización. Obtén más información para implementar un flujo de trabajo con una cuenta de servicio administrada por el usuario.

Habilitación de las API

Antes de usar el conector de Workflows para la API de Secret Manager, asegúrate de habilitar las APIs de Secret Manager y Workflows.

Console

Habilitar las API

gcloud

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

Cómo invocar una llamada de conector

Al igual que cuando se invoca un extremo HTTP, una llamada al conector requiere campos call y args. Para obtener más información, consulta Cómo invocar una llamada de conector.

Además de usar un paso de llamada, puedes llamar a los métodos auxiliares en una expresión como esta:

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

Por ejemplo, puedes usar el método auxiliar accessString para recuperar los datos secretos como una cadena. Esto es más sencillo que usar la API de access, ya que los datos secretos se decodifican automáticamente a un formato de cadena.

También puedes usar el método auxiliar addVersionString para agregar un valor secreto nuevo a un secreto existente. Esto es más sencillo que usar la API de addVersion, ya que los datos secretos se codifican automáticamente en una cadena de base 64, que es lo que requiere addVersion.

Cómo recuperar un Secret con el conector de Secret Manager

En el siguiente flujo de trabajo, se muestra cómo usar el conector de Secret Manager para recuperar un secreto.

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

¿Qué sigue?