Rails Activestorage and S3, storing sensitive data

Rails Activestorage and S3, storing sensitive data



ActiveStorage makes possible to upload and access files directly on S3 through the user browser in JS. Does it means that your S3 credentials are embedded into the user browser? I think I misunderstand that, that would make your credentials almost public...



In that case the only thing that prevents anybody to access other users data is the unique token generation. But 24-bytes random key can easily be bruteforced. Should I enforce security by implementing a unique key per user related to its own data?



What would be a good security architecture?




3 Answers
3



A good security architecture and probably this is what's implemented in ActiveStorage is:



1- A page including an upload form is requested.



2- A blob record will be created at the server side and persisted to the database (even before any upload happens). https://github.com/rails/rails/blob/0718c75bc2a7378d30e729a3c1d25ceb99400b7b/activestorage/app/models/active_storage/blob.rb#L70



3- The server call the 3rd party cloud service (AWS S3 for ex.) in the backend and issue a presigned url using the AWS credentials (secret credentials and should not be exposed to public) to be used for upload. https://github.com/rails/rails/blob/master/activestorage/lib/active_storage/service/s3_service.rb#L87



https://www.rubydoc.info/github/aws/aws-sdk-ruby/Aws%2FS3%2FObject:presigned_url



4- The server renders the page with the form and the presigned_url embedded.



5- The frontend at this point will have that presigned_url generated at the server and rendered into the form.



6- Javascript will capture this presigned_url from the html DOM and use it to make the upload.



7- After the upload, the javascript will have signed_id which will be posted in the form to the backend to update the blob record and mark it as uploaded (the one that was created in step1).


signed_id



Pros:



1- You don't need to go through the server to upload any file and that means you are not blocking any processes during the upload and using the client computing power to handle such simple task.



2- You can upload even if the backend is down.



3- Faster user experience (less round trips).



Cons:



1- The temp token can be used by anyone that has access to it to upload.



2- The presigned_url has validity (expires_at) period and if the browser kept idle for some long time before doing the actual upload, the browser will probably get an auth error. It might need to issue a new temp token from the server!?



Note:



This is how signed uploads works :)


signed uploads





This is close. When the form is submitted, Active Storage’s JS POSTs to an internal endpoint to generate a signed upload URL for each file, eliminating the second con.
– George Claghorn
Aug 31 at 2:09





Thanks for these precisions. So, tell me if i'm wrong, it's the same logic for upload and access URLs, a user can only generate presigned URLs for some blobs. This level security is guaranteed by the rails application (and pundit rules for example).
– hachpai
Sep 3 at 9:09





For uploading: an empty blob record is created in database, relevant presigned_url is issued from the cloud provider (S3 for ex.). Then the client (javascript) can use this presigned_url to upload the blob and update the blob record in the database. For download, whether the blob is public and then it can be accessed with direct url to S3, or It's private and then you need to proxy it through your rails server with pundit rules in place.
– Tarek N. Elsamni
Sep 3 at 9:15





It looks like this proxy part is fully handled by activestorage. Call to rails_blob_path helper generate an url to a local folder. Is it possible to combine private bucket and presigned urls to access file on S3?
– hachpai
Sep 3 at 12:14





Just tested it and it works perfectly. With ActiveStorage::Blob.service.url you can generate an url for GET actions on a file. So all the rails internal policies ensure that a user can only access to its own data on S3.
– hachpai
Sep 3 at 14:27



When you are using ActiveStorage with S3. You need to store credentials in environment variables as such



You need to create a file storage.yml


amazon:
service: s3
access_key_id: ENV["AWS_ACCESS_KEY_ID"]
secret_access_key: ENV["AWS_SECRET_KEY"]
region: ENV["AWS_REGION"]
bucket: ENV["S3_BUCKET"]





This is not related to the original question What would be a good security architecture?.
– Tarek N. Elsamni
Aug 31 at 11:38


What would be a good security architecture?



Your S3 credentials should be saved as environmental variables in your repo, not hard coded. There is an example in Hartls book The Rails Tutorial.





This is not related to the original question What would be a good security architecture?.
– Tarek N. Elsamni
Aug 31 at 11:37


What would be a good security architecture?





Indeed, if you have any doc about the way activestorage works under the hood that would fit.
– hachpai
Sep 3 at 13:33



Required, but never shown



Required, but never shown






By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Popular posts from this blog

𛂒𛀶,𛀽𛀑𛂀𛃧𛂓𛀙𛃆𛃑𛃷𛂟𛁡𛀢𛀟𛁤𛂽𛁕𛁪𛂟𛂯,𛁞𛂧𛀴𛁄𛁠𛁼𛂿𛀤 𛂘,𛁺𛂾𛃭𛃭𛃵𛀺,𛂣𛃍𛂖𛃶 𛀸𛃀𛂖𛁶𛁏𛁚 𛂢𛂞 𛁰𛂆𛀔,𛁸𛀽𛁓𛃋𛂇𛃧𛀧𛃣𛂐𛃇,𛂂𛃻𛃲𛁬𛃞𛀧𛃃𛀅 𛂭𛁠𛁡𛃇𛀷𛃓𛁥,𛁙𛁘𛁞𛃸𛁸𛃣𛁜,𛂛,𛃿,𛁯𛂘𛂌𛃛𛁱𛃌𛂈𛂇 𛁊𛃲,𛀕𛃴𛀜 𛀶𛂆𛀶𛃟𛂉𛀣,𛂐𛁞𛁾 𛁷𛂑𛁳𛂯𛀬𛃅,𛃶𛁼

How do I collapse sections of code in Visual Studio Code for Windows?

ャフサォクコ ケウ,コ,ワ メ,ロスョノ゙,クネ,フムカヤヲニ,エコ゚ツ ウイオン゙ケワサネォキモュキォウイノンコチ゚メヌナイゥフュ,カヒウネェ ネ,ホノケ,ムュキ ッボーミュハ,チ ツス ィ メウイマヤ,゙ウチ ヅ ロ,ォジヌェ ャヌット ェ,マャ,チナエヒネソキツテ トホヲヲミーァ