ablog

不器用で落着きのない技術者のメモ

クロスアカウントでS3マルチパートアップロードすると "when calling the UploadPartCopy operation: Access Denied" と怒られる

事象

KMS CMK でデフォルト暗号化しているS3バケットにクロスアカウントのS3バケット間コピーでマルチパートアップロードが失敗するがマルチパートでない場合は成功する。AWS CLIaws s3 cp/sync など)はデフォルトで 8MB 以上だとマルチパートアップロードする

  • マルチパートアップロードでない場合は成功する。
$ dd if=/dev/urandom of=1mb.dat bs=1M count=1
$ aws s3 cp 1mb.dat s3://cp-src/
$ aws s3 cp s3://cp-src/1mb.dat s3://cp-dst/
copy: s3://cp-src/1mb.dat to s3://cp-dst/1mb.dat   
  • マルチパートアップロードは失敗する。
$ dd if=/dev/urandom of=1gb.dat bs=1M count=1024
$ aws s3 cp 1gb.dat s3://cp-src/
$ aws s3 cp s3://cp-src/1gb.dat s3://cp-dst/
copy failed: s3://cp-src/1gb.dat to s3://cp-dst/1gb.dat
An error occurred (AccessDenied) when calling the UploadPartCopy operation: Access Denied

解決策

  • コピー先アカウントのキーポリシーとコピー元のIAMポリシーに kms:Decrypt を付与する。

設定例

以下は設定例、最小権限となっている。

前提
  • コピー元アカウント「123456789012」からコピー先アカウント「9876543210987」にS3バケット間コピーする。
  • クロスアカウントアクセス許可は S3 バケットポリシーで行う(AssumeRoleではない)。
  • コピー先S3バケットは KMS CMK で暗号化している。
  • コピー元アカウント「123456789012」の EC2 で AWS CLIaws s3 cp コマンドでコピーを行う。
コピー元アカウント

以下のIAMポリシーをIAMロールにアタッチ、そのIAMロールを AWS CLI を実行する EC2 にアタッチする。

  • IAMポリシー(S3の権限)
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "S3 permission to allow multi part upload",
            "Effect": "Allow",
            "Action": [
                "s3:PutObject",
                "s3:GetObject"
            ],
            "Resource": "*"
        }
    ]
}
  • IAMポリシー(KMSの権限)
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "KMS permission to allow multi part upload",
            "Effect": "Allow",
            "Action": [
                "kms:Encrypt",
                "kms:Decrypt",
                "kms:ReEncrypt*",
                "kms:GenerateDataKey*",
                "kms:DescribeKey"
            ],
            "Resource": "*"
        }
    ]
}
コピー先アカウント
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "Allow multi part upload from account 9876543210987",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::123456789012:role/EC2Role"
            },
            "Action": [
                "s3:PutObject"
            ],
            "Resource": [
                "arn:aws:s3:::cp-dst",
                "arn:aws:s3:::cp-dst/*"
            ]
        }
    ]
}
  • KMS CMK のキーポリシー
{
    "Version": "2012-10-17",
    "Id": "key-consolepolicy-3",
    "Statement": [
        {
            "Sid": "Enable IAM User Permissions",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::9876543210987:root"
            },
            "Action": "kms:*",
            "Resource": "*"
        },
        {
            "Sid": "Enable IAM User Permissions",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::123456789012:role/EC2Role"
            },
            "Action": [
                "kms:Encrypt",
                "kms:Decrypt",
                "kms:ReEncrypt*",
                "kms:GenerateDataKey*",
                "kms:DescribeKey"
            ],
            "Resource": "*"
        }
    ]
}

参考

問題
大容量ファイルを Amazon Simple Storage Service (Amazon S3) バケットにアップロードしようとしています。アップロードのリクエストは、AWS Key Management Service (AWS KMS) キーを使用した暗号化情報を含めています。しかし、「Access Denied (アクセス拒否)」エラーが発生します。一方で、暗号化情報を含む小さいファイルをアップロードすると、アップロードは成功します。どうすれば修正できますか?

(中略)

解決方法
AWS Identity and Access Management (IAM) ユーザーまたはロールが AWS KMS キーと同じ AWS アカウントにある場合は、キーポリシーで kms:Decrypt を実行するアクセス許可が必要です。IAM ユーザーまたはロールがキーとは異なるアカウントに属している場合は、キーポリシーと IAM アクセス許可の両方に対して、kms:Decrypt へのアクセス許可が必要です。

AWS KMS キーを使用した暗号化で、大容量ファイルを S3 にアップロードする

"PutObject オペレーションを呼び出すときにエラー (AccessDenied) が発生しました: アクセスが拒否されました"
kms:GenerateDataKey アクションにアクセス権限を追加します。このアクセス権限は、カスタム AWS KMS キーによるデフォルトの暗号化を使用するバケットで必要です。
"CreateMultipartUpload オペレーションを呼び出すときにエラー (AccessDenied) が発生しました: アクセスが拒否されました"
kms:GenerateDataKey および kms:Decrypt アクションにアクセス権限を追加します。これらのアクセス権限は、AWS KMS のデフォルトの暗号化を使用したバケットへのマルチパートアップロードで必要です。

KMS 暗号化を使用した S3 バケットからの「アクセス拒否」エラーを解決する