在AWS Lambda中使用smart-open访问S3时出现权限拒绝错误
问题分析与解决方案
核心问题
你遇到的AccessDenied错误主要来自三个方面:
- smart-open参数配置错误:错误地将
CreateMultipartUpload的参数放在client_kwargs中,这不是smart-open指定分片上传参数的正确方式。 - 未实现真正流式传输:使用
response.content会把整个响应加载到内存,既浪费资源,也违背了stream=True的初衷,同时触发smart-open分片上传逻辑时因参数错误导致权限验证失败。 - KMS权限缺失:使用KMS加密上传时,除
s3:PutObject和解密权限,还需要kms:GenerateDataKey权限(用于生成加密文件所需的数据密钥)。
修正后的代码
import boto3 import requests from smart_open import open def download_report(baseURL): bucket = "my-bucket-xyz" s3url = f"s3://{bucket}/reports.txt" # 初始化S3客户端(Lambda中可自动获取角色权限,无需额外配置凭证) s3_client = boto3.client('s3') # 流式获取响应并分块写入S3 with requests.get(baseURL, stream=True) as response: response.raise_for_status() # 提前捕获HTTP请求错误 # 正确配置smart-open的传输参数:用multipart_upload_kwargs指定分片上传的加密设置 with open( s3url, 'wb', # 二进制写入,避免文本编码损坏文件 transport_params={ 'client': s3_client, 'multipart_upload_kwargs': { 'ServerSideEncryption': 'aws:kms' # 若需指定特定KMS密钥,添加'KMSKeyId': 'your-key-arn' } } ) as fout: # 分块读取响应,每次1MB,适配Lambda内存限制 for chunk in response.iter_content(chunk_size=1024*1024): if chunk: fout.write(chunk) return
关键修正点说明
- 参数配置修正:将加密参数从
client_kwargs移到multipart_upload_kwargs中,这是smart-open专门用于配置分片上传选项的参数。 - 流式传输实现:使用
response.iter_content分块读取和写入,避免一次性加载大文件到内存,同时契合smart-open的流式处理逻辑。 - 二进制写入:将打开模式从
'w'改为'wb',避免文本编码导致的非文本文件损坏。 - 请求状态校验:添加
response.raise_for_status(),提前捕获HTTP请求错误,避免后续无意义的上传操作。
权限补充确认
检查Lambda角色的KMS权限策略,确保包含以下权限(使用自定义KMS密钥时):
{ "Effect": "Allow", "Action": [ "kms:GenerateDataKey", "kms:Decrypt" ], "Resource": "arn:aws:kms:your-region:your-account-id:key/your-key-id" }
内容的提问来源于stack exchange,提问作者Jack
相关产品推荐
相关产品推荐

