S3既存オブジェクトに一括でbucket-owner-full-controlを付与する | AWS CLI

S3バケットの既存の全オブジェクトに--acl bucket-owner-full-controlを一括付与するやり方の備忘録です。


はじめに

クロスアカウントのS3間でオブジェクトをコピーするとき、--acl bucket-owner-full-controlを付与せずにそのままアップロードしてしまうと、アップロード先のアカウント側からアクセスできなくなることが知られています


f:id:BioErrorLog:20201102184648p:plain
--acl bucket-owner-full-controlを付与せずにクロスアカウントS3アップロードすると、アップロード先のアカウントからアクセスできない

この問題を事前に回避するには、オブジェクトコピー時に--acl bucket-owner-full-controllを付与したり、コピー先のS3バケットでObject Ownershipを設定したりする方法が挙げられます。

一方、オブジェクトコピー後にこの問題を解消するには、put-object-aclコマンドを用いて後からbucket-owner-full-controlを付与する方法があります。

aws s3api put-object-acl --bucket destination_awsexamplebucket --key keyname --acl bucket-owner-full-control

※コマンドはオブジェクトコピー元アカウントの権限で実行する必要があります。

しかし、このコマンドはS3オブジェクト1つに対して実行するものであり、特定ディレクトリやバケット全体を指定することはできません。 そうしたい場合には、ちょっとした工夫が必要になります。

今回はそのような、特定ディレクトリやバケット全体を指定して--acl bucket-owner-full-controlを一括付与するやり方を記します。


既存オブジェクトにbucket-owner-full-controllを一括付与する

結論として、以下のコマンドを実行します。

aws s3 ls s3://target-bucket/ --recursive | awk '{print $4}' | xargs -I KEY aws s3api put-object-acl --bucket target-bucket --key "KEY" --acl bucket-owner-full-control

(コマンドはこちらを参考/改変しています)


※追記: 上記コマンドは、オブジェクトキーに日本語が入っていたり、スペースが入っていたりすると上手く機能しません。 代わりに以下のコマンドの方がお勧めです。

aws s3api list-objects-v2 --bucket target-bucket | jq .Contents[].Key | xargs -I KEY aws s3api put-object-acl --bucket target-bucket --key "KEY" --acl bucket-owner-full-control


これは3つのコマンドをパイプで繋げたものであり、指定したS3バケット/ディレクトリ以下にあるオブジェクト全てにbucket-owner-full-controlを付与しています。

以下、上記コマンドを旧バージョンのものと追記バージョンのものとで、それぞれひとつひとつ見ていきます。


追記バージョンコマンドの解説

aws s3api list-objects-v2 --bucket target-bucket | jq .Contents[].Key | xargs -I KEY aws s3api put-object-acl --bucket target-bucket --key "KEY" --acl bucket-owner-full-control

まず、こちら追記バージョンコマンドの解説をします。


aws s3api list-objects-v2 --bucket target-bucket

まずはこちらlist-objects-v2コマンドにより、以下のようにバケットのオブジェクトリストを取得します。

$ aws s3api list-objects-v2 --bucket target-bucket
{
    "Contents": [
        {
            "LastModified": "2020-11-02T12:45:17.000Z", 
            "ETag": "\"47bce5c74f589f4867dbd57e9ca9f808\"", 
            "StorageClass": "STANDARD", 
            "Key": "aaa.txt", 
            "Size": 3
        }, 
        {
            "LastModified": "2020-11-02T12:45:17.000Z", 
            "ETag": "\"585cc54d19a29743e94948bf6d3a4592\"", 
            "StorageClass": "STANDARD", 
            "Key": "bbb.txt", 
            "Size": 12
        }, 
        {
            "LastModified": "2020-11-02T12:45:17.000Z", 
            "ETag": "\"9df62e693988eb4e1e1444ece0578579\"", 
            "StorageClass": "STANDARD", 
            "Key": "ccc.txt", 
            "Size": 3
        }, 
        {
            "LastModified": "2020-11-02T12:45:17.000Z", 
            "ETag": "\"47bce5c74f589f4867dbd57e9ca9f808\"", 
            "StorageClass": "STANDARD", 
            "Key": "ddd.txt", 
            "Size": 3
        }, 
        {
            "LastModified": "2020-11-02T12:45:17.000Z", 
            "ETag": "\"585cc54d19a29743e94948bf6d3a4592\"", 
            "StorageClass": "STANDARD", 
            "Key": "eee.txt", 
            "Size": 12
        }, 
        {
            "LastModified": "2020-11-02T12:45:17.000Z", 
            "ETag": "\"9df62e693988eb4e1e1444ece0578579\"", 
            "StorageClass": "STANDARD", 
            "Key": "fff.txt", 
            "Size": 3
        }
    ]
}

なお、取得範囲を特定パスに絞りたいときは、--prefixオプションを使用します。


次に、上記実行結果をjqコマンドで処理します。

jq .Contents[].Key

jqは、jsonから値を抽出できるコマンドです。 上記コマンドにより、オブジェクトリストのうちオブジェクトキーを抽出します。

$ aws s3api list-objects-v2 --bucket target-bucket-001 | jq .Contents[].Key                                                                                                                                             
"aaa.txt"
"bbb.txt"
"ccc.txt"
"ddd.txt"
"eee.txt"
"fff.txt"

これでちょうど、オブジェクトキーが出力される形になります。


最後にこの出力を受け取って、以下のコマンドを実行します。

xargs -I KEY aws s3api put-object-acl --bucket target-bucket --key "KEY" --acl bucket-owner-full-control

xargsコマンドは、標準入力からインプットを受けてコマンドを実行するものです。

-Iオプションに指定した変数(今回の例ではKEY)を置き換え文字とし、標準入力から受け取ったオブジェクトキー名を後続コマンドaws s3api put-object-acl--keyオプションに当てています。


以上この3段階のコマンドを経て、指定したディレクトリ以下にある全オブジェクトに--acl bucket-owner-full-controlを付与さることができます。


旧バージョンコマンドの解説

aws s3 ls s3://target-bucket/ --recursive | awk '{print $4}' | xargs -I KEY aws s3api put-object-acl --bucket target-bucket --key "KEY" --acl bucket-owner-full-control

こちら旧バージョンコマンドの解説も残しておきます。

前述の通り、こちらはオブジェクトキーに日本語が入っていたり、スペースが入っていたりすると上手く機能しないので注意が必要です。

aws s3 ls s3://target-bucket/ --recursive

まずはこのaws s3 lsコマンドで、指定したS3バケット/ディレクトリ以下にある全オブジェクトを取得します。

このコマンド単体の実行結果は以下のようになります。

$ aws s3 ls s3://target-bucket-001/ --recursive
2020-11-02 12:45:17          3 aaa.txt
2020-11-02 12:45:17         12 bbb.txt
2020-11-02 12:45:17          3 ccc.txt
2020-11-02 12:45:17          3 ddd.txt
2020-11-02 12:45:17         12 eee.txt
2020-11-02 12:45:17          3 fff.txt


次に、上記実行結果がawkコマンドに渡されます。

awk '{print $4}'

awkコマンドは、テキストデータをパターンで処理できるコマンドです。 '{print $4}'を指定することで、4行目を出力させています。

ここまでを合わせると、出力は以下のようになります。

$ aws s3 ls s3://target-bucket-001/ --recursive | awk '{print $4}'
aaa.txt
bbb.txt
ccc.txt
ddd.txt
eee.txt
fff.txt

ちょうどオブジェクトキーが出力される形になります。


最後にこの出力を受け取って、以下のコマンドを実行します。

xargs -I KEY aws s3api put-object-acl --bucket target-bucket --key "KEY" --acl bucket-owner-full-control

xargsコマンドは、標準入力からインプットを受けてコマンドを実行するものです。

-Iオプションに指定した変数(今回の例ではKEY)を置き換え文字とし、標準入力から受け取ったオブジェクトキー名を後続コマンドaws s3api put-object-acl--keyオプションに当てています。


以上この3段階のコマンドを経て、指定したディレクトリ以下にある全オブジェクトに--acl bucket-owner-full-controlを付与さることができます。


おわりに

S3バケットの既存オブジェクトに、--acl bucket-owner-full-controlを一括付与するやり方の備忘録を書きました。

今回はbucket-owner-full-controlを取り上げましたが、ほかのACL権限設定についても同様のやり方で対処することが出来ます。

また、もちろんBoto3などSDKを用いても同様の処理を書くことができます。

が、一行で済んでしまうこの手軽さは、コマンド良いところだと改めて感じます。


関連記事

S3バケットポリシーとIAMポリシーの関係を、同一アカウント・クロスアカウントそれぞれにおいて整理しました。 www.bioerrorlog.work


AWS CLIのs3 cps3 syncの違いをまとめました。 www.bioerrorlog.work


Boto3でAssumeRoleするやり方を書きました。 www.bioerrorlog.work


参考

Resolve 403 Access Denied Error From S3 Object Uploaded by Another Account

Require S3 Object Access When Other AWS Accounts Upload to Your Bucket

Bucket Policy Examples - Amazon Simple Storage Service

Amazon S3 Object Ownership is available to enable bucket owners to automatically assume ownership of objects uploaded to their buckets

Controlling ownership of uploaded objects using S3 Object Ownership - Amazon Simple Storage Service