Usar etiquetas de entidad para el control de simultaneidad optimista

Secret Manager admite el uso de etiquetas de entidad (ETags) para el control de simultaneidad optimista.

En algunos casos, dos procesos que actualizan el mismo recurso en paralelo pueden interferir entre sí, de forma que el último proceso sobrescribe el trabajo del primero.

Los ETags proporcionan un medio para controlar la simultaneidad optimista, ya que permiten que los procesos comprueben si un recurso se ha modificado antes de tomar medidas en él.

Usar ETags con Secret Manager

Las siguientes solicitudes de modificación de recursos admiten ETags:

En una solicitud secrets.patch, el ETag de la solicitud se inserta en los datos de Secret. El resto de las solicitudes aceptan un parámetro etag opcional.

Si se proporciona un ETag y coincide con el ETag del recurso actual, la solicitud se realiza correctamente. De lo contrario, se produce un error FAILED_PRECONDITION y se devuelve el código de estado HTTP 400. Si no se proporciona un ETag, la solicitud continúa sin comprobar el valor de ETag almacenado.

Los ETags de recursos se generan al crear el recurso (projects.secrets.create y projects.secrets.addVersion) y se actualizan con cada una de las solicitudes de modificación indicadas anteriormente. Una solicitud de modificación solo actualiza el ETag del recurso al que se aplica. Es decir, al actualizar una versión de un secreto, no se modifica la etiqueta ETag del secreto y, del mismo modo, al actualizar la etiqueta ETag, no se modifica la versión del secreto.

Aunque una actualización no cambie el estado de un recurso, se actualiza su ETag.

Veamos un ejemplo:

  • El usuario 1 intenta habilitar una versión de un secreto sin saber que ya está habilitada. El sistema procesa esto sin cambiar nada, excepto el ETag de la versión.

  • El usuario 2, que usa el ETag antiguo, intenta inhabilitar la versión.

  • Se produce un error porque el sistema reconoce el ETag más reciente, que indica una intención más reciente de mantener la versión habilitada.

Incluso las actualizaciones aparentemente menores son importantes debido a los cambios en las etiquetas ETag. De esta forma, se garantiza la coherencia de los datos, sobre todo cuando varios usuarios o sistemas interactúan con el mismo recurso.

El recurso etag se devuelve en la respuesta siempre que se incluya un recurso (Secret o SecretVersion).

Eliminar un secreto con ETags

En esta sección se describe cómo usar ETags al eliminar un secreto. Si otro proceso ha modificado el secreto, la operación de eliminación fallará.

gcloud

Antes de usar los datos de los comandos que se indican a continuación, haz los siguientes cambios:

  • SECRET_ID: el ID del secreto.
  • ETAG: la etiqueta de entidad del secreto. El ETag debe incluir las comillas. Por ejemplo, si el valor de ETag era "abc", el valor con escape de shell sería "\"abc\"".

Ejecuta el siguiente comando:

Linux, macOS o Cloud Shell

gcloud secrets delete SECRET_ID \
    --etag "ETAG"

Windows (PowerShell)

gcloud secrets delete SECRET_ID `
    --etag "ETAG"

Windows (cmd.exe)

gcloud secrets delete SECRET_ID ^
    --etag "ETAG"

REST

Antes de usar los datos de la solicitud, haz las siguientes sustituciones:

  • PROJECT_ID: el ID del proyecto. Google Cloud
  • SECRET_ID: el ID del secreto.
  • ETAG: la etiqueta de entidad del secreto. El ETag se especifica como parte de la cadena de consulta de la URL y debe codificarse como URL. Por ejemplo, si el valor de ETag es "abc", el valor codificado como URL sería %22abc%22 porque el carácter de comillas se codifica como %22.

Método HTTP y URL:

DELETE https://secretmanager.googleapis.com/v1/projects/PROJECT_ID/secrets/SECRET_ID?etag=ETAG

Cuerpo JSON de la solicitud:

{}

Para enviar tu solicitud, elige una de estas opciones:

curl

Guarda el cuerpo de la solicitud en un archivo llamado request.json y ejecuta el siguiente comando:

curl -X DELETE \
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
-H "Content-Type: application/json; charset=utf-8" \
-d @request.json \
"https://secretmanager.googleapis.com/v1/projects/PROJECT_ID/secrets/SECRET_ID?etag=ETAG"

PowerShell

Guarda el cuerpo de la solicitud en un archivo llamado request.json y ejecuta el siguiente comando:

$cred = gcloud auth print-access-token
$headers = @{ "Authorization" = "Bearer $cred" }

Invoke-WebRequest `
-Method DELETE `
-Headers $headers `
-ContentType: "application/json; charset=utf-8" `
-InFile request.json `
-Uri "https://secretmanager.googleapis.com/v1/projects/PROJECT_ID/secrets/SECRET_ID?etag=ETAG" | Select-Object -Expand Content

Deberías recibir una respuesta JSON similar a la siguiente:

{}

Actualizar un secreto con ETags

En esta sección se describe cómo usar ETags al actualizar un secreto. Si otro proceso ha modificado el secreto, la operación de actualización no se llevará a cabo.

gcloud

Antes de usar los datos de los comandos que se indican a continuación, haz los siguientes cambios:

  • SECRET_ID: el ID del secreto.
  • KEY: nombre de la etiqueta.
  • VALUE: el valor de etiqueta correspondiente.
  • ETAG: la etiqueta de entidad del secreto. El ETag debe incluir las comillas. Por ejemplo, si el valor de ETag era "abc", el valor con escape de shell sería "\"abc\"".

Ejecuta el siguiente comando:

Linux, macOS o Cloud Shell

gcloud secrets update SECRET_ID \
    --update-labels "KEY=VALUE" \
    --etag "ETAG"

Windows (PowerShell)

gcloud secrets update SECRET_ID `
    --update-labels "KEY=VALUE" `
    --etag "ETAG"

Windows (cmd.exe)

gcloud secrets update SECRET_ID ^
    --update-labels "KEY=VALUE" ^
    --etag "ETAG"

La respuesta devuelve el secreto.

REST

Antes de usar los datos de la solicitud, haz las siguientes sustituciones:

  • PROJECT_ID: el ID del proyecto. Google Cloud
  • SECRET_ID: el ID del secreto.
  • ETAG: la etiqueta de entidad del secreto. El ETag se especifica como un campo en el secreto y debe incluir las comillas correspondientes. Por ejemplo, si el valor de ETag era "abc", el valor con caracteres de escape JSON sería {"etag":"\"abc\""}.
  • KEY: nombre de la etiqueta.
  • VALUE: el valor de etiqueta correspondiente.

Método HTTP y URL:

PATCH https://secretmanager.googleapis.com/v1/projects/PROJECT_ID/secrets/SECRET_ID?updateMask=labels

Cuerpo JSON de la solicitud:

{"etag":"ETAG", "labels":{"KEY": "VALUE"}}

Para enviar tu solicitud, elige una de estas opciones:

curl

Guarda el cuerpo de la solicitud en un archivo llamado request.json y ejecuta el siguiente comando:

curl -X PATCH \
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
-H "Content-Type: application/json; charset=utf-8" \
-d @request.json \
"https://secretmanager.googleapis.com/v1/projects/PROJECT_ID/secrets/SECRET_ID?updateMask=labels"

PowerShell

Guarda el cuerpo de la solicitud en un archivo llamado request.json y ejecuta el siguiente comando:

$cred = gcloud auth print-access-token
$headers = @{ "Authorization" = "Bearer $cred" }

Invoke-WebRequest `
-Method PATCH `
-Headers $headers `
-ContentType: "application/json; charset=utf-8" `
-InFile request.json `
-Uri "https://secretmanager.googleapis.com/v1/projects/PROJECT_ID/secrets/SECRET_ID?updateMask=labels" | Select-Object -Expand Content

Deberías recibir una respuesta JSON similar a la siguiente:

{
  "name": "projects/PROJECT_ID/locations/LOCATION/secrets/SECRET_ID",
  "createTime": "2024-09-04T04:06:00.660420Z",
  "labels": {
    "KEY": "VALUE"
  },
  "etag": "\"162145a4f894d5\""
}

Actualizar una versión de un secreto con etiquetas ETag

En esta sección se describe cómo usar ETags al actualizar una versión de un secreto. Si otro proceso ha modificado la versión del secreto, no se podrá realizar la operación de actualización.

En este ejemplo de código se describe cómo inhabilitar una versión secreta con ETags. También puede especificar ETags durante otras operaciones de mutación de secretos, como cuando habilita versiones inhabilitadas o destruye versiones de secretos. Consulta los códigos de ejemplo de Secret Manager.

gcloud

Antes de usar los datos de los comandos que se indican a continuación, haz los siguientes cambios:

  • VERSION_ID: el ID de la versión del secreto.
  • SECRET_ID: el ID del secreto.
  • ETAG: la etiqueta de entidad. El ETag debe incluir las comillas. Por ejemplo, si el valor de ETag era "abc", el valor con escape de shell sería "\"abc\"".

Ejecuta el siguiente comando:

Linux, macOS o Cloud Shell

gcloud secrets versions disable VERSION_ID \
  --secret SECRET_ID \
  --etag "ETAG"

Windows (PowerShell)

gcloud secrets versions disable VERSION_ID `
  --secret SECRET_ID `
  --etag "ETAG"

Windows (cmd.exe)

gcloud secrets versions disable VERSION_ID ^
  --secret SECRET_ID ^
  --etag "ETAG"

La respuesta devuelve el secreto.

REST

Antes de usar los datos de la solicitud, haz las siguientes sustituciones:

  • PROJECT_ID: el ID del proyecto. Google Cloud
  • SECRET_ID: el ID del secreto.
  • VERSION_ID: el ID de la versión del secreto.
  • ETAG: la etiqueta de entidad de la versión del secreto. El ETag se especifica como un campo en SecretVersion y debe incluir las comillas. Por ejemplo, si el valor de ETag era "abc", el valor con caracteres de escape JSON sería {"etag":"\"abc\""}.

Método HTTP y URL:

POST https://secretmanager.googleapis.com/v1/projects/PROJECT_ID/secrets/SECRET_ID/versions/VERSION_ID:disable"

Cuerpo JSON de la solicitud:

{"etag":"ETAG"}

Para enviar tu solicitud, elige una de estas opciones:

curl

Guarda el cuerpo de la solicitud en un archivo llamado request.json y ejecuta el siguiente comando:

curl -X POST \
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
-H "Content-Type: application/json; charset=utf-8" \
-d @request.json \
"https://secretmanager.googleapis.com/v1/projects/PROJECT_ID/secrets/SECRET_ID/versions/VERSION_ID:disable""

PowerShell

Guarda el cuerpo de la solicitud en un archivo llamado request.json y ejecuta el siguiente comando:

$cred = gcloud auth print-access-token
$headers = @{ "Authorization" = "Bearer $cred" }

Invoke-WebRequest `
-Method POST `
-Headers $headers `
-ContentType: "application/json; charset=utf-8" `
-InFile request.json `
-Uri "https://secretmanager.googleapis.com/v1/projects/PROJECT_ID/secrets/SECRET_ID/versions/VERSION_ID:disable"" | Select-Object -Expand Content

Deberías recibir una respuesta JSON similar a la siguiente:

{
  "name": "projects/PROJECT_ID/locations/LOCATION/secrets/SECRET_ID/versions/VERSION_ID",
  "createTime": "2024-09-04T06:41:57.859674Z",
  "state": "DISABLED",
  "etag": "\"1621457b3c1459\""
}

Siguientes pasos