[S3 sync] sync元バケット/sync先バケットそれぞれに対して必要な権限を調べた

s3 syncを実行する際に必要になる権限は何なのか、sync元とsync先バケットではそれぞれ必要な権限が違うはず…と思ったので調べてみました。
2020.07.08

結論

  • sync元バケットに対しては、s3:ListBuckets3:GetObject権限が必要
  • sync先バケットに対しては、s3:ListBuckets3:PutObject権限が必要

調査準備

  • S3バケットを2つ用意します。 kazue-sync-sourceがをsync元バケット、kazue-sync-destをsync先バケットとして利用します。
  • 何のポリシーも付与していないIAMロールを作成します。profile名s3synctestでcliを使えるように設定します。
  • sync元バケットkazue-sync-sourceに適当なファイルをいくつかアップロードしておきます。(上記IAMロールとは違うprofileで。)

sync元バケットに対する権限の確認

sync元とsync先同時に確認すると混乱するので、まずはsync元の権限についてのみ調べます。

s3 syncはバケット間のsyncだけではなく、バケット→ローカルディレクトリやローカルディレクトリ→バケットのsyncも可能です。今回はまずはバケット→ローカルディレクトリのsyncを実行して、sync元バケットに対する権限の調査を行ないます。

まずはコマンド実行してみましょう。

$ aws s3 sync s3://kazue-sync-source . --profile s3synctest
fatal error: An error occurred (AccessDenied) when calling the ListObjectsV2 operation: Access Denied

s3synctestプロファイルには前述の通り何の権限も付与していないので、失敗するのは当然ですね。

ListObjectsV2 とは、バケット内のオブジェクト一覧を返すAPIです。lsコマンドみたいなものだと捉えていただければよいかと思います。

蛇足ですが、V2というとおりV1の後継APIです。V1も依然利用可能です。このあたりについての詳細は こちらのブログエントリ をどうぞ。

ListObjectsV2 APIを実行するのに必要な権限は何でしょうか?APIリファレンスに記載があります。

To use this operation in an AWS Identity and Access Management (IAM) policy, you must have permissions to perform the s3:ListBucket action.

s3:ListBucketですね。というわけでs3synctestに以下インラインポリシーを追加します。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "s3:ListBucket",
            "Resource": "arn:aws:s3:::kazue-sync-source"
        }
    ]
}

再度コマンド実行してみましょう。

$ aws s3 sync s3://kazue-sync-source . --profile s3synctest
download failed: s3://kazue-sync-source/2020-2nd-q/2.md to 2020-2nd-q/2.md An error occurred (AccessDenied) when calling the GetObject operation: Access Denied
Completed 14.1 KiB/~127.1 MiB (0 Bytes/s) with ~125 file(s) remaining (calculatidownload failed: s3://kazue-sync-source/2020-2nd-q/.DS_Store to 2020-2nd-q/.DS_Store An error occurred (AccessDenied) when calling the GetObject operation: Access Denied
Completed 24.1 KiB/~127.2 MiB (0 Bytes/s) with ~125 file(s) remaining (calculatidownload failed: s3://kazue-sync-source/2020-2nd-q/2-1.md to 2020-2nd-q/2-1.md An error occurred (AccessDenied) when calling the GetObject operation: Access Denied
Completed 26.2 KiB/~127.3 MiB (0 Bytes/s) with ~125 file(s) remaining (calculatidownload failed: s3://kazue-sync-source/2020-2nd-q/helpful-for-saa-exam.md to 2020-2nd-q/helpful-for-saa-exam.md An error occurred (AccessDenied) when calling the GetObject operation: Access Denied
(続く)

たくさん出力が返ってきました。各ファイルについての記述があるので、当然ですがs3:ListBucketは成功してそうです。各ファイルでGetObject operation: Access Deniedというエラーがでています。

GetObject APIのリファレンスをチェックします。

You need the s3:GetObject permission for this operation.

s3:GetObjectですね。そのままですね。

s3:GetObjectはオブジェクトレベルのアクションなので、Resource欄はオブジェクトを対象とするように末尾に/*をつけるのをお忘れなく。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::kazue-sync-source/*"
        }
    ]
}
$ aws s3 sync s3://kazue-sync-source . --profile s3synctest
Completed 10.0 KiB/~125.5 MiB (45.8 KiB/s) with ~117 file(s) remaining (calculatdownload: s3://kazue-sync-source/2020-2nd-q/.DS_Store to 2020-2nd-q/.DS_Store
Completed 10.0 KiB/~126.8 MiB (45.8 KiB/s) with ~123 file(s) remaining (calculatCompleted 12.1 KiB/129.9 MiB (51.6 KiB/s) with 166 file(s) remaining            download: s3://kazue-sync-source/2020-2nd-q/2-1.md to 2020-2nd-q/2-1.md
download: s3://kazue-sync-source/2020-2nd-q/2-2.md to 2020-2nd-q/2-2.md
(続く)

無事syncできるようになりました!

というわけでsync元バケットに対して必要な権限はs3:ListBuckets3:GetObjectです。

sync先バケットに対する権限の確認

今度はsync先をローカルディレクトリからS3バケットkazue-sync-dest変えます。現時点でs3synctestプロファイルはkazue-sync-destに対して何の権限もありません。

$ aws s3 sync s3://kazue-sync-source s3://kazue-sync-dest --profile s3synctest
fatal error: An error occurred (AccessDenied) when calling the ListObjectsV2 operation: Access Denied

先程と同様ListObjectsV2でAccess Deniedエラーになりました。sync先バケットにもs3:ListBucket権限は必要なようです。追加します。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "s3:ListBucket",
            "Resource": "arn:aws:s3:::kazue-sync-dest"
        }
    ]
}

再実行です。

$ aws s3 sync s3://kazue-sync-source s3://kazue-sync-dest --profile s3synctest
copy failed: s3://kazue-sync-source/2020-2nd-q/2-1.md to s3://kazue-sync-dest/2020-2nd-q/2-1.md An error occurred (AccessDenied) when calling the CopyObject operation: Access Denied
copy failed: s3://kazue-sync-source/2020-2nd-q/20200415.md to s3://kazue-sync-dest/2020-2nd-q/20200415.md An error occurred (AccessDenied) when calling the CopyObject operation: Access Denied
copy failed: s3://kazue-sync-source/2020-2nd-q/helpful-for-saa-exam.md to s3://kazue-sync-dest/2020-2nd-q/helpful-for-saa-exam.md An error occurred (AccessDenied) when calling the CopyObject operation: Access Denied
(copy failed:が続く)

今度はCopyObjectでAccess Deniedですね。CopyObjectのAPIリファレンスをチェックしましょう。

The following operations are related to CopyObject:
- PutObject
- GetObject

PutObjectとGetObjectのページリンクは割愛しますが、要はコピー元オブジェクトに対するs3:GetObject、コピー先オブジェクトに対するs3:PutObject権限があれば良いです。コピー元オブジェクトに対する権限はすでに付与済ですので、コピー先オブジェクトに対する権限を追加します。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "s3:PutObject",
            "Resource": "arn:aws:s3:::kazue-sync-dest/*"
        }
    ]
}

コマンド再実行します。

$ aws s3 sync s3://kazue-sync-source s3://kazue-sync-dest --profile s3synctest
copy: s3://kazue-sync-source/2020-2nd-q/2-1.md to s3://kazue-sync-dest/2020-2nd-q/2-1.md
copy: s3://kazue-sync-source/2020-2nd-q/helpful-for-saa-exam.md to s3://kazue-sync-dest/2020-2nd-q/helpful-for-saa-exam.md
copy: s3://kazue-sync-source/2020-2nd-q/20200415.md to s3://kazue-sync-dest/2020-2nd-q/20200415.md
(copy:が続く)

無事syncできました!

結論(再掲)

  • sync元バケットに対しては、s3:ListBuckets3:GetObject権限が必要
  • sync先バケットに対しては、s3:ListBuckets3:PutObject権限が必要

AWSでは、各リソースには必要最低限の権限のみ付与することが推奨されています。今回の場合は例えば s3フルアクセス、かつ対象リソースの縛りも無し、といった権限を与えてしまえば、こんな調査をする必要はありません。が、想定外の操作が実行されてしまうリスクを抱えることになります。できる限り最低限の権限のみを付与することを心がけましょう。

参考情報