Skip to content

Commit

Permalink
[s3] fix disabling cloudfront signing with cloudfront_signer=None (#1326
Browse files Browse the repository at this point in the history
)

This change fixes disabling cloudfront signing by specifying "None" (or
another falsy value). This allows multiple storage configs that are all
distributed via cloudfront, but only some of the configs need to be
signed.
  • Loading branch information
terencehonles committed Oct 18, 2023
1 parent a13b0ec commit c408bf0
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 3 deletions.
39 changes: 38 additions & 1 deletion docs/backends/amazon-S3.rst
Expand Up @@ -186,12 +186,49 @@ Settings
Set this to specify a custom domain for constructed URLs.

.. note::
You'll have to configure CloudFront to use the bucket as an origin for this to work.
You'll have to configure CloudFront to use the bucket as an origin for this to
work.

If your CloudFront config restricts viewer access you will also need to provide
``cloudfront_key`` / ``AWS_CLOUDFRONT_KEY`` and ``cloudfront_key_id`` /
``AWS_CLOUDFRONT_KEY_ID``; See those settings and
:ref:`cloudfront-signed-url-header` for more info.

If you have more than one storage with different viewer access permissions, you
can provide ``cloudfront_signer=None`` to disable signing on one or more
storages.

.. warning::

Django’s STATIC_URL must end in a slash and this must not. It is best to set this variable independently of STATIC_URL.

``cloudfront_key`` or ``AWS_CLOUDFRONT_KEY``

Default: ``None``

A private PEM encoded key to use in a ``boto3`` ``CloudFrontSigner``; See
:ref:`cloudfront-signed-url-header` for more info.

``cloudfront_key_id`` or ``AWS_CLOUDFRONT_KEY_ID``

Default: ``None``

The AWS key ID for the private key provided with ``cloudfront_key`` /
``AWS_CLOUDFRONT_KEY``; See :ref:`cloudfront-signed-url-header` for more info.

``cloudfront_signer``

Default: omitted

By default the ``cloudfront_signer`` is generated based on the CloudFront key and ID
provided. If both are provided URLs will be signed and will work for distributions
with restricted viewer access, but if neither are provided then URLs will not be
signed and will work for distributions with unrestricted viewer access.

If you require a custom CloudFront signer you may pass a ``boto3``
``CloudFrontSigner`` instance that can sign URLs, and to disable signing you may pass
``None``.

``signature_version`` or ``AWS_S3_SIGNATURE_VERSION``

Default: ``None``
Expand Down
7 changes: 5 additions & 2 deletions storages/backends/s3.py
Expand Up @@ -299,7 +299,8 @@ class S3Storage(CompressStorageMixin, BaseStorage):
config = None

def __init__(self, **settings):
self.cloudfront_signer = settings.pop("cloudfront_signer", None)
omitted = object()
self.cloudfront_signer = settings.pop("cloudfront_signer", omitted)

super().__init__(**settings)

Expand Down Expand Up @@ -333,7 +334,7 @@ def __init__(self, **settings):
if self.transfer_config is None:
self.transfer_config = TransferConfig(use_threads=self.use_threads)

if not self.cloudfront_signer:
if self.cloudfront_signer is omitted:
if self.cloudfront_key_id and self.cloudfront_key:
self.cloudfront_signer = self.get_cloudfront_signer(
self.cloudfront_key_id, self.cloudfront_key
Expand All @@ -343,6 +344,8 @@ def __init__(self, **settings):
"Both AWS_CLOUDFRONT_KEY_ID/cloudfront_key_id and "
"AWS_CLOUDFRONT_KEY/cloudfront_key must be provided together."
)
else:
self.cloudfront_signer = None

def get_cloudfront_signer(self, key_id, key):
return _cloud_front_signer_from_pem(key_id, key)
Expand Down
4 changes: 4 additions & 0 deletions tests/test_s3.py
Expand Up @@ -890,6 +890,10 @@ def test_cloudfront_config(self):
storage = s3.S3Storage()
self.assertIsNotNone(storage.cloudfront_signer)

# allow disabling cloudfront signing
storage = s3.S3Storage(cloudfront_signer=None)
self.assertIsNone(storage.cloudfront_signer)

storage = s3.S3Storage(cloudfront_key_id=key_id, cloudfront_key=pem)
self.assertIsNotNone(storage.cloudfront_signer)

Expand Down

0 comments on commit c408bf0

Please sign in to comment.