ENECHANGE Developer Blog

ENECHANGE開発者ブログ

Amazon S3 が条件付き書き込みのサポートを開始

Amazon S3における条件付きリクエストの活用

特定の条件が満たされた場合にのみオブジェクトのアップロードや更新を許可する機能です。競合の防止やデータの整合性を確保するために使用できます。

https://aws.amazon.com/jp/about-aws/whats-new/2024/08/amazon-s3-conditional-writes/

GetObject、HeadObjectの条件付きリクエスト

  • If-Match: オブジェクトのEtagと一致する場合にのみリクエストを実行
  • If-None-Match: オブジェクトのEtagと異なる場合にのみリクエストを実行
  • If-Modified-Since: 指定日時以降にオブジェクトが変更されている場合にリクエストを実行
  • If-Unmodified-Since: 指定日時以降に変更されていない場合にリクエストを実行

PutObjectの条件付きリクエスト

  • If-None-Match: オブジェクトのEtagと異なる場合にのみリクエストを実行

重要なのはS3自体には、すべてのリクエストで条件付き書き込みを標準化するための機能は提供されていません。つまり、S3の設定で条件付きリクエストを必須にすることはできません。標準化はクライアント側の実装や運用ポリシーで行う必要があります。

PutObjectの使用方法

主にIf-None-Matchを使用し、条件付きでオブジェクトの上書きを制御します。If-Matchはサポートされていないため、書き込み時にEtagを使った厳密な制御はできません。

  • --if-none-match: 同名のオブジェクトがすでに存在する場合はアップロードが失敗します。オブジェクトの内容が一致しているかどうかは関係なく、名前(キー)が同じであれば条件に合致せず、アップロードが拒否されます。

条件合致しないケース(同名キーが存在する)

% aws s3api put-object --bucket hopstepjump --key test.data --body ~/docs/test.data --if-none-match "*"

An error occurred (PreconditionFailed) when calling the PutObject operation: At least one of the pre-conditions you specified did not hold
  • 条件合致するケース(同名キーが存在しない)
% aws s3api put-object --bucket hopstepjump --key test.data2 --body ~/docs/test.data2 --if-none-match "*"
{
    "ETag": "\"*******************************\"",
    "ServerSideEncryption": "AES256"
}

GetObjectの条件付きリクエスト

If-MatchIf-None-Matchを使用して、Etagの一致を基にオブジェクトの取得条件を設定できます。読み取りに対してEtagによる整合性のチェックが可能です。

If-MatchでEtagによる整合性をチェックするケース

Etagの確認

% aws s3api head-object --bucket hopstepjump --key test.data --query ETag --output text
"*******************************"

得たEtagを指定した条件合致するケース

% aws s3api get-object --bucket hopstepjump --key test.data ~/docs/test.data --if-match "*******************************"
{
    "AcceptRanges": "bytes",
    "LastModified": "2024-09-03T05:15:22+00:00",
    "ContentLength": 8888,
    "ETag": "\"*******************************\"",
    "ContentType": "binary/octet-stream",
    "ServerSideEncryption": "AES256",
    "Metadata": {}
}

Etagを指定した条件合致しないケース

% aws s3api get-object --bucket hopstepjump --key test.data ~/docs/test.data --if-match "*******************************"

An error occurred (PreconditionFailed) when calling the GetObject operation: At least one of the pre-conditions you specified did not hold

terraform.tfstateについて

terraformのtfstateをDynamoDBによってロックしなくてもこの条件付き上書き機能で運用できるかも?と思いましたが、そもそもPutActionはEtagを使った制御ができませんでした。