[アップデート]S3の条件付き書き込みをバケットポリシーで強制できるようになりました

[アップデート]S3の条件付き書き込みをバケットポリシーで強制できるようになりました

Amazon S3の新機能「条件付き書き込みのバケットポリシーによる強制」を実際に検証しました。この機能により、S3バケットレベルで条件付き書き込みを強制し、データの整合性を保護する新たな選択肢が追加されました。
Clock Icon2024.11.26

こんにちは、リテールアプリ共創部の塚本です。
2024年11月25日に、S3のバケットポリシーにて条件付き書き込みを強制する機能が追加されました。

https://aws.amazon.com/jp/about-aws/whats-new/2024/11/amazon-s3-enforcement-conditional-write-operations-general-purpose-buckets/

今回の記事では、バケットポリシーを設定し、実際に条件付き書き込みを強制できるかを確認します。

条件付き書き込みは簡単に説明すると、S3へのリクエスト時に特定のヘッダーを付与することで、上書き防止や競合防止を実現できる機能です。
条件付き書き込みの詳しい仕様については、以下のブログをご参照ください。

https://dev.classmethod.jp/articles/amazon-s3-conditional-writes/

https://dev.classmethod.jp/articles/s3-conditional-writes-awscli/

試してみた

if-none-matchif-match どちらのヘッダーも強制する設定が可能です。
今回は上書き防止用の if-none-match ヘッダーをバケットポリシーで強制してみます。

User Guideに詳しい記載があるので、こちらを参考にして試してみます。

https://docs.aws.amazon.com/AmazonS3/latest/userguide/conditional-writes-enforce.html

バケットポリシーの設定

S3バケットを作成し、以下のバケットポリシーを設定します。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "AllowConditionalPut",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::<ACCOUNT_ID>:user/<IAM_USER>"
            },
            "Action": "s3:PutObject",
            "Resource": "arn:aws:s3:::<BUCKET_NAME>/*",
            "Condition": {
                "Null": {
                    "s3:if-none-match": "false"
                }
            }
        }
    ]
}

以下、個別の設定を見ていきます。

            "Principal": {
                "AWS": "arn:aws:iam::<ACCOUNT_ID>:user/<IAM_USER>"
            },

こちらで設定するIAMユーザーは、後ほどAWS CLIを実行する際のユーザーです。
事前に、S3に関する権限を何も付与していないユーザーを用意しました。

            "Condition": {
                "Null": {
                    "s3:if-none-match": "false"
                }
            }

こちらの箇所ではNull演算子を利用し、「if-none-match ヘッダーが存在し、その値がnullではないこと」を条件としています。
https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/reference_policies_elements_condition_operators.html#Conditions_Null

同名オブジェクトがなし・if-none-matchヘッダなしで put-objectを実行する => オブジェクトが作成されない

$ aws s3api put-object --bucket "<BUCKET_NAME>"  --key "test-object" --body test-file.txt

An error occurred (AccessDenied) when calling the PutObject operation: User: arn:aws:iam::<ACCOUNT_ID>:user/<USER_NAME> is not authorized to perform: s3:PutObject on resource: "arn:aws:s3:::<BUCKET_NAME>/test-object" because no identity-based policy allows the s3:PutObject action

バケットポリシーの設定通り、if-none-matchがない場合はバケットポリシーにて権限が設定されていないため、PutObjectに失敗します。

同名オブジェクトなし・if-none-matchヘッダありで put-objectを実行する => オブジェクトが作成される

$ aws s3api put-object --bucket "<BUCKET_NAME>"  --key "test-object" --body test-file.txt --if-none-match "*"

{
    "ETag": "\"hogehoge\"",
    "ServerSideEncryption": "AES256"
}

バケットポリシーの設定通り、if-none-matchがある場合はバケットポリシーにて権限が設定されているため、PutObjectに成功します。

同名オブジェクトあり・if-none-matchヘッダありで put-objectを実行する => 上書きされない

$ aws s3api put-object --bucket "<BUCKET_NAME>"  --key "test-object" --body test-file.txt --if-none-match "*"

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

念の為、同名オブジェクトがある場合も試してみました。
通常の動作通り、同名オブジェクトが存在するので上書きすることができません。

おわりに

今回、Amazon S3のアップデートである「条件付き書き込みのバケットポリシーによる強制」を実際に試してみました。主な内容は以下の通りです:

  • バケットポリシーを使用して、if-none-match ヘッダーの使用を強制する設定を行いました。
  • AWS CLIを使用して、ヘッダーありとなしの両方のケースでPutObjectを実行し、動作を確認しました。
  • 期待通り、if-none-match ヘッダーがない場合はアクセスが拒否され、ヘッダーがある場合はオブジェクトの作成に成功しました。

この機能により、S3バケットレベルで条件付き書き込みを強制できるようになり、データの整合性を保護するための新たな選択肢が増えました。特に、複数のクライアントやアプリケーションが同じバケットにアクセスするような環境で有用だと感じました。

この新機能は、特定のシナリオで非常に有効に機能しそうです。今後、実際のプロジェクトでの適用を検討し、その効果を実践的に検証していきたいと思います。

Share this article

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.