#2104 - S3 - Persist metadata for Presigned URL
This commit is contained in:
parent
920d074bb9
commit
b33c5dff06
3 changed files with 143 additions and 1 deletions
|
|
@ -1079,6 +1079,10 @@ class ResponseObject(_TemplateEnvironmentMixin, ActionAuthenticatorMixin):
|
|||
if key:
|
||||
if not key.acl.public_read and not signed_url:
|
||||
return 403, {}, ""
|
||||
elif signed_url:
|
||||
# coming in from requests.get(s3.generate_presigned_url())
|
||||
if self._invalid_headers(request.url, dict(headers)):
|
||||
return 403, {}, S3_INVALID_PRESIGNED_PARAMETERS
|
||||
|
||||
if hasattr(request, "body"):
|
||||
# Boto
|
||||
|
|
@ -1287,6 +1291,7 @@ class ResponseObject(_TemplateEnvironmentMixin, ActionAuthenticatorMixin):
|
|||
)
|
||||
request.streaming = True
|
||||
metadata = metadata_from_headers(request.headers)
|
||||
metadata.update(metadata_from_headers(query))
|
||||
new_key.set_metadata(metadata)
|
||||
new_key.set_acl(acl)
|
||||
new_key.website_redirect_location = request.headers.get(
|
||||
|
|
@ -1672,6 +1677,29 @@ class ResponseObject(_TemplateEnvironmentMixin, ActionAuthenticatorMixin):
|
|||
"Method POST had only been implemented for multipart uploads and restore operations, so far"
|
||||
)
|
||||
|
||||
def _invalid_headers(self, url, headers):
|
||||
"""
|
||||
Verify whether the provided metadata in the URL is also present in the headers
|
||||
:param url: .../file.txt&content-type=app%2Fjson&Signature=..
|
||||
:param headers: Content-Type=app/json
|
||||
:return: True or False
|
||||
"""
|
||||
metadata_to_check = {
|
||||
"content-disposition": "Content-Disposition",
|
||||
"content-encoding": "Content-Encoding",
|
||||
"content-language": "Content-Language",
|
||||
"content-length": "Content-Length",
|
||||
"content-md5": "Content-MD5",
|
||||
"content-type": "Content-Type",
|
||||
}
|
||||
for url_key, header_key in metadata_to_check.items():
|
||||
metadata_in_url = re.search(url_key + "=(.+?)(&.+$|$)", url)
|
||||
if metadata_in_url:
|
||||
url_value = unquote(metadata_in_url.group(1))
|
||||
if header_key not in headers or (url_value != headers[header_key]):
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
S3ResponseInstance = ResponseObject(s3_backend)
|
||||
|
||||
|
|
@ -2214,6 +2242,15 @@ S3_ENCRYPTION_CONFIG = """<?xml version="1.0" encoding="UTF-8"?>
|
|||
</BucketEncryptionStatus>
|
||||
"""
|
||||
|
||||
S3_INVALID_PRESIGNED_PARAMETERS = """<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Error>
|
||||
<Code>SignatureDoesNotMatch</Code>
|
||||
<Message>The request signature we calculated does not match the signature you provided. Check your key and signing method.</Message>
|
||||
<RequestId>0D68A23BB2E2215B</RequestId>
|
||||
<HostId>9Gjjt1m+cjU4OPvX9O9/8RuvnG41MRb/18Oux2o5H5MY7ISNTlXN+Dz9IG62/ILVxhAGI0qyPfg=</HostId>
|
||||
</Error>
|
||||
"""
|
||||
|
||||
S3_NO_ENCRYPTION = """<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Error>
|
||||
<Code>ServerSideEncryptionConfigurationNotFoundError</Code>
|
||||
|
|
|
|||
|
|
@ -75,7 +75,11 @@ def metadata_from_headers(headers):
|
|||
# Check for special metadata that doesn't start with x-amz-meta
|
||||
meta_key = header
|
||||
if meta_key:
|
||||
metadata[meta_key] = headers[header]
|
||||
metadata[meta_key] = (
|
||||
headers[header][0]
|
||||
if type(headers[header]) == list
|
||||
else headers[header]
|
||||
)
|
||||
return metadata
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue