オプティミスティック同時実行制御にエンティティ タグを使用する

Secret Manager は、オプティミスティック同時実行制御でのエンティティ タグ(ETag)の使用に対応しています。

場合によっては、同じリソースを並行して更新する 2 つのプロセスが互いに干渉することがあり、後のプロセスが前のプロセスの結果を上書きします。

ETag は、リソースに対してアクションを行う前に、リソースが変更されているかどうかをプロセスが確認できるようにすることで、オプティミスティック同時実行制御への手段を提供します。

Secret Manager で ETag を使用する

次のリソース変更リクエストは ETag をサポートします。

secrets.patch リクエストでは、リクエストの ETag が Secret データに埋め込まれます。他のすべてのリクエストは、オプションの etag パラメータを受け入れます。

ETag が指定され、現在のリソースの ETag と一致すると、リクエストは成功します。それ以外の場合は、FAILED_PRECONDITION エラーと HTTP ステータス コード 400 で失敗します。ETag が指定されていない場合、リクエストは現在格納されている ETag 値を確認せずに続行します。

リソース ETag はリソース作成時に生成され(projects.secrets.createprojects.secrets.addVersion)、上記の変更リクエストごとに更新されます。変更リクエストでは、適用先のリソースの ETag のみが更新されます。つまり、シークレット バージョンを更新してもシークレットの ETag には影響せず、同様に、ETag を更新してもシークレット バージョンには影響しません。

更新によってリソースの状態が変更されない場合でも、リソースの ETag は更新されます。

次に例を示します。

  • ユーザー 1 は、シークレット バージョンがすでに有効になっていることを認識せず、シークレット バージョンを有効にしようとします。システムはこれを処理し、バージョンの ETag 以外は変更しません。

  • ユーザー 2 が古い ETag を使用してバージョンを無効にしようとします。

  • これは、バージョンを有効に保つための新しいインテントを示す、新しい ETag がシステムで認識されるため失敗します。

ETag が変更されるため、一見すると小さな更新でも重要です。これにより、特に複数のユーザーまたはシステムが同じリソースを操作する場合に、データの整合性が確保されます。

リソース etag は、リソース(Secret または SecretVersion)が含まれている場合にレスポンスで返されます。

ETag を使用してシークレットを削除する

このセクションでは、シークレットを削除する際に ETag を使用する方法について説明します。シークレットが別のプロセスによって変更されている場合、削除のオペレーションは失敗します。

gcloud

後述のコマンドデータを使用する前に、次のように置き換えます。

  • SECRET_ID: Secret の ID。
  • ETAG: シークレットのエンティティ タグ。ETag には、引用符を含める必要があります。たとえば、ETag 値が "abc" の場合、シェルのエスケープ値は "\"abc\"" になります。

次のコマンドを実行します。

Linux、macOS、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

リクエストのデータを使用する前に、次のように置き換えます。

  • PROJECT_ID: Google Cloud プロジェクト ID。
  • SECRET_ID: Secret の ID。
  • ETAG: シークレットのエンティティ タグ。ETag は、URL のクエリ文字列の一部として指定され、URL エンコードされている必要があります。たとえば、ETag 値が "abc" の場合、引用符が %22 としてエンコードされるため、URL エンコード値は %22abc%22 になります。

HTTP メソッドと URL:

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

リクエストの本文(JSON):

{}

リクエストを送信するには、次のいずれかのオプションを選択します。

curl

リクエスト本文を request.json という名前のファイルに保存して、次のコマンドを実行します。

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

リクエスト本文を request.json という名前のファイルに保存して、次のコマンドを実行します。

$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

次のような JSON レスポンスが返されます。

{}

ETag を使用してシークレットを更新する

このセクションでは、シークレットの更新時に ETag を使用する方法について説明します。シークレットが別のプロセスによって変更されている場合、更新のオペレーションは失敗します。

gcloud

後述のコマンドデータを使用する前に、次のように置き換えます。

  • SECRET_ID: Secret の ID。
  • KEY: ラベル名
  • VALUE: 対応するラベル値。
  • ETAG: シークレットのエンティティ タグ。ETag には、引用符を含める必要があります。たとえば、ETag 値が "abc" の場合、シェルのエスケープ値は "\"abc\"" になります。

次のコマンドを実行します。

Linux、macOS、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"

レスポンスで、シークレットが返されます。

REST

リクエストのデータを使用する前に、次のように置き換えます。

  • PROJECT_ID: Google Cloud プロジェクト ID。
  • SECRET_ID: Secret の ID。
  • ETAG: シークレットのエンティティ タグ。ETag はシークレットのフィールドとして指定され、引用符を含む必要があります。たとえば、ETag 値が "abc" の場合、JSON のエスケープ値は {"etag":"\"abc\""} になります。
  • KEY: ラベル名
  • VALUE: 対応するラベル値。

HTTP メソッドと URL:

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

リクエストの本文(JSON):

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

リクエストを送信するには、次のいずれかのオプションを選択します。

curl

リクエスト本文を request.json という名前のファイルに保存して、次のコマンドを実行します。

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

リクエスト本文を request.json という名前のファイルに保存して、次のコマンドを実行します。

$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

次のような JSON レスポンスが返されます。

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

ETag を使用してシークレット バージョンを更新する

このセクションでは、シークレット バージョンの更新時に ETag を使用する方法について説明します。シークレット バージョンが別のプロセスによって変更されている場合、更新のオペレーションは失敗します。

次のコードサンプルでは、ETag を使用してシークレット バージョンを無効にする方法について説明します。無効なバージョンの有効化やシークレット バージョンの破棄など、他のシークレットのミューテーション オペレーション中に ETag を指定することもできます。Secret Manager のコードサンプルをご覧ください。

gcloud

後述のコマンドデータを使用する前に、次のように置き換えます。

  • VERSION_ID: シークレット バージョンの ID。
  • SECRET_ID: Secret の ID。
  • ETAG: エンティティ タグ。ETag には、引用符を含める必要があります。たとえば、ETag 値が "abc" の場合、シェルのエスケープ値は "\"abc\"" になります。

次のコマンドを実行します。

Linux、macOS、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"

レスポンスで、シークレットが返されます。

REST

リクエストのデータを使用する前に、次のように置き換えます。

  • PROJECT_ID: Google Cloud プロジェクト ID。
  • SECRET_ID: Secret の ID。
  • VERSION_ID: シークレット バージョンの ID。
  • ETAG: シークレットのバージョンのエンティティ タグ。ETag は SecretVersion のフィールドとして指定され、引用符を含む必要があります。たとえば、ETag 値が "abc" の場合、JSON のエスケープ値は {"etag":"\"abc\""} になります。

HTTP メソッドと URL:

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

リクエストの本文(JSON):

{"etag":"ETAG"}

リクエストを送信するには、次のいずれかのオプションを選択します。

curl

リクエスト本文を request.json という名前のファイルに保存して、次のコマンドを実行します。

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

リクエスト本文を request.json という名前のファイルに保存して、次のコマンドを実行します。

$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

次のような JSON レスポンスが返されます。

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

次のステップ