![](/img/trans.png)
[英]"An error occurred (AccessDenied) when calling the ListObjectsV2 operation: Access Denied" when using batch jobs
[英]An error occurred (AccessDenied) when calling the PutObject operation: Access Denied but works on my system
我坚持尝试使用我的 flask 应用程序中的 boto3 库将图像上传到 aws s3,该应用程序运行在 ec2 实例上,实例角色附加了以下 s3 策略:
{
"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:::*/*"
]
}
]
}
这在我的计算机上有效,但在上传到 ec2 实例上运行的 flask 应用程序时失败。 我收到以下错误:
An error occurred (AccessDenied) when calling the PutObject operation: Access Denied
这是用于执行此上传的 flask 代码:
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
s3:PutObjectACL
并以正确的方式列出桶。 但是,python的实现有点问题。 AWS python SDK 提供了两个接口:一个client和一个resource 。
客户端接口非常接近 API,如果操作返回一个,您会收到一个 json 作为响应。
资源接口是 pythonic 的,它是更高级别的并返回一个你可以使用的 object。
在上面的代码中,您从 Session 启动资源
res = session.resource(
service_name='s3',
region_name='eu-west-2'
)
但是,在尝试上传时,语法使用的是客户端语法而不是资源语法。 如果你想使用客户端的put_object方法,那么你应该从session发起一个客户端。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.