Bagaimana cara menyimpan data di S3 dan mengizinkan akses pengguna dengan cara yang aman dengan Rails API / klien iOS?

93

Saya baru dalam menulis Rails dan API. Saya butuh bantuan dengan solusi penyimpanan S3. Inilah masalah saya.

Saya menulis API untuk aplikasi iOS di mana pengguna login dengan API Facebook di iOS. Server memvalidasi pengguna terhadap token masalah Facebook kepada pengguna iOS dan mengeluarkan token Sesi sementara. Dari titik ini pengguna perlu mengunduh konten yang disimpan di S3. Konten ini hanya milik pengguna dan sebagian dari teman-temannya. Pengguna ini dapat menambahkan lebih banyak konten ke S3 yang dapat diakses oleh sekelompok orang yang sama. Saya kira ini mirip dengan melampirkan file ke grup Facebook ...

Ada 2 cara pengguna dapat berinteraksi dengan S3 ... serahkan ke server atau minta server untuk menerbitkan token S3 sementara (tidak yakin tentang kemungkinannya di sini) dan pengguna dapat mengakses URL konten langsung ke S3. Saya menemukan pertanyaan ini berbicara tentang pendekatan, namun, ini benar-benar tertanggal (2 tahun yang lalu): Pertanyaan arsitektur dan desain tentang mengunggah foto dari aplikasi iPhone dan S3

Jadi pertanyaannya:

  • Apakah ada cara untuk membatasi pengguna untuk mengakses hanya beberapa konten di S3 saat token sementara dikeluarkan? Bagaimana saya bisa melakukan ini? Asumsikan ada ... katakanlah 100.000 atau lebih pengguna.
  • Apakah sebaiknya membiarkan perangkat iOS menarik konten ini keluar secara langsung?
  • Atau harus membiarkan server mengontrol semua konten yang lewat (ini tentu saja memecahkan keamanan)? Apakah ini berarti saya harus mengunduh semua konten ke server sebelum menyerahkannya kepada pengguna yang terhubung?
  • Jika Anda tahu rel ... dapatkah saya menggunakan penjepit kertas dan permata aws-sdk untuk mencapai pengaturan ini?

Mohon maaf atas banyak pertanyaan dan saya menghargai setiap wawasan tentang masalah ini. Terima kasih :)

makan malam
sumber
1
menemukan ini dan berpikir saya akan komentar orang lain mencari docs.aws.amazon.com/AmazonS3/latest/dev/...
dibble

Jawaban:

113

Dengan menggunakan permata aws-sdk , Anda bisa mendapatkan url bertanda tangan sementara untuk objek S3 apa pun dengan memanggil url_for:

s3 = AWS::S3.new(
  :access_key_id => 1234,
  :secret_access_key => abcd
)
object = s3.buckets['bucket'].objects['path/to/object']
object.url_for(:get, { :expires => 20.minutes.from_now, :secure => true }).to_s

Ini akan memberi Anda URL penggunaan sementara yang ditandatangani hanya untuk objek itu di S3. Kedaluwarsa setelah 20 menit (dalam contoh ini), dan hanya berlaku untuk satu objek itu.

Jika Anda memiliki banyak objek yang dibutuhkan klien, Anda harus menerbitkan banyak URL yang ditandatangani.

Atau harus membiarkan server mengontrol semua konten yang lewat (ini tentu saja memecahkan keamanan)? Apakah ini berarti saya harus mengunduh semua konten ke server sebelum menyerahkannya kepada pengguna yang terhubung?

Perhatikan bahwa ini tidak berarti server perlu mengunduh setiap objek, itu hanya perlu mengautentikasi dan mengotorisasi klien tertentu untuk mengakses objek tertentu di S3.

Dokumen API dari Amazon: https://docs.aws.amazon.com/AmazonS3/latest/dev/RESTAuthentication.html#RESTAuthenticationQueryStringAuth

ejdyksen.dll
sumber
3
Terima kasih untuk @ejdyksen itu. Solusi yang saya buat menggunakan persis seperti itu (saya belum memperbarui pertanyaan dengan jawaban saya)! Jadi solusi saya adalah melakukan URL terotentikasi untuk permintaan GET. Namun, saat pengguna menyumbangkan konten, ia membuat resource ke lokasi / bucket / user / objectname tertentu menggunakan token IAM federasi (kredensial sementara yang kedaluwarsa) dengan kebijakan yang dilampirkan untuk memungkinkan akses tulis / bucket / user / *. jadi tidak ada pengguna di sistem yang dapat merusak konten pengguna lain. Sepertinya bekerja dengan baik. Hargai jawaban Anda.
makan malam
5
Jika Anda menggunakan v2 dari aws-sdk-ruby, perhatikan bahwa metodenya agak berbeda: docs.aws.amazon.com/sdkforruby/api/Aws/S3/…
vijucat
2
Bukankah berisiko bagi pengguna untuk melihat kunci akses saya? Ada juga kunci rahasia (diubah)
user2503775
3
@Dennis intinya adalah bahwa file tersebut tidak harus mengenai server Anda. Tautan tidak berisi kredensial AWS Anda. Ini mungkin berisi ACCESS_KEY_ID(Saya tidak ingat dari atas kepala saya), tapi itu tidak dimaksudkan sebagai rahasia.
ejdyksen
2
@ejdyksen Anda benar, saya baru saja memverifikasi bahwa URL hanya berisi AWS_ACCESS_KEY_ID. Saya awalnya mengira AWS_SECRET_ACCESS_KEYitu juga ditampilkan tetapi ternyata tidak.
Dennis
46

Jawaban di atas menggunakan permata aws-sdk-v1 yang lama daripada yang baru aws-sdk-resources versi 2.

Cara barunya adalah:

aws_resource = Aws::S3::Resource::new
aws_resource.bucket('your_bucket').object('your_object_key').presigned_url(:get, expires_in: 1*20.minutes)

di mana your_object_key adalah jalur ke file Anda. Jika Anda perlu mencarinya, Anda akan menggunakan sesuatu seperti:

s3 = Aws::S3::Client::new
keys = []
s3.list_objects(bucket: 'your_bucket', prefix: 'your_path').contents.each { |e| 
  keys << e.key
}

Informasi itu sangat sulit untuk digali, dan saya hampir menyerah dan menggunakan permata yang lebih tua.

Referensi

http://docs.aws.amazon.com/sdkforruby/api/Aws/S3/Object.html#presigned_url-instance_method

chaqke
sumber
1
expires_inmengharapkan data dalam bentuk detik, pastikan untuk mengonversinya terlebih dahulu.
frillybob
"ArgumentError (diharapkan: expires_in menjadi beberapa detik)"
reedwolf