#amazon-web-services #amazon-s3 #aws-sdk #pre-signed-url #aws-sdk-js
#amazon-web-services #amazon-s3 #aws-sdk #предварительно подписанный URL #aws-sdk-js
Вопрос:
Мне нужно создать подписанный URL для загрузки файла в корзину s3. Ключом файла s3 должен быть его sha256
хэш.
Тогда возникает вопрос: как я могу убедиться, что клиент отправляет действительный хэш? Я создаю подписанный URL в своей лямбда-функции и избегаю передачи файла через него, поэтому лямбда, конечно, не может вычислить хэш.
Я думаю, что смогу добиться этого, используя 2 шага:
-
Заставьте клиента отправить его вычисленный
sha256
при загрузке. Исходя из спецификации, я предполагаю, что это будет автоматически проверяться при предоставлении его вx-amz-content-sha256
заголовке. -
Заставьте клиента отправлять тот же хэш в лямбда, чтобы я мог заставить его быть ключом.
Сначала я попробовал это:
s3.getSignedUrl('putObject', { Key: userProvidedSha256 }, callback)
Я попытался добавить условие, подобное { header: { 'X-Amz-Content-Sha256': userProvidedSha256 } }
.
Но я не нашел способа добавить такое определение, чтобы оно фактически заставляло клиента отправлять X-Amz-Content-Sha256
заголовок.
Кроме того, я бы использовал тот же подход для обеспечения соблюдения фиксированного требуемого Content-Length
заголовка (клиент отправляет желаемую длину на серверную часть, там мы его подписываем), но не уверен, что это сработает из-за этой проблемы.
Поскольку я обнаружил, что s3.createPresignedPost
это также позволяет мне ограничить максимальный размер вложения и выглядит более гибким, я пошел по этому пути:
const signPostFile = () => {
const params = {
Fields: {
key: userProvidedSha256
},
Expires: 86400,
Conditions: [
['content-length-range', 0, 10000000],
{ 'X-Amz-Content-Sha256': userProvidedSha256]
]
}
s3.createPresignedPost(params, callback)
}
Но пока это работает (это заставляет клиента отправлять принудительный заголовок sha256, и заголовок передается, см. Журнал запросов ниже), похоже, что теперь клиенту нужно добавить x-amz-content-sha256
в поля формы, а не в заголовок. Похоже, что это так, как задумано, но очевидно, что s3 не будет проверять отправленный файл на соответствие предоставленному sha256: любой файл, который я добавляю в форму, успешно загружен, даже если sha256 не соответствует.
Есть предложения, что не так, или как еще я могу обеспечить выполнение условия sha256, одновременно ограничивая длину содержимого?
Обновление: я использую signature v4, и я попробовал политику S3 Deny
для этого условия:
Condition:
StringEquals:
s3:x-amz-content-sha256: UNSIGNED-PAYLOAD
Соответствующий журнал запросов для отправки файла, содержащего строку «hello world»:
----------------------------986452911605138616518063
Content-Disposition: form-data; name="X-Amz-Content-Sha256"
b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9
----------------------------986452911605138616518063
Content-Disposition: form-data; name="key"
b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9
Комментарии:
1. Как вы в конечном итоге справились с этим? В настоящее время пытаюсь сделать то же самое. Также сделал запрос на форуме для этой функции здесь .
Ответ №1:
Насколько мне известно, S3 не предоставляет sha256 по умолчанию. Однако, прослушивая события S3, вы можете реализовать функцию Lambda, которая делает это автоматически для вас. Вот предложение, которое приходит на ум:
- Клиент запрашивает подписанный S3 URL на основе предоставленного пользователем sha256
- Клиент загружает файл, используя подписанный URL
- Функция Lambda настроена для прослушивания
s3:ObjectCreated:*
событий из корзины загрузки - Когда загрузка завершена, функция Lambda запускается событием сообщения S3. Частью события является ключ объекта S3
- Функция Lambda загружает загруженный файл и повторно вычисляет sha256
- Функция Lambda удаляет файл, если вычисленное значение sha256 отличается от значения sha256, которое было предоставлено клиентом (либо в качестве ключа объекта, либо доступно из метаданных объектов)
В качестве альтернативы, если основной целью является проверка целостности загруженных файлов, S3 предоставляет другой вариант использования sha256 при вычислении контрольных сумм.
- Настройте политику корзины, чтобы принимать только запросы, которые были подписаны
-
Настройте клиентский AWS S3 sdk для использования AWS signature версии 4, например
const s3 = new AWS.S3({apiVersion: '2006-03-01', signatureVersion: 'v4'});
-
Функция S3.putObject() подпишет запрос перед загрузкой файла
S3 не сохранит объект, если подпись неправильная, как описано в часто задаваемых вопросах AWS CLI S3
Комментарии:
1. Подход 1: это может сработать, но разве это не соответствует цели подписанных URL-адресов, что файлы не должны проходить через лямбда? В противном случае я мог бы напрямую отправлять файлы в lambda, а проверка выполняется централизованно?
2. Подход 2: мне трудно это понять. Я обновил вопрос (подпись, политика) и упростил здесь