diff --git a/CTFd/config.ini b/CTFd/config.ini index 6db6db99..9e8fc742 100644 --- a/CTFd/config.ini +++ b/CTFd/config.ini @@ -163,7 +163,7 @@ MAILGUN_BASE_URL = # MAIL_PROVIDER # Specifies the email provider that CTFd will use to send email. -# By default CTFd will automatically detect the correct email provider based on the other settings +# By default CTFd will automatically detect the correct email provider based on the other settings # specified here or in the configuration panel. This setting can be used to force a specific provider. MAIL_PROVIDER = @@ -198,6 +198,17 @@ AWS_S3_ENDPOINT_URL = # The aws region that hosts your bucket. Only used in the s3 uploader. AWS_S3_REGION = +# AWS_S3_ADDRESSING_STYLE +# The S3 addressing style to use for URLs. Only used under the s3 uploader. +# Defaults to auto; can be set to virtual or path. +# See https://boto3.amazonaws.com/v1/documentation/api/latest/guide/configuration.html +AWS_S3_ADDRESSING_STYLE = + +# AWS_S3_CUSTOM_DOMAIN +# A hostname that replaces the default hostname in the generated S3 download URLs. Required by some S3 providers or CDNs. +# Only used under the s3 uploader. +AWS_S3_CUSTOM_DOMAIN = + [logs] # LOG_FOLDER # The location where logs are written. These are the logs for CTFd key submissions, registrations, and logins. The default location is the CTFd/logs folder. diff --git a/CTFd/config.py b/CTFd/config.py index d2e7222f..5598e069 100644 --- a/CTFd/config.py +++ b/CTFd/config.py @@ -210,6 +210,10 @@ class ServerConfig(object): AWS_S3_REGION: str = empty_str_cast(config_ini["uploads"]["AWS_S3_REGION"]) + AWS_S3_CUSTOM_DOMAIN: str = empty_str_cast(config_ini["uploads"].get("AWS_S3_CUSTOM_DOMAIN", "")) + + AWS_S3_ADDRESSING_STYLE: str = empty_str_cast(config_ini["uploads"].get("AWS_S3_ADDRESSING_STYLE", ""), default="auto") + # === OPTIONAL === REVERSE_PROXY: Union[str, bool] = empty_str_cast(config_ini["optional"]["REVERSE_PROXY"], default=False) diff --git a/CTFd/utils/uploads/uploaders.py b/CTFd/utils/uploads/uploaders.py index f802edf4..2778b56b 100644 --- a/CTFd/utils/uploads/uploaders.py +++ b/CTFd/utils/uploads/uploaders.py @@ -5,6 +5,7 @@ import string import time from pathlib import PurePath from shutil import copyfileobj, rmtree +from urllib.parse import urlparse import boto3 from botocore.client import Config @@ -89,9 +90,12 @@ class S3Uploader(BaseUploader): secret_key = get_app_config("AWS_SECRET_ACCESS_KEY") endpoint = get_app_config("AWS_S3_ENDPOINT_URL") region = get_app_config("AWS_S3_REGION") + addressing_style = get_app_config("AWS_S3_ADDRESSING_STYLE") client = boto3.client( "s3", - config=Config(signature_version="s3v4"), + config=Config( + signature_version="s3v4", s3={"addressing_style": addressing_style} + ), aws_access_key_id=access_key, aws_secret_access_key=secret_key, endpoint_url=endpoint, @@ -141,6 +145,11 @@ class S3Uploader(BaseUploader): }, ExpiresIn=3600, ) + + custom_domain = get_app_config("AWS_S3_CUSTOM_DOMAIN") + if custom_domain: + url = urlparse(url)._replace(netloc=custom_domain).geturl() + return redirect(url) def delete(self, filename):