Update the signature x5u cache bust to be configurable. (#805)

* Update the signature x5u cache bust to be configurable.

* Document new x5u cache bust setting and fix lint issues.
This commit is contained in:
Michael Kelly 2017-06-12 13:22:45 -07:00 коммит произвёл Mike Cooper
Родитель 568568d268
Коммит e0247707c1
4 изменённых файлов: 33 добавлений и 15 удалений

Просмотреть файл

@ -162,6 +162,15 @@ in other Django projects.
possible while still guaranteeing that actions will get resigned during the
overlap period.
.. envvar:: DJANGO_AUTOGRAPH_X5U_CACHE_BUST
:default: Unset
If set, the value will be added to the URL for the x5u certificate chain as
a query parameter named `cachebust`. This is used to force clients to
re-fetch the certificate chain in cases where they're caching an expired or
otherwise invalid copy of the chain.
.. envvar:: DJANGO_API_CACHE_TIME
:default: ``30``

Просмотреть файл

@ -1,7 +1,8 @@
import time
import urllib.parse as urlparse
from urllib.parse import urlencode
from django.conf import settings
from pyjexl import JEXL
from rest_framework import serializers
@ -218,17 +219,16 @@ class SignatureSerializer(serializers.ModelSerializer):
def get_x5u(self, signature):
x5u = signature.x5u
if x5u is None:
return None
# Add cachebust parameter to x5u URL that changes once per hour.
url_parts = list(urlparse.urlparse(x5u))
query = urlparse.parse_qs(url_parts[4])
cachebust = int(time.time())
cachebust -= cachebust % 3600
query['cachebust'] = cachebust
url_parts[4] = urlencode(query)
return urlparse.urlunparse(url_parts)
# Add cachebust parameter to x5u URL.
if x5u is not None and settings.AUTOGRAPH_X5U_CACHE_BUST is not None:
url_parts = list(urlparse.urlparse(x5u))
query = urlparse.parse_qs(url_parts[4])
query['cachebust'] = settings.AUTOGRAPH_X5U_CACHE_BUST
url_parts[4] = urlencode(query)
return urlparse.urlunparse(url_parts)
return x5u
class SignedRecipeSerializer(serializers.ModelSerializer):

Просмотреть файл

@ -1,4 +1,3 @@
import re
import urllib.parse as urlparse
import pytest
@ -240,12 +239,21 @@ class TestSignatureSerializer:
'public_key': Whatever.regex(r'[a-zA-Z0-9/+]{160}')
}
def test_it_cachebusts_x5u(self):
def test_it_cachebusts_x5u(self, settings):
signature = SignatureFactory()
serializer = SignatureSerializer(instance=signature)
# If none, do not cache bust
settings.AUTOGRAPH_X5U_CACHE_BUST = None
serializer = SignatureSerializer(instance=signature)
url_parts = list(urlparse.urlparse(serializer.data['x5u']))
query = urlparse.parse_qs(url_parts[4])
assert 'cachebust' not in query
# If set, cachebust using the value
settings.AUTOGRAPH_X5U_CACHE_BUST = 'new'
serializer = SignatureSerializer(instance=signature)
url_parts = list(urlparse.urlparse(serializer.data['x5u']))
query = urlparse.parse_qs(url_parts[4])
assert 'cachebust' in query
assert len(query['cachebust']) == 1
assert re.match('^\d+$', query['cachebust'][0])
assert query['cachebust'][0] == 'new'

Просмотреть файл

@ -321,6 +321,7 @@ class Base(Core):
AUTOGRAPH_HAWK_ID = values.Value()
AUTOGRAPH_HAWK_SECRET_KEY = values.Value()
AUTOGRAPH_SIGNATURE_MAX_AGE = values.IntegerValue(60 * 60 * 24 * 7)
AUTOGRAPH_X5U_CACHE_BUST = values.Value(None)
# How many days before expiration to warn for expired certificates
CERTIFICATES_EXPIRE_EARLY_DAYS = values.IntegerValue(None)