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 a fin de acceder a Secret Manager dentro de un flujo de trabajo. Esto simplifica la integración para ti, 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 los reintentos y las operaciones de larga duración. Para obtener más información sobre cómo usar los conectores de Workflows, consulta Información sobre 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 de proyecto y a nivel de recurso individual. Consulta Control de acceso con IAM para obtener más información.

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

Habilita las APIs

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

Console

Habilita las APIs

gcloud

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

Invocar una llamada del conector

De manera similar a la invocación de un extremo HTTP, una llamada al conector requiere los campos call y args. Para obtener más información, consulta Invoca una llamada al conector.

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

${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 del Secret como una cadena. Esto es más sencillo que usar la API de access, ya que los datos del secreto se decodifican automáticamente en un formato de cadena.

También puedes usar el método auxiliar addVersionString para agregar un valor de secreto nuevo a uno existente. Esto es más simple que usar la API de addVersion, ya que los datos del secreto se codifican de forma automática en una string en base 64, que es obligatoria para addVersion.

Recupera un secreto 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?