Я тестирую, чтобы создать предварительно подписанный URL для загрузки файлов на S3.У меня нет проблем с созданием подписанного URL-адреса, но я получаю ошибку AccessDenied при попытке загрузить его.
Я суммировал мою проблему в следующем коде для тестирования.
Исходный код
import boto3
import os
s3 = boto3.client('s3')
def list_files():
print("Listing files in bucket:")
bucket = boto3.resource('s3').Bucket(bucket_name)
for obj in bucket.objects.all():
print(" - "+obj.key)
bucket_name = "asf-bucket"
list_files()
key= "test.py"
print (" Generating pre-signed url...")
url=s3.generate_presigned_url('put_object', Params={'Bucket':bucket_name, 'Key':key}, ExpiresIn=3600, HttpMethod='PUT')
command="curl --request PUT --upload-file {} {}".format(key, url)
print(command)
print (" Uploading with curl ...")
os.system(command)
Вывод сценария
$ python3 test.py
Listing files in bucket:
- Dropped text.txt
Generating pre-signed url...
curl --request PUT --upload-file test.py https://asf-bucket.s3.amazonaws.com/test.py?AWSAccessKeyId=----&Signature=----&Expires=----
Uploading with curl ...
<?xml version="1.0" encoding="UTF-8"?>
<Error><Code>AccessDenied</Code><Message>Access Denied</Message><RequestId>A0E4587FFEB9F1EE</RequestId><HostId>kvfkV7YdDmtNNCSfWAjDTdZ/8+y2HrfcXSseQPlrq0300vjg9zYe1H0Qidsqf7kcBIieUGoXoUA=</HostId></Error>
Протестировано с учетной записью root AWS.Я получаю ту же ошибку.
Конфигурация CORS
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<CORSRule>
<AllowedOrigin>*</AllowedOrigin>
<AllowedMethod>GET</AllowedMethod>
<AllowedMethod>POST</AllowedMethod>
<AllowedMethod>PUT</AllowedMethod>
<AllowedMethod>DELETE</AllowedMethod>
<AllowedHeader>*</AllowedHeader>
</CORSRule>
</CORSConfiguration>
Чего мне не хватает?
https://docs.aws.amazon.com/AmazonS3/latest/dev/PresignedUrlUploadObject.html
Обновление - добавление типа контента
Следуя совету @kichik, я добавил тип контента без изменений в текущем поведении
url=s3.generate_presigned_url('put_object', Params={'Bucket':bucket_name, 'Key':key, 'ContentType':'text/plain'}, ExpiresIn=3600, HttpMethod='PUT')
command="curl --header \"Content-Type: text/plain\" --request PUT --upload-file {} {}".format(key, url)