#heroku #amazon-s3 #boto3
#heroku #amazon-s3 #boto3
Вопрос:
Я пытаюсь выполнить загрузку с Heroku
S3
помощью boto3
, но продолжаю получать сообщение об ошибке <Error><Code>SignatureDoesNotMatch</Code><Message>The request signature we calculated does not match the signature you provided. Check your key and signing method.</Message>
. Я пытался использовать a pre-signed post
и a pre-signed url
, но ошибка сохраняется. Учетные данные, которые я предоставляю Heroku для отправки запроса, — это мой корневой AWSAccessKeyId и секретный ключ, поэтому у меня не должно быть проблем с разрешениями. Я могу напрямую загружать файлы в S3 из своей командной строки.
Значения, возвращаемые после создания предварительно подписанного сообщения:
{'fields': {'x-amz-signature': '26eff5417d0d11a25dd294b059a088e2be37a97f14713962f4240c9f4e33febb', 'x-amz-algorithm': 'AWS4-HMAC-SHA256', 'key': u'sound.m4a', 'x-amz-credential': u'<AWSAccessID>/20161011/us-east-1/s3/aws4_request', 'policy': u'eyJjb25kaXRpb25zIjogW3siYnVja2V0IjogImZ1dHVyZWZpbGVzIn0sIHsia2V5IjogInNvdW5kLm00YSJ9LCB7IngtYW16LWFsZ29yaXRobSI6ICJBV1M0LUhNQUMtU0hBMjU2In0sIHsieC1hbXotY3JlZGVudGlhbCI6ICJBS0lBSTdLRktCTkJTNEM0VktKQS8yMDE2MTAxMS91cy1lYXN0LTEvczMvYXdzNF9yZXF1ZXN0In0sIHsieC1hbXotZGF0ZSI6ICIyMDE2MTAxMVQyMDM4NDlaIn1dLCAiZXhwaXJhdGlvbiI6ICIyMDE2LTEwLTExVDIxOjM4OjQ5WiJ9', 'x-amz-date': '20161011T203849Z'}, 'url': u'https://s3.amazonaws.com/bucketname'}
Код, который в настоящее время находится на Heroku:
@api.route('/post_track', methods=['POST'])
@login_required
def post_track():
if request.method == 'POST':
file = request.files['file']
track = Track.upload_fromJSON(request.form.get('share'), request.form.get('title'))
//Postgres entry
conn = get_conn()
with conn.cursor() as cur:
cur.execute('INSERT INTO tracks(user_id, title, share)'
'VALUES (%s, %s, %s) RETURNING id;',
(track.user_id, track.title, track.share))
track_id = cur.fetchone()[0]
conn.commit()
//Obtain pre-signed request
signed_request = get_signed_request(track.title, request.form.get('type'), track_id, file)
return json.dumps({'response':signed_request})
def get_signed_request(title, type, track_id, file):
S3_BUCKET = os.environ.get('S3_BUCKET')
file_name = title
file_type = type
region = 'us-east-1'
s3 = boto3.client('s3', region_name=region, config=Config(signature_version='s3v4'))
presigned_post = s3.generate_presigned_post(
Bucket = S3_BUCKET,
Key = file_name
)
files = {'file': file}
r_response = requests.post(presigned_post["url"], data=presigned_post["fields"], files=files)
print(r_response)
print(r_response.text)
В конечном итоге я собираюсь настроить код для возврата предварительно подписанного запроса в мой интерфейс и прямой загрузки оттуда. Просто делаю это в качестве тестового запуска.
Ответ №1:
Мне действительно было трудно с этим. Я обратился в службу поддержки S3, и они сказали, что запрос, который они получали, выглядел хорошо и что, должно быть, что-то не так с тем, как подпись генерируется в Heroku. Я обратился к Heroku, и они на самом деле не ответили. Что решило проблему, так это удаление моего корневого доступа AWS и создание нового, а затем перенастройка heroku с новыми идентификаторами доступа. Супер просто, но очень странно, что это была проблема. Надеюсь, это поможет кому-то справиться с той же проблемой.
Комментарии:
1. Вы получили ключи из csv, загруженного с консоли? В конце этого файла нет пустой строки, что приводит к тому, что некоторые инструменты (например,
cat
) отображают a%
, чтобы указать это. Если вы скопировали дополнительный символ, это не сработало бы. Кроме того, не рекомендуется использовать учетные данные учетной записи root. Рекомендуется использовать пользователей и роли даже для одного пользователя.2. @JordonPhillips хотел запустить его с помощью root, чтобы убедиться, что ошибки не связаны с какими-либо проблемами с разрешениями. Я в замешательстве — csv, на который я смотрю, находится в
AWSAccessKeyID
одной строке иAWSSecretKey
в строке ниже. Вы хотите сказать, что в конце каждого ключа должен быть пустой символ, например_