自分のAWSアカウント内のS3から、別アカウントのS3へファイルをコピーする機会があったので方法を残しておく。
今回は送信元アカウントのIAMユーザーに対して、送信先アカウントで権限を付与してもらい、このIAMユーザーを使ってファイルをコピーする方法を取った。
内容としてはこちらの記事にも詳しく説明されている:
準備
まず、送信先のアカウントの管理者から、送信先のバケット名、バケット内のどのPrefixにファイルをコピーするのかを確認しておく。ここでは仮に
- 送信先バケット名:
bucket-to
- 送信先Prefix:
copy/to/here/
とする。
*実務的には、1回限りの連携と思っても、実際には何度かデータ再送信することもある。なのでPrefixは適宜ネームスペースを切っておくと良い。例えば、copy/here/${送信日}/${ファイルバージョン名}/
みたいに。
送信元については、
- 送信元バケット名:
bucket-from
- 送信元Prefix:
copy/from/here
(ココにコピーしたいファイルを置いている)
とする。
送信元: IAMユーザー作成と権限付与
次に、ファイルを送信するためのIAMユーザーを作成する。
適当な名称でIAMユーザーを払い出し、以下のPolicyをアタッチする。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": ["s3:ListBucket", "s3:GetObject", "s3:GetObjectTagging"],
"Resource": [
"arn:aws:s3:::bucket-from",
"arn:aws:s3:::bucket-from/copy/from/here/*"
]
},
{
"Effect": "Allow",
"Action": ["s3:ListBucket", "s3:PutObject", "s3:PutObjectAcl"],
"Resource": [
"arn:aws:s3:::bucket-to",
"arn:aws:s3:::bucket-to/copy/to/here/*"
]
}
]
}
ここで、参考記事にも記載されているが、s3:GetObjectTagging
については、送信元のS3バケットでバージョニングを有効化している場合は必要となる。その他、権限でエラーが出た場合の対応についても参考記事に詳しく載っている。
発行したらIAMユーザーのARNを送信先アカウントの管理者に連携する。
ARNはこのような形式になるはず: arn:aws:iam::123456789:user/copy-user
送信先: バケットの権限設定
送信先のバケットのS3 Object OwnerShipをbucket owner prefferedに設定する。
これでbucket-owner-full-control
オプション付きでUploadされたオブジェクトは、送信先アカウントの所有となる。
次に、送信先バケットのバケットポリシーを設定する。
{
"Version": "2012-10-17",
"Id": "Policy123456789",
"Statement": [
{
"Sid": "Stmt123456789",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::123456789:user/copy-user"
},
"Action": "s3:PutObject",
"Resource": "arn:aws:s3:::bucket-to/*",
"Condition": {
"StringEquals": {
"s3:x-amz-acl": "bucket-owner-full-control"
}
}
},
{
"Sid": "Stmt123456789",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::123456789:user/copy-user"
},
"Action": "s3:ListBucket",
"Resource": "arn:aws:s3:::bucket-to"
}
]
}
ここでも、先ほどのアカウントと同様、ObjectTaggingなど必要な権限は環境によって異なる可能性があるので、適宜修正する。
送信元: ファイル送信
以上で設定は完了したので、ファイルを送信できる。
自分のケースではショットでの対応だったので、作業PCからaws cliを叩いて実行した。適宜キーを発行してaws cliでの認証を通しておく。今回は--profile copy-user
に設定したものとする。
まずは実行前に--dryrun
を使ってコマンドを確認するのがおすすめ。
aws s3 cp --dryrun \\
--profile copy-user \\
--recursive \\
--expected-size 107374182400 \\
--acl bucket-owner-full-control \\
s3://bucket-from/copy/from/here/ s3://bucket-to/copy/to/here/
ここで、
--expected-size 107374182400
は50GiB以上の大きなファイルをコピー際に必要なオプション(参考)--acl bucket-owner-full-control
は前述の通りコピーしたオブジェクトのOwnerを送信先アカウントとするために必要なオプション
dryrun結果に問題がなければ、--dryrun
オプションを消して実行する。
データ量が多い場合は、かなり時間がかかることもあるので、作業PC上で実行する際はtmuxを活用すると、PCがスリープしてもバックグランドで実行を継続してくれる。
tmux new -s s3-operation
自分の場合は、tmuxで実行したが、社内VPNが途中で切れてしまってErrorになってしまった。可能であればVPNは最初から切っておくのが良さそうだ。
送信が完了したら、最後に念の為、ファイル数とサイズが一致するか確認しておくと良いだろう。
# ファイル数の一致確認
aws s3 ls --profile copy-user --recursive s3://bucket-from/copy/from/here/ | wc -l
aws s3 ls --profile copy-user --recursive s3://bucket-to/copy/to/here/ | wc -l
# ファイルサイズの一致確認
aws s3 ls --profile copy-user --recursive --summarize s3://bucket-from/copy/from/here/ | grep "Total Size"
aws s3 ls --profile copy-user --recursive --summarize s3://bucket-to/copy/to/here/ | grep "Total Size"
上記結果がそれぞれ一致していれば、ミスなくコピーできているはずだ。