S3にバケット所有者でオブジェクトをUploadする

AWS,IAM_Policy関連,S3

概要

  • 今回は、S3バケットの"Object ownership" 設定をカスタマイズして、S3にバケット所有者としてオブジェクトをUpload する方法をご紹介します。
  • S3バケットの"Object ownership" 設定は、2020年10月の Amazon S3 Updateの機能追加によって使用可能になっています。
  • なお、今回の内容は下記記事でご紹介した、S3 クロスアカウント環境においてCloudWatch Logs からエクスポートされたオブジェクトを取得する際に発生するHTTP 403 エラーの対策にもなりえます。同様の問題でお困りの方は、是非試してみてください。

 

シチュエーション

  • 今回の想定するシチュエーションは、下記2つです。
    • 1つ目は、クロスアカウントで使用するS3 環境があり、アカウント:A のサーバーリソースからアカウント:B の S3バケットにオブジェクトを書き込みます。通常はオブジェクトの所有者は、オブジェクトの書き込みを行ったアカウント:A となります。"Object ownership" 設定をカスタマイズ後は、オブジェクトの所有者は、バケット所有者であるアカウント:B となります。
    • 2つ目は、クロスアカウントで使用するS3 環境があり、アカウント:A のCloudWatch Logsからアカウント:B の S3バケットにログをエクスポートします。通常はオブジェクトの所有者は、CloudWatch Logsを表す“logs+prod-nrt" となります。"Object ownership" 設定をカスタマイズ後は、オブジェクトの所有者は、バケット所有者であるアカウント:B となります。

 

 

クロスアカウント環境のオブジェクト書き込み

S3 クロスアカウント環境の準備

  • S3 をクロスアカウント環境で使用する場合の準備を行います。アカウント:B のS3バケットに、こちらの記事で紹介したバケットポリシーを設定します。ここで、"111111111111″ はアカウント:A のアカウント番号を表します。
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "DelegateS3Access",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::111111111111:root"
            },
            "Action": "s3:*",
            "Resource": [
                "arn:aws:s3:::s3-bucket-name/*",
                "arn:aws:s3:::s3-bucket-name"
            ]
        }
    ]
}
  • アカウント:A のEC2 には、S3バケットに書き込みが可能なポリシー(例: AmazonS3FullAccess)を設定したロールを割り当てます。

 

Object ownershipがデフォルトの場合

  • S3のObject ownershipがデフォルトのObject writer(オブジェクトライター)に設定された場合の動作は下記となります。
  • アカウント:A のEC2 からアカウント:B の S3バケットに対し、aws s3 lsコマンド, aws s3 cpコマンドが成功します。aws s3api list-objects-v2コマンドで確認すると、"DisplayName"からオブジェクトの所有者はアカウント:A であることが分かります。
$ aws s3 ls s3://s3-bucket-name/test-cross-account/
2021-01-10 12:18:12          0
$ aws s3 cp TEST-A s3://s3-bucket-name/test-cross-account/
upload: ./TEST-A to s3://s3-bucket-name/test-cross-account/TEST-A
$ aws s3 ls s3://s3-bucket-name/test-cross-account/
2021-01-10 12:18:12          0
2021-01-10 12:20:18          0 TEST-A
$ aws s3api list-objects-v2 --fetch-owner --bucket s3-bucket-name --prefix test-cross-account/TEST-A
{
    "Contents": [
        {
            "LastModified": "2021-01-10T12:20:18.000Z",
            "ETag": "\"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\"",
            "StorageClass": "STANDARD",
            "Key": "test-cross-account/TEST-A",
            "Owner": {
                "DisplayName": "account-a",
                "ID": "0123abcd0123abcd0123abcd0123abcd0123abcd0123abcd0123abcd0123abcd"
            },
            "Size": 0
        }
    ]
}

 

  • また、コンソールからの確認においても、オブジェクトの所有者はアカウント:A であることが分かります。

 

Object ownershipがバケット所有者の場合

  • S3のObject ownershipをBucket owner preferred(希望するバケット所有者)に設定します。
  • S3バケットの設定から"アクセス許可"を開きます。"オブジェクト所有者" の設定を編集します。

 

  • 以下の通り、オブジェクト所有者を"Bucket owner preferred(希望するバケット所有者)" に変更します。

 

  • 次に、必須ではありませんが、アカウント:B のS3バケットに記載したバケットポリシーに、ConditionとしてオブジェクトのACLに “bucket-owner-full-control" がセットされている条件を追記します。
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "DelegateS3Access",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::111111111111:root"
            },
            "Action": "s3:*",
            "Resource": [
                "arn:aws:s3:::s3-bucket-name/*",
                "arn:aws:s3:::s3-bucket-name"
            ],
            "Condition": {
                "StringEquals": {
                    "s3:x-amz-acl": "bucket-owner-full-control"
                }
            }
        }
    ]
}
  • 再度、アカウント:A のEC2 からアカウント:B の S3バケットに対し、AWS CLI を実行します。先ほど実行した aws s3 lsコマンド, aws s3 cpコマンドは失敗しました。
$ aws s3 ls s3://s3-bucket-name/test-cross-account/

An error occurred (AccessDenied) when calling the ListObjectsV2 operation: Access Denied
$ aws s3 cp TEST-B s3://s3-bucket-name/test-cross-account/
upload failed: ./TEST-B to s3://s3-bucket-name/test-cross-account/TEST-B An error occurred (AccessDenied) when calling the PutObject operation: Access Denied

 

  • 代わりに、aws s3 cpコマンドに “–acl bucket-owner-full-control" オプションを付け実行します。
$ aws s3 cp TEST-B s3://s3-bucket-name/test-cross-account/ --acl bucket-owner-full-control
upload: ./TEST-B to s3://s3-bucket-name/test-cross-account/TEST-B

 

  • コンソールから確認すると、オブジェクトの所有者はバケット所有者であるアカウント:B であることが分かります。

 

 

クロスアカウント環境のCloudWatch LogsのExport

S3 クロスアカウント環境の準備

  • S3 をクロスアカウント環境で使用する場合の準備を行います。アカウント:B のS3バケットに、こちらの記事で紹介したバケットポリシーを設定します。
  • さらに、CloudWatch Logsのログをエクスポートするために、こちらの記事で紹介したバケットポリシーを設定します。
  • ここで、"111111111111″ はアカウント:A のアカウント番号を表します。
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "DelegateS3Access",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::111111111111:root"
            },
            "Action": "s3:*",
            "Resource": [
                "arn:aws:s3:::s3-bucket-name/*",
                "arn:aws:s3:::s3-bucket-name"
            ]
        },
        {
            "Effect": "Allow",
            "Principal": {
                "Service": "logs.ap-northeast-1.amazonaws.com"
            },
            "Action": "s3:GetBucketAcl",
            "Resource": "arn:aws:s3:::s3-bucket-name"
        },
        {
            "Effect": "Allow",
            "Principal": {
                "Service": "logs.ap-northeast-1.amazonaws.com"
            },
            "Action": "s3:PutObject",
            "Resource": "arn:aws:s3:::s3-bucket-name/*",
            "Condition": {
                "StringEquals": {
                    "s3:x-amz-acl": "bucket-owner-full-control"
                }
            }
        }
    ]
}

 

Object ownershipがデフォルトの場合

  • S3のObject ownershipがデフォルトのObject writer(オブジェクトライター)に設定された場合の動作は下記となります。
  • アカウント:A のコンソールからCloudWatch Logsを開き、ログをエクスポートします。

 

  • アカウントに"Another account"、S3バケット名, プレフィックスに対象の名前を指定して、[エクスポート]を押します。

 

  • アカウント:B のS3 コンソールから、エクスポートされたオブジェクトが書き込みされたことを確認します。
  • 以下の通り、オブジェクトの所有者は、CloudWatch Logsを表す“logs+prod-nrt" となります。

 

Object ownershipがバケット所有者の場合

  • S3のObject ownershipをBucket owner preferred(希望するバケット所有者)に設定します。
  • S3バケットの設定から"アクセス許可"を開きます。"オブジェクト所有者" の設定を編集します。

 

  • 以下の通り、オブジェクト所有者を"Bucket owner preferred(希望するバケット所有者)" に変更します。

 

  • 次に、必須ではありませんが、アカウント:B のS3バケットに記載したバケットポリシーに、ConditionとしてオブジェクトのACLに “bucket-owner-full-control" がセットされている条件を追記します。
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "DelegateS3Access",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::111111111111:root"
            },
            "Action": "s3:*",
            "Resource": [
                "arn:aws:s3:::s3-bucket-name/*",
                "arn:aws:s3:::s3-bucket-name"
            ],
            "Condition": {
                "StringEquals": {
                    "s3:x-amz-acl": "bucket-owner-full-control"
                }
            }
        },
        {
            "Effect": "Allow",
            "Principal": {
                "Service": "logs.ap-northeast-1.amazonaws.com"
            },
            "Action": "s3:GetBucketAcl",
            "Resource": "arn:aws:s3:::s3-bucket-name"
        },
        {
            "Effect": "Allow",
            "Principal": {
                "Service": "logs.ap-northeast-1.amazonaws.com"
            },
            "Action": "s3:PutObject",
            "Resource": "arn:aws:s3:::s3-bucket-name/*",
            "Condition": {
                "StringEquals": {
                    "s3:x-amz-acl": "bucket-owner-full-control"
                }
            }
        }
    ]
}

 

  • 再度、アカウント:A のコンソールからCloudWatch Logsを開き、ログをエクスポートします。

 

  • 最後に、アカウント:B のS3 コンソールから、エクスポートされたオブジェクトが書き込みされたことを確認します。
  • 以下の通り、オブジェクトの所有者は、バケット所有者であるアカウント:B に変わりました。

 

 

参考記事

  • 以下は、Amazon S3 Update がアナウンスされたAWS News Blogです。

  • 以下は、Amazon S3 Developer Guide の説明となります。

AWS,IAM_Policy関連,S3

Posted by takaaki