Skip to content

Commit 31b43d0

Browse files
committed
storages: s3 custom domain signature fix
S3 signatures are fickle since there are several hashes of components which must ultimately be correct for the signature to match with no room for error. Since both the *host* header as well as the path, the former by default, the latter necessarily. The issue with custom domains is therefore that the *host* header mismatches unless the signature was created for that specific domain. This is complicated further by *boto3* making it incredibly difficult to actually sign a link with the path *not* containing the bucket prefix. Therefore setting the endpoint alone does not work with a truly custom domain (i.e. one where the data resides on the root of the domain). Changing this to a rather hacky workaround accessing fields of the internal data structures and grabbing the signer directly allows for signing the request. This comes with several caveats such as the parameters going largely untouched, however in preliminary testing it works fine. There are no superfluous slashes (i.e. no `https://example.com//file.svg`), no superfluous prefixes (i.e. `https://example.com/example.com/example.com/file.svg`), and there are no signature errors in general. Uploads still work. Reminder that the application cache may need clearing before the changes reflect in the non-admin UI. Relates: - [issue 13463](https://redirect.github.com/goauthentik/authentik/issues/13463) - [pr 14706 ](https://redirect.github.com/goauthentik/authentik/pull/14706) Signed-off-by: benaryorg <[email protected]>
1 parent ce1ea92 commit 31b43d0

File tree

1 file changed

+6
-10
lines changed

1 file changed

+6
-10
lines changed

authentik/root/storages.py

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
from django.db import connection
1010
from storages.backends.s3 import S3Storage as BaseS3Storage
1111
from storages.utils import clean_name, safe_join
12+
import botocore
1213

1314
from authentik.lib.config import CONFIG
1415

@@ -97,16 +98,11 @@ def url(self, name, parameters=None, expire=None, http_method=None):
9798
)
9899

99100
if self.custom_domain:
100-
# Key parameter can't be empty. Use "/" and remove it later.
101-
params["Key"] = "/"
102-
root_url_signed = self.bucket.meta.client.generate_presigned_url(
103-
"get_object", Params=params, ExpiresIn=expire
104-
)
105-
# Remove signing parameter and previously added key "/".
106-
root_url = self._strip_signing_parameters(root_url_signed)[:-1]
107-
# Replace bucket domain with custom domain.
108-
custom_url = f"{self.url_protocol}//{self.custom_domain}/"
109-
url = url.replace(root_url, custom_url)
101+
custom_url = f"{self.url_protocol}//{self.custom_domain}/{name}"
102+
request = botocore.awsrequest.AWSRequest(http_method or "GET", custom_url)
103+
self.bucket.meta.client._request_signer.sign("GetObject", request, signing_type="presign-url", expires_in=expire)
104+
prepared_request = request.prepare()
105+
url = prepared_request.url
110106

111107
if self.querystring_auth:
112108
return url

0 commit comments

Comments
 (0)