如何使用Lambda在S3同存储桶不同前缀间复制文件并解决AccessDenied报错
S3触发Lambda执行CopyObject操作报AccessDenied错误的解决记录
问题背景
S3无实际文件夹概念,现有两个前缀路径:abcabc/Pdf和abcabc/BackUpPdf。需求为:客户端上传文件到abcabc/Pdf前缀时,自动触发Lambda将文件复制到abcabc/BackUpPdf路径,使用boto3进行开发。
初始代码及报错
Lambda部分代码如下,变量key存储源文件路径:
def lambda_handler(event, context): print(event) print('Inside the function') # 从事件中获取对象信息 bucket = event['Records'][0]['s3']['bucket']['name'] key = urllib.parse.unquote_plus(event['Records'][0]['s3']['object']['key'], encoding='utf-8') print('Bucket: ' + bucket + ', Key: ' + key) client.Object(bucket, 'abcabc/BackUpPdf/TestFile.pdf').copy_from(CopySource = key, ACL='public-read')
运行时报错:ClientError: An error occurred (AccessDenied) when calling the CopyObject operation: Access Denied
排查过程
- 首先排查IAM角色权限,给Lambda执行角色授予
S3FullAccess权限后,报错仍然存在 - 尝试修改存储桶策略为公开权限,策略内容如下:
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": "*", "Action": [ "s3:GetObject", "s3:GetObjectTagging", "s3:PutObject", "s3:PutObjectTagging" ], "Resource": "arn:aws:s3:::bucket-name/*" }, { "Effect": "Allow", "Principal": "*", "Action": "s3:ListBucket", "Resource": "arn:aws:s3:::bucket-name" } ] }
因该S3存储桶已开启「全部阻止公共访问」配置,上述策略修改未生效。
问题根因及解决方案
错误根因为copy_from方法的CopySource参数格式不符合要求:boto3要求该参数需要同时指定源桶名和对象key,仅传入key无法定位源对象,平台会返回无权限的模糊报错。
修改后可正常运行的代码如下:
client.Object(bucket, 'abcabc/BackUpPdf/TestFile.pdf').copy_from(CopySource = bucket + '/' + key)
注:同时移除了原代码中ACL='public-read'参数,避免与存储桶的公共访问阻止配置冲突
内容的提问来源于stack exchange,提问作者Carlos Quiñones
相关产品推荐
相关产品推荐

