ちょっと話題の記事

[アップデート] オブジェクト所有権でもう悩まない!S3 バケット所有者がアップロード時に自動的にオブジェクト所有権を引き継げるようになりました。

「なんか、アクセス権ないオブジェクトあるーーっ!」なんてサプライズも昨日まで。
2020.10.03

本日のアップデートで、S3 バケット所有者が自動的にオブジェクトの所有権を引き継ぐことが可能となりました。

タイトルだけ読んでもサッパリ解らないと思いますので、ひとまず以下の図で説明していきます!

オブジェクトの所有権を引き継ぐとは?

S3 でデータレイクを構成する場合、とあるアカウントの S3 バケットに対して各 AWS アカウントからファイルをアップロードするといった環境が多いのではないでしょうか。いわゆるクロスアカウントでの S3 アップロードの構成です。

このような環境において課題となるのはオブジェクトの所有権です。

従来のオブジェクト所有権

仮に S3 バケット所有者をアカウントA、オブジェクトを PUT する側をアカウントBとします。単純に S3 バケットポリシーでアカウントBからの PutObject を許可し、ファイルアップロードさせた場合は下図のとおりオブジェクトの所有者はアカウントBとなり、アカウントAはそのオブジェクトを管理することが出来ません。

この問題を回避するためには、アカウントBからの PutObject--acl bucket-owner-full-control オプションを付与することで、バケット所有者にもオブジェクトのアクセス権限を設定することが可能です。

必ず --acl bucket-owner-full-control が付与されるのであれば良いのですが、実際の運用ではオプション指定が漏れたオブジェクトもアップロードされてくるでしょう。その場合、このようになります。

え。「なんもわからんやん・・・」(アクセス権がないので。。)

幾つもの AWS アカウントで共有されているバケットの場合、このオブジェクトは誰にアクセス権付与を依頼すればよいのでしょう・・・。どこからアップロードされたのかを突き止めるまでに一苦労。そんな運用はつらすぎる。。

自動的にオブジェクト所有権を変更する

そこで今回のアップデートです。S3 バケットの設定値として「オブジェクト所有者」の指定が可能となりました。同設定をバケット所有者に設定することで、--acl bucket-owner-full-control によってアップロードされたオブジェクトの所有権は自動的にバケット所有者に変更されます。(後述しますが、同設定を利用するにはバケットポリシーで bucket-owner-full-control の指定を必須にします)

(余談)GA なの?プレビューなの?

公式ドキュメントでは S3 Object Ownership はプレビューであるとの記載があります。

S3 Object Ownership is currently under preview and can be configured through the AWS Management Console, AWS Command Line Interface, AWS SDKs, or Amazon S3 REST APIs. AWS CloudFormation support is planned for general availability.

通常、公式のリリース情報ではプレビューの場合はプレビューであると明記されているはずなのですが、今回はアップデートリリースおよび公式ブログを確認しても特にプレビューだと言及しているものがありません。

本番利用を検討されるユーザーにとっては、「GA?プレビュー?どっちなん?」というのは重要なポイントかと思いますので明確なアナウンスを待ってから導入検討いただくのが良いかと思います。

やってみる

2 つの AWS アカウントを使ってさっそく試してみました。S3 バケットには以下のようなポリシーを設定しています。AWS アカウント 123456789012 が上図のアカウントB だとお考えください。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "Only allow writes to my bucket with bucket owner full control",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::123456789012:user/marumo1981"
            },
            "Action": "s3:PutObject",
            "Resource": "arn:aws:s3:::cm-cross-account/*",
            "Condition": {
                "StringEquals": {
                    "s3:x-amz-acl": "bucket-owner-full-control"
                }
            }
        }
    ]
}

2020.10.09 追記
より厳密に制限をかけたい場合は、明示的な拒否ポリシーをあわせてご利用ください。
Examples — Amazon S3 Condition Keys for Object Operations

デフォルト(オブジェクトライター)の動作

まずは従来の動作を確認します。アカウントB からファイルをアップロードします。

$ aws s3 cp test.text s3://cm-cross-account --acl bucket-owner-full-control
upload: ./test.text to s3://cm-cross-account/test.text

オブジェクトの所有者を確認すると (外部アカウント) になっていますので所有権は オブジェクトライター であることが確認できました。

オブジェクト所有者を設定する

S3 コンソールから対象バケットの [アクセス権限] タブを開き、[オブジェクト所有者] - [編集] をクリックします。

希望するバケット所有者 を選択し、[保存]します。注意点としては対象のバケットポリシーでは先述のポリシーのように bucket-owner-full-control を PUT リクエストの条件に設定することが必要となります。

bucket-owner-full-control の指定がない場合、以下のように PutObject に失敗します。

$ aws s3 cp test.text s3://cm-cross-account
upload failed: ./test.text to s3://cm-cross-account/test.text An error occurred (AccessDenied) when calling the PutObject operation: Access Denied

アカウントBからアップロード

それでは再度、アカウントBからファイルをアップロードします

$ aws s3 cp test.text s3://cm-cross-account --acl bucket-owner-full-control
upload: ./test.text to s3://cm-cross-account/test.text

バケット所有者がオブジェクト所有者として自動的に設定されていることが確認できました。

検証は以上です。

さいごに

これまでクロスアカウントの S3 利用でハマった方は少なくないのではないでしょうか。私も過去に何度かハマった経験があります。。

個人的にはバケット所有者がそのバケット内のオブジェクト所有者であることで、よりシンプルにクロスアカウント環境の運用が出来るように思います。(もちろんセキュリティ上、そうできないものもあると思いますが)

クロスアカウントの S3 利用でアクセス権漏れに苦しめられている管理者の方がおられましたら、ご検討されてみてはいかがでしょうか!

以上!大阪オフィスの丸毛(@marumo1981)でした!