跨账号S3对象复制调用CopyObject遇权限拒绝(IAM STS扮演)
跨账号S3复制CopyObject报AccessDenied错误排查与解决方案
问题背景
通过Account-B的Lambda函数关联Role-B,扮演Account-A的Role-A执行跨账号S3对象复制时,调用CopyObject操作触发AccessDenied错误,但已成功AssumeRole并能访问Bucket-A及其对象。
环境配置
Account-A侧
Bucket-A:无桶级别策略- IAM角色
Role-A:
内联权限策略:
信任关系(允许Account-B的Role-B调用AssumeRole):{ "Version": "2012-10-17", "Statement": [ { "Sid": "VisualEditor0", "Effect": "Allow", "Action": [ "kms:Decrypt", "kms:GenerateDataKey" ], "Resource": "*" }, { "Sid": "VisualEditor1", "Effect": "Allow", "Action": [ "s3:GetObject", "s3:GetObjectVersion", "s3:GetObjectAcl", "s3:CopyObject", "s3:HeadObject", "s3:GetObjectTagging", "s3:PutObjectTagging" ], "Resource": "arn:aws:s3:::Bucket-A/*" }, { "Sid": "VisualEditor2", "Effect": "Allow", "Action": [ "s3:ListBucket", "s3:ListAllMyBuckets", "s3:GetBucketAcl", "s3:GetBucketLocation" ], "Resource": "arn:aws:s3:::Bucket-A" } ] }{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "AWS": [ "arn:aws:iam::xxxxxxxxxx:role/service-role/Role-B" ] }, "Action": "sts:AssumeRole" } ] }
Account-B侧
Bucket-B:无桶级别策略- Lambda函数
Lambda-B:执行跨账号S3复制的Python函数 - IAM角色
Role-B:
扮演Role-A的权限策略:
附加权限:{ "Version": "2012-10-17", "Statement": [ { "Action": [ "iam:PassRole", "iam:GetRole" ], "Resource": "*", "Effect": "Allow" }, { "Action": "sts:AssumeRole", "Resource": "arn:aws:iam:: xxxxxxxxxx:role/Role-A", "Effect": "Allow" } ] }Encrypt and Decrypt KMS - of KMS-A and KMS-B (tried adding both accounts KMS IDs too) AmazonSSMFullAccess AWSLambdaVPCAccessExecutionRole AmazonRedshiftFullAccess AmazonS3FullAccess
错误日志
[ERROR] ClientError: An error occurred (AccessDenied) when calling the CopyObject operation: Access Denied Traceback (most recent call last): File "/var/task/lambda_function.py", line 136, in lambda_handler s3_resource.meta.client.copy(copy_source, TARGET_BUCKET, SOURCE_PATH) File "/var/runtime/boto3/s3/inject.py", line 380, in copy return future.result() File "/var/runtime/s3transfer/futures.py", line 103, in result return self._coordinator.result() File "/var/runtime/s3transfer/futures.py", line 266, in result raise self._exception File "/var/runtime/s3transfer/tasks.py", line 139, in __call__ return self._execute_main(kwargs) File "/var/runtime/s3transfer/tasks.py", line 162, in _execute_main return_value = self._main(**kwargs) File "/var/runtime/s3transfer/copies.py", line 313, in _main client.copy_object( File "/var/runtime/botocore/client.py", line 391, in _api_call return self._make_api_call(operation_name, kwargs) File "/var/runtime/botocore/client.py", line 719, in _make_api_call raise error_class(parsed_response, operation_name)END RequestId: 80c88cc3-46ee-4707-85d1-6b62b0f3f50d
解决方案
1. 缺失的权限分析
核心问题是执行CopyObject时使用的是Role-A的身份,而Role-A没有写入Account-B的Bucket-B的权限:
- CopyObject操作需要同时拥有源对象的读取权限和目标桶的写入权限。当前Role-A仅配置了Bucket-A的权限,缺少对Bucket-B的
s3:PutObject(或s3:CopyObject)权限。 - 注意:Role-B的
AmazonS3FullAccess权限不会生效,因为复制操作是通过AssumeRole后的Role-A凭证执行的,权限以Role-A为准。 - 另外,Role-B的AssumeRole策略中,Role-A的ARN存在空格(
arn:aws:iam:: xxxxxxxxxx:role/Role-A),虽当前AssumeRole成功,但属于拼写错误,建议修正。
需给Role-A添加以下权限策略:
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "s3:PutObject", "s3:CopyObject" ], "Resource": "arn:aws:s3:::Bucket-B/*" }, { "Effect": "Allow", "Action": "s3:GetBucketLocation", "Resource": "arn:aws:s3:::Bucket-B" } ] }
若Account-B的Bucket-B有桶策略限制,需确保允许Role-A的ARN访问。
2. 该复制方式是否可行
这种方式完全可行,只要修正Role-A的权限配置,确保其同时拥有源桶读取和目标桶写入权限,即可通过AssumeRole后的身份执行跨账号复制。
3. 大文件跨账号复制推荐方案
针对大文件(尤其是超过5GB的对象),推荐以下方案:
- S3批量复制(S3 Batch Operations):无需编写代码,直接通过控制台或API配置批量任务,支持跨账号,可指定IAM角色执行,适合大量文件的一次性复制。
- 分段复制(Multipart Copy):对于大于5GB的文件,必须使用分段复制,boto3的
copy方法会自动处理分段逻辑,但需确保Role-A拥有s3:UploadPartCopy、s3:CompleteMultipartUpload等相关权限。 - S3 Transfer Acceleration:如果跨区域复制,开启目标桶的Transfer Acceleration功能,可提升跨区域传输速度。
- S3跨区域复制(CRR):若需长期同步源桶和目标桶的对象,配置CRR自动同步,无需手动触发,适合持续同步场景。
内容的提问来源于stack exchange,提问作者Bhavesh Bendale
相关产品推荐
相关产品推荐

