使用Terraform+AWS S3+Python调用PutObject时遇AccessDenied错误
解决S3 PutObject AccessDenied错误的方案
核心问题排查与修复
1. 修正Python脚本的Body参数错误
你的Python脚本中Body=image传入的是文件名字符串,而非文件二进制内容,这会导致上传请求格式错误,进而触发权限验证失败。需修改为读取文件内容:
import os import boto3 image = "x.jpg" s3_filestore_path = "images/x.jpg" filename, file_extension = os.path.splitext(image) content_type_dict = { ".png": "image/png", ".html": "text/html", ".css": "text/css", ".js": "application/javascript", ".jpg": "image/jpeg", # 修正:.jpg对应的Content-Type应为image/jpeg,原脚本写错为image/png ".gif": "image/gif", ".jpeg": "image/jpeg", } content_type = content_type_dict[file_extension.lower()] # 兼容文件名后缀大小写 # 读取文件二进制内容 with open(image, "rb") as f: image_content = f.read() s3 = boto3.client( "s3", config=boto3.session.Config(signature_version="s3v4"), region_name="eu-west-3", aws_access_key_id="你的访问密钥ID", aws_secret_access_key="你的私有访问密钥", ) s3.put_object( Body=image_content, # 传入文件二进制内容 Bucket="x-rc-bucket", Key=s3_filestore_path, ContentType=content_type )
2. 确认桶加密配置兼容性
Terraform配置中开启了allow_encrypted_uploads_only = true和桶默认SSE加密(sse_algorithm = "AES256")。默认情况下S3会自动使用桶的加密配置,但如果仍有问题,可显式指定加密参数:
s3.put_object( Body=image_content, Bucket="x-rc-bucket", Key=s3_filestore_path, ContentType=content_type, ServerSideEncryption='AES256' # 显式指定服务器端加密方式 )
3. 验证IAM权限与密钥正确性
- 检查Secrets Manager中存储的
KEY和SECRET是否与生成的IAM用户完全匹配,避免复制时出现字符遗漏、多空格等错误。 - 登录AWS控制台,进入IAM用户页面,确认CloudPosse模块生成的权限策略已正确附加到目标用户。
- IAM权限存在1-5分钟的生效延迟,若刚创建完资源,等待几分钟后重试。
4. 排除CORS干扰(非直接原因)
你的CORS配置已允许PUT方法,当前AccessDenied错误与CORS无关,但若后续出现跨域问题可参考现有配置调整。
内容的提问来源于stack exchange,提问作者Muhammad Taqi
相关产品推荐
相关产品推荐

