Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support Signed, Secure and Expiring URLs with CloudFront/S3 #138

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 24 additions & 6 deletions fileconveyor/transporters/transporter_cf.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,37 @@ class TransporterCF(TransporterS3):


name = 'CF'
valid_settings = ImmutableSet(["access_key_id", "secret_access_key", "bucket_name", "distro_domain_name", "bucket_prefix"])
valid_settings = ImmutableSet(["access_key_id", "secret_access_key", "bucket_name", "distro_domain_name", "bucket_prefix",
"use_signed_urls", "use_secure_urls", "set_url_expiration", "secure_distro_domain_name"])
required_settings = ImmutableSet(["access_key_id", "secret_access_key", "bucket_name", "distro_domain_name"])


def __init__(self, settings, callback, error_callback, parent_logger=None):
return TransporterS3.__init__(self, settings, callback, error_callback, parent_logger)
# Fill out defaults if necessary.
TransporterS3.__init__(self, settings, callback, error_callback, parent_logger)
configured_settings = Set(self.settings.keys())

if self.settings["use_secure_urls"].lower() == "true":
if not "secure_distro_domain_name" in configured_settings:
if self.settings["distro_domain_name"].partition('.')[2] == "cloudfront.net":
self.settings["secure_distro_domain_name"] = self.settings["distro_domain_name"]
else:
self.logger.error("You must set 'secure_distro_domain_name' when you have 'use_secure_urls' set but are not using a cloudfront.net host for 'distro_domain_name'")
raise InvalidSettingError

return TransporterS3.__init__(self, settings, callback, error_callback, parent_logger)

def alter_url(self, url):
return url.replace(
self.settings["bucket_prefix"] + self.settings["bucket_name"] + ".s3.amazonaws.com",
self.settings["distro_domain_name"]
)
if self.settings["use_secure_urls"].lower() == "true":
return url.replace(
self.settings["bucket_prefix"] + self.settings["bucket_name"] + ".s3.amazonaws.com",
self.settings["secure_distro_domain_name"]
)
else:
return url.replace(
self.settings["bucket_prefix"] + self.settings["bucket_name"] + ".s3.amazonaws.com",
self.settings["distro_domain_name"]
)


def create_distribution(access_key_id, secret_access_key, origin, comment="", cnames=None):
Expand Down
37 changes: 35 additions & 2 deletions fileconveyor/transporters/transporter_s3.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ class TransporterS3(Transporter):


name = 'S3'
valid_settings = ImmutableSet(["access_key_id", "secret_access_key", "bucket_name", "bucket_prefix"])
valid_settings = ImmutableSet(["access_key_id", "secret_access_key", "bucket_name", "bucket_prefix",
"use_signed_urls", "use_secure_urls", "set_url_expiration"])
required_settings = ImmutableSet(["access_key_id", "secret_access_key", "bucket_name"])
headers = {
'Expires': 'Tue, 20 Jan 2037 03:00:00 GMT', # UNIX timestamps will stop working somewhere in 2038.
Expand All @@ -26,6 +27,34 @@ def __init__(self, settings, callback, error_callback, parent_logger=None):
if not "bucket_prefix" in configured_settings:
self.settings["bucket_prefix"] = ""

# Continue default behavior of S3BotoStorage
# if the user has not defined these in the
# configuration file.
if not "use_signed_urls" in configured_settings:
self.settings["use_signed_urls"] = "true"

if not "use_secure_urls" in configured_settings:
self.settings["use_secure_urls"] = "true"

if not "set_url_expiration" in configured_settings:
self.settings["set_url_expiration"] = 3600

# set_url_expiration must be an integer, if it is not, set to default.
if not isinstance(self.settings["set_url_expiration"], int):
self.settings["set_url_expiration"] = 3600

if self.settings["use_signed_urls"].lower() == "true":
USE_QUERYSTRING_AUTH=True
else:
USE_QUERYSTRING_AUTH=False

if self.settings["use_secure_urls"].lower() == "true":
USE_SECURE_URLS=True
USE_URL_PROTOCOL="https"
else:
USE_SECURE_URLS=False
USE_URL_PROTOCOL="http"

# Map the settings to the format expected by S3Storage.
try:
self.storage = S3BotoStorage(
Expand All @@ -34,7 +63,11 @@ def __init__(self, settings, callback, error_callback, parent_logger=None):
self.settings["secret_access_key"].encode('utf-8'),
"public-read",
"public-read",
self.__class__.headers
self.__class__.headers,
querystring_auth=USE_QUERYSTRING_AUTH,
querystring_expire=self.settings["set_url_expiration"],
secure_urls=USE_SECURE_URLS,
#url_protocol=USE_URL_PROTOCOL
)
except Exception, e:
raise ConnectionError(e)