EC2实例中Flask应用调用S3 PutObject时出现AccessDenied权限问题
EC2上Flask应用使用boto3上传S3报AccessDenied问题
在EC2实例运行的Flask应用中,使用boto3向AWS S3上传图片时触发AccessDenied错误,但本地运行完全正常。已为EC2实例角色附加了S3相关权限策略,具体信息如下:
已附加的IAM实例角色策略
{ "Version": "2012-10-17", "Statement": [ { "Sid": "VisualEditor0", "Effect": "Allow", "Action": [ "s3:GetBucketTagging", "s3:ListBucket", "s3:GetBucketAcl", "s3:GetBucketPolicy", "s3:PutObject", "s3:GetObjectAcl", "s3:GetObject", "s3:PutObjectVersionAcl", "s3:GetObjectVersionAcl", "s3:PutBucketAcl", "s3:PutBucketPolicy", "s3:DeleteObject", "s3:GetBucketLocation", "s3:PutObjectAcl", "s3:AbortMultipartUpload", "s3:ListBucketMultipartUploads", "s3:AbortMultipartUpload", "s3:ListMultipartUploadParts" ], "Resource": [ "arn:aws:s3:::bucket-name", "arn:aws:s3:::bucket-name/*", "arn:aws:s3:::bucket-name/users/*", "arn:aws:s3:::*/*" ] } ] }
报错信息
An error occurred (AccessDenied) when calling the PutObject operation: Access Denied
上传用Flask代码
from flask import current_app from werkzeug.datastructures import FileStorage import boto3 class S3ImageBucketManagement: S3_LOCATION = 'http://{}.s3.amazonaws.com/'.format('bucket-name') def __init__(self, bucket_name: str, bucket_region: str, _id: str, image_type: str, acl: str = "public-read"): self._client = self.__s3_resource().Bucket(bucket_name) self._image_type = image_type self._bucket_name = bucket_name self._bucket_region = bucket_region self._id = _id self._acl = acl def __s3_resource(self): """ Creates the boto3 client :return: boto3.client """ session = boto3.Session() res = None try: res = session.resource( service_name='s3', region_name='eu-west-2' ) except Exception as e: print(f'Error: {e}') return res def upload_file_to_s3(self, file: FileStorage, upload_folder: str): try: res = self._client res.put_object( Body=file, Bucket=self._bucket_name, Key=f"{self._image_type}/{file.filename}", ACL=self._acl, ContentType=file.content_type, ) # res.upload_file( # Filename=f"/tmp/{file.filename}", # Key=f"{self._image_type}/{file.filename}", # ExtraArgs={ # "ACL": self._acl, # "ContentType": file.content_type # } # ) except Exception as e: current_app.logger.error(f'upload_file_to_s3 function error: {e}') return False, 'File upload failed', 500 return True, "{}{}/{}".format(self.S3_LOCATION, self._image_type, file.filename), 200
排查与解决建议
- 检查S3桶策略:若桶本身配置了拒绝访问的策略,会优先于实例角色的允许权限,导致上传失败。确认桶策略未阻止
PutObject操作,尤其是针对该EC2实例角色的访问。 - 验证实例角色信任关系:确保信任关系文档中包含
ec2.amazonaws.com作为Principal,允许EC2服务承担该角色。 - 确认S3阻止公共访问配置:代码中使用
public-readACL,若桶开启了阻止公共访问的相关选项,设置公共ACL会被拒绝,进而导致PutObject失败。可在S3控制台关闭对应选项,或修改ACL为private等非公共权限。 - 检查EC2实例角色关联状态:在EC2控制台确认实例已正确附加目标IAM角色,也可在实例内执行以下命令验证凭证是否有效:
# 获取角色名称 curl http://169.254.169.254/latest/meta-data/iam/security-credentials/ # 获取临时凭证详情 curl http://169.254.169.254/latest/meta-data/iam/security-credentials/[角色名称] - 排查实例内AWS凭证优先级:若EC2实例环境变量中配置了
AWS_ACCESS_KEY_ID和AWS_SECRET_ACCESS_KEY,会覆盖实例角色凭证,导致使用错误权限执行上传。需确保实例未配置此类环境变量。
内容的提问来源于stack exchange,提问作者George Udosen
相关产品推荐
相关产品推荐

