✨(backend) add url to download media attachments with access rights
We make use of nginx subrequests to block media file downloads while we check for access rights. The request is then proxied to the object storage engine and authorization is added via the "Authorization" header. This way the media urls are static and can be stored in the document's json content without compromising on security: access control is done on all requests based on the user cookie session.
This commit is contained in:
committed by
Samuel Paccoud
parent
c9f1356d3e
commit
67a20f249e
33
src/backend/core/api/utils.py
Normal file
33
src/backend/core/api/utils.py
Normal file
@@ -0,0 +1,33 @@
|
||||
"""Util to generate S3 authorization headers for object storage access control"""
|
||||
|
||||
from django.core.files.storage import default_storage
|
||||
|
||||
import botocore
|
||||
|
||||
|
||||
def generate_s3_authorization_headers(key):
|
||||
"""
|
||||
Generate authorization headers for an s3 object.
|
||||
These headers can be used as an alternative to signed urls with many benefits:
|
||||
- the urls of our files never expire and can be stored in our documents' content
|
||||
- we don't leak authorized urls that could be shared (file access can only be done
|
||||
with cookies)
|
||||
- access control is truly realtime
|
||||
- the object storage service does not need to be exposed on internet
|
||||
"""
|
||||
url = default_storage.unsigned_connection.meta.client.generate_presigned_url(
|
||||
"get_object",
|
||||
ExpiresIn=0,
|
||||
Params={"Bucket": default_storage.bucket_name, "Key": key},
|
||||
)
|
||||
request = botocore.awsrequest.AWSRequest(method="get", url=url)
|
||||
|
||||
s3_client = default_storage.connection.meta.client
|
||||
# pylint: disable=protected-access
|
||||
credentials = s3_client._request_signer._credentials # noqa: SLF001
|
||||
frozen_credentials = credentials.get_frozen_credentials()
|
||||
region = s3_client.meta.region_name
|
||||
auth = botocore.auth.S3SigV4Auth(frozen_credentials, "s3", region)
|
||||
auth.add_auth(request)
|
||||
|
||||
return request
|
||||
Reference in New Issue
Block a user