summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--keystone/tests/unit/token/test_fernet_provider.py39
-rw-r--r--keystone/token/providers/fernet/token_formatters.py16
2 files changed, 53 insertions, 2 deletions
diff --git a/keystone/tests/unit/token/test_fernet_provider.py b/keystone/tests/unit/token/test_fernet_provider.py
index 5f74b430e..a909ee276 100644
--- a/keystone/tests/unit/token/test_fernet_provider.py
+++ b/keystone/tests/unit/token/test_fernet_provider.py
@@ -16,7 +16,9 @@ import hashlib
import os
import uuid
+import msgpack
from oslo_utils import timeutils
+from six.moves import urllib
from keystone.common import config
from keystone.common import utils
@@ -58,6 +60,10 @@ class TestFernetTokenProvider(unit.TestCase):
class TestTokenFormatter(unit.TestCase):
+ def setUp(self):
+ super(TestTokenFormatter, self).setUp()
+ self.useFixture(ksfixtures.KeyRepository(self.config_fixture))
+
def test_restore_padding(self):
# 'a' will result in '==' padding, 'aa' will result in '=' padding, and
# 'aaa' will result in no padding.
@@ -73,6 +79,39 @@ class TestTokenFormatter(unit.TestCase):
)
self.assertEqual(encoded_string, encoded_str_with_padding_restored)
+ def test_legacy_padding_validation(self):
+ first_value = uuid.uuid4().hex
+ second_value = uuid.uuid4().hex
+ payload = (first_value, second_value)
+ msgpack_payload = msgpack.packb(payload)
+
+ # NOTE(lbragstad): This method perserves the way that keystone used to
+ # percent encode the tokens, prior to bug #1491926.
+ def legacy_pack(payload):
+ tf = token_formatters.TokenFormatter()
+ encrypted_payload = tf.crypto.encrypt(payload)
+
+ # the encrypted_payload is returned with padding appended
+ self.assertTrue(encrypted_payload.endswith('='))
+
+ # using urllib.parse.quote will percent encode the padding, like
+ # keystone did in Kilo.
+ percent_encoded_payload = urllib.parse.quote(encrypted_payload)
+
+ # ensure that the padding was actaully percent encoded
+ self.assertTrue(percent_encoded_payload.endswith('%3D'))
+ return percent_encoded_payload
+
+ token_with_legacy_padding = legacy_pack(msgpack_payload)
+ tf = token_formatters.TokenFormatter()
+
+ # demonstrate the we can validate a payload that has been percent
+ # encoded with the Fernet logic that existed in Kilo
+ serialized_payload = tf.unpack(token_with_legacy_padding)
+ returned_payload = msgpack.unpackb(serialized_payload)
+ self.assertEqual(first_value, returned_payload[0])
+ self.assertEqual(second_value, returned_payload[1])
+
class TestPayloads(unit.TestCase):
def test_uuid_hex_to_byte_conversions(self):
diff --git a/keystone/token/providers/fernet/token_formatters.py b/keystone/token/providers/fernet/token_formatters.py
index f0b6271d1..a6b42197f 100644
--- a/keystone/token/providers/fernet/token_formatters.py
+++ b/keystone/token/providers/fernet/token_formatters.py
@@ -22,6 +22,7 @@ from oslo_log import log
from oslo_utils import timeutils
import six
from six.moves import map
+from six.moves import urllib
from keystone.auth import plugins as auth_plugins
from keystone.common import utils as ks_utils
@@ -73,8 +74,19 @@ class TokenFormatter(object):
"""Unpack a token, and validate the payload."""
token = six.binary_type(token)
- # Restore padding on token before decoding it
- token = TokenFormatter.restore_padding(token)
+ # TODO(lbragstad): Restore padding on token before decoding it.
+ # Initially in Kilo, Fernet tokens were returned to the user with
+ # padding appended to the token. Later in Liberty this padding was
+ # removed and restored in the Fernet provider. The following if
+ # statement ensures that we can validate tokens with and without token
+ # padding, in the event of an upgrade and the tokens that are issued
+ # throughout the upgrade. Remove this if statement when Mitaka opens
+ # for development and exclusively use the restore_padding() class
+ # method.
+ if token.endswith('%3D'):
+ token = urllib.parse.unquote(token)
+ else:
+ token = TokenFormatter.restore_padding(token)
try:
return self.crypto.decrypt(token)