Как я могу использовать AWS Cognito для ограничения доступа к файлам S3? - PullRequest
0 голосов
/ 07 ноября 2019

Я создаю веб-приложение, которое должно обслуживать большие файлы из корзины S3 пользователям для загрузки. Пользователь в нашем приложении авторизован Cognito. Я хотел бы иметь корзину S3 с файлами, чтобы некоторые пользователи Cognito могли загружать только определенные файлы. Из моего исследования я нашел несколько способов сделать это. Насколько я могу судить, ни один из них не идеально подходит для моего варианта использования.

AWS допускает, чтобы блоки S3 были разрешены пользователем Cognito. Это так близко к тому, что мне нужно, но на самом деле, к сожалению, не годится для использования. В схеме безопасности нашего приложения логины Cognito принадлежат организации. Каждая организация делится всеми своими данными на сервере. Поэтому мне нужно разрешить всем входам в организацию, определенным моей базой данных, доступ к корзине S3, а не именам пользователей по имени.

Предопределенные URL-адреса кажутся типичным вариантом использования для этого, в некотором смысле, новсе еще не совсем то, что мне нужно, я думаю. Предопределенные URL-адреса дадут мне истекающий URL-адрес, чтобы пользователь мог загрузить файл. Хорошо, так что я могу дать каждому пользователю URL, который может быть пользовательским, но я могу выдать несколько в своем бэкэнде. Но я не хочу, чтобы срок действия URL истек, я бы хотел, чтобы он длился вечно. Это не так уж сложно, поскольку постоянный URL-адрес может быть конечной точкой API, которая перенаправляет на динамически созданный предварительно назначенный URL-адрес, срок действия которого может истечь через одну минуту. Но этот URL позволит получить доступ любому, у кого он есть. Это не соответствует нашей модели безопасности, ограничивающей URL-адреса для пользователей Cognito при входе в систему. Если этот URL-адрес выходит, путем вырезания и вставки пользователем или, возможно, перехватчиком пакетов, кажется, что безопасность нарушается. Конечно, срок действия URL истекает, но он не совсем подходит для этого проекта.

Другой вариант, который я рассмотрел, - это реализовать его в коде самостоятельно, создав конечную точку API, которая создает поток загружаемых файлов, который создается путем доступаобъект S3 также как файловый поток. Он будет читать файл в память и передавать его пользователю. Безопасность для этого, кажется, полностью соответствует нашим потребностям, поскольку конечная точка API, конечно, будет проверять токен пользователя Cognito. Но чтение из корзины S3 в мой бэкэнд, а затем для пользователя - это ненужный сетевой трафик, оно может быть медленнее, а также может потребовать много памяти в бэкэнд-процессе.

Похоже, вырезать посредникаи предоставление пользователю прямого доступа к корзине S3, хотя и с правильными пользовательскими ограничениями разрешений, было бы наилучшим решением. Я просто могу найти любой проект или учебник, который делает это в соответствии с рекомендациями, подходящими для моего проекта. Я думаю, что у моего проекта довольно распространенный вариант использования. Есть ли лучший способ сделать это?

1 Ответ

0 голосов
/ 08 ноября 2019

Один из подходов, которые я видел в приложениях, заключается в том, чтобы просто использовать общедоступную корзину с неосуществимыми именами объектов S3. Например, вы должны сохранить файл пользователей в s3://public-bucket/<secure hash>, а затем в ответе перенаправить их на общедоступный URL-адрес для этого объекта, чтобы теперь пользователь непосредственно загружал из S3. Поскольку S3 не позволяет вам перечислять объекты, это теоретически безопасно, поскольку случайное имя объекта действует как пароль, который нужно знать точно, чтобы получить доступ к файлу. И поскольку весь трафик на S3 идет через SSL, URL никогда не может быть открыт при передаче.

Теперь лично мне это кажется немного странным, потому что в отличие от пароля имя файла видно в истории браузераи, возможно, в других местах, но это, вероятно, не самая плохая вещь в мире, если данные не очень чувствительны.

Одна вещь, которую вы упоминаете, с которой я не согласен:

Другой вариантЯ подумал, что сам реализую это в коде, создав конечную точку API, которая создает скачиваемый файловый поток, который создается путем доступа к объекту S3 также в виде файлового потока. ... Но чтение из корзины S3 в мой бэкэнд и затем к пользователю является ненужным сетевым трафиком, может быть медленнее, а также потенциально требует много памяти в бэкэнд-процессе

Этовероятно, лучшее решение на мой взгляд (иметь веб-сервер в качестве посредника), потому что вы имеете полный контроль над логикой своего приложения и можете спокойно спать, зная, что меньше шансов на махинации и раскрытие данных.

Я очень скептически настроенчто это будет иметь много накладных расходов в вычислительном отношении. Потоковая передача данных с S3 должна быть быстрой и использовать очень мало памяти (вы, вероятно, можете сделать это на t2.micro и все будет хорошо, если у вас нет тонны запросов). Все веб-фреймворки должны позволять вам передавать данные в HTTP-ответе, так что вам вообще не нужно лезть в память. Я построил подобные вещи, и это никогда не было для меня узким местом в производительности.

...