S3跨账号上传触发Lambda失败:GetObject权限问题排查
跨账号S3触发Lambda时GetObject权限拒绝问题
场景概述
账号A内有一个Lambda函数,会在指定S3桶上传文件时触发,功能为将PDF转换为DataFrame并写入另一个S3桶。目前允许账号B的Administrator IAM用户跨账号上传文件触发该Lambda,但Lambda执行GetObject操作时出现权限拒绝错误。账号A内部上传文件时流程正常,仅跨账号上传时出现问题。
相关代码与报错
Lambda代码
LOGGER = logging.getLogger(__name__) logging.basicConfig(level=logging.ERROR) logging.getLogger(__name__).setLevel(logging.DEBUG) session = boto3.Session( aws_access_key_id="XXXX", aws_secret_access_key="XXXX", ) s3 = session.resource('s3') dest_bucket = 'bucket-output' csv_buffer = StringIO() def lambda_handler(event,context): source_bucket = event['Records'][0]['s3']['bucket']['name'] pdf_name = event['Records'][0]['s3']['object']['key'] LOGGER.info('Reading {} from {}'.format(pdf_name, source_bucket)) pdf_obj = s3.Object(source_bucket,pdf_name) fs = pdf_obj.get()['Body'].read() #### code is failing here df = convert_bytes_to_df(BytesIO(fs)) df.to_csv(csv_buffer,index=False) s3.Object(dest_bucket,str(pdf_name.split('.')[0])+".csv").put(Body=csv_buffer.getvalue()) LOGGER.info('Successfully converted {} from {} to {}'.format(pdf_name,source_bucket,dest_bucket))
报错信息
ClientError: An error occurred (AccessDenied) when calling the GetObject operation: Access Denied
已配置的权限策略
账号A的S3桶策略(Terraform)
resource "aws_s3_bucket_policy" "cross_account_input_access" { bucket = aws_s3_bucket.statements_input.id policy = <<EOF { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam::XXXXXXXXX:user/Administrator" }, "Action": [ "s3:ListBucket" ], "Resource": [ "arn:aws:s3:::capsphere-input" ] }, { "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam::XXXXXXXXX:user/Administrator" }, "Action": [ "s3:PutObject", "s3:GetObject", "s3:DeleteObject" ], "Resource": [ "arn:aws:s3:::bucket-name", "arn:aws:s3:::bucket-name/*" ] } ] } EOF }
账号B的Administrator用户IAM策略
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "s3:ListBucket" ], "Resource": [ "arn:aws:s3:::bucket-name" ] }, { "Effect": "Allow", "Action": [ "s3:PutObject", "s3:GetObject", "s3:DeleteObject" ], "Resource": [ "arn:aws:s3:::bucket-name", "arn:aws:s3:::bucket-name/*" ] } ] }
跨账号上传命令
aws s3 cp filename.pdf s3://bucket-name
解决方案
- 修复桶策略资源ARN不一致问题:账号A的桶策略中第一个Statement的Resource是
arn:aws:s3:::capsphere-input,第二个Statement用的是bucket-name,需统一为实际输入桶名称(如capsphere-input),避免资源匹配错误。 - 配置S3桶对象所有权:将账号A的目标S3桶对象所有权设置为
Bucket owner preferred,这样账号B用户上传的对象会自动归账号A所有,避免因对象归属导致的权限拒绝。 - 为Lambda使用的身份添加GetObject权限:Lambda中硬编码密钥对应的账号A用户需要明确拥有目标桶的
s3:GetObject权限,可在该用户的IAM策略中添加对应规则,同时在账号A的桶策略中补充允许该用户访问桶内对象的Statement:{ "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam::账号AID:user/硬编码密钥对应的用户名" }, "Action": "s3:GetObject", "Resource": "arn:aws:s3:::capsphere-input/*" }
内容的提问来源于stack exchange,提问作者clattenburg cake
相关产品推荐
相关产品推荐

