事象
IAMユーザー単位で閲覧/保存制御をかけているS3バケットが本番用とstg用で2つあります。
日時で本番からstg用にsyncをかけるのですが、
An error occurred (AccessDenied) when calling the CopyObject operation
のエラーが出ました。
対処
https://aws.amazon.com/jp/premiumsupport/knowledge-center/s3-troubleshoot-copy-between-buckets/
AWS公式をみてみると、ズバリ書いてありました。
必要なことは4つです。
1. コピー元バケット: 使用している IAM ユーザーまたはロールによって s3:ListBucket と s3:GetObject の両方を許可
2. コピー先バケット: IAM ユーザーまたはロールによって s3:ListBucket と s3:PutObject の両方を許可
3. IAM ユーザー: s3:ListBucket および s3:GetObject をコピー元バケットへ許可
4. IAM ユーザー: s3:ListBucket と s3:PutObject をコピー先バケットへ許可
私の場合、IAMロールはs3への全権限が与えられていたので、バケットポリシーだけを見直しました。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "huge",
"Effect": "Deny",
"NotPrincipal": {
"AWS": "hogehoge"
},
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::hogebucket-production/*"
}
]
}
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "huge",
"Effect": "Deny",
"NotPrincipal": {
"AWS": "hogehoge"
},
"Action": "s3:PutObject",
"Resource": "arn:aws:s3:::hogebucket-staging/*"
}
]
}
なぜだかわからないですが、s3:ListBucket
はなくてもあってもいけたので消しました。
ちなみにs3:ListBucket
権限を付与するのにはまた罠があり、Resourceを指定する時に/*
をつけてはいけません。
考えてみればバケット単位の権限なのでまあそうかという感じなのですが、普通にハマりました。
間違えると、action does not apply to any resource(s) in statement
というエラーが出てバケットを保存できません。
下記のように書いてみてください。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:ListBucket"
],
"Resource": [
"arn:aws:s3:::bucketname",
]
}
]
}
実行
コピー元 コピー先の順で指定します。
フォルダ指定もできます。
aws s3 sync s3://hogebucket-production/uploads/huga s3://hogebucket-staging/uploads/huga
余談
バケットポリシーの書き方は初めは難しいですよね。
EffectとPrincipalの組み合わせとか。
"Version": "2012-10-17" てなんやとか。