Merge "auth_token hashes PKI token once"

This commit is contained in:
Jenkins
2014-05-28 01:26:35 +00:00
committed by Gerrit Code Review
3 changed files with 38 additions and 20 deletions

View File

@@ -166,7 +166,6 @@ from keystoneclient.middleware import memcache_crypt
from keystoneclient.openstack.common import jsonutils from keystoneclient.openstack.common import jsonutils
from keystoneclient.openstack.common import memorycache from keystoneclient.openstack.common import memorycache
from keystoneclient.openstack.common import timeutils from keystoneclient.openstack.common import timeutils
from keystoneclient import utils
# alternative middleware configuration in the main application's # alternative middleware configuration in the main application's
@@ -914,10 +913,10 @@ class AuthProtocol(object):
raise InvalidUserToken( raise InvalidUserToken(
'Token authorization failed') 'Token authorization failed')
elif cms.is_pkiz(user_token): elif cms.is_pkiz(user_token):
verified = self.verify_pkiz_token(user_token) verified = self.verify_pkiz_token(user_token, token_id)
data = jsonutils.loads(verified) data = jsonutils.loads(verified)
elif cms.is_asn1_token(user_token): elif cms.is_asn1_token(user_token):
verified = self.verify_signed_token(user_token) verified = self.verify_signed_token(user_token, token_id)
data = jsonutils.loads(verified) data = jsonutils.loads(verified)
else: else:
data = self.verify_uuid_token(user_token, retry) data = self.verify_uuid_token(user_token, retry)
@@ -1250,11 +1249,8 @@ class AuthProtocol(object):
raise InvalidUserToken() raise InvalidUserToken()
def is_signed_token_revoked(self, signed_text): def is_signed_token_revoked(self, token_id):
"""Indicate whether the token appears in the revocation list.""" """Indicate whether the token appears in the revocation list."""
if isinstance(signed_text, six.text_type):
signed_text = signed_text.encode('utf-8')
token_id = utils.hash_signed_token(signed_text)
is_revoked = self._is_token_id_in_revoked_list(token_id) is_revoked = self._is_token_id_in_revoked_list(token_id)
if is_revoked: if is_revoked:
self.LOG.debug('Token is marked as having been revoked') self.LOG.debug('Token is marked as having been revoked')
@@ -1301,17 +1297,17 @@ class AuthProtocol(object):
self.LOG.error('CMS Verify output: %s', err.output) self.LOG.error('CMS Verify output: %s', err.output)
raise raise
def verify_signed_token(self, signed_text): def verify_signed_token(self, signed_text, token_id):
"""Check that the token is unrevoked and has a valid signature.""" """Check that the token is unrevoked and has a valid signature."""
if self.is_signed_token_revoked(signed_text): if self.is_signed_token_revoked(token_id):
raise InvalidUserToken('Token has been revoked') raise InvalidUserToken('Token has been revoked')
formatted = cms.token_to_cms(signed_text) formatted = cms.token_to_cms(signed_text)
verified = self.cms_verify(formatted) verified = self.cms_verify(formatted)
return verified return verified
def verify_pkiz_token(self, signed_text): def verify_pkiz_token(self, signed_text, token_id):
if self.is_signed_token_revoked(signed_text): if self.is_signed_token_revoked(token_id):
raise InvalidUserToken('Token has been revoked') raise InvalidUserToken('Token has been revoked')
try: try:
uncompressed = cms.pkiz_uncompress(signed_text) uncompressed = cms.pkiz_uncompress(signed_text)

View File

@@ -31,6 +31,12 @@ CMSDIR = os.path.join(ROOTDIR, 'examples', 'pki', 'cms')
KEYDIR = os.path.join(ROOTDIR, 'examples', 'pki', 'private') KEYDIR = os.path.join(ROOTDIR, 'examples', 'pki', 'private')
def _hash_signed_token_safe(signed_text, **kwargs):
if isinstance(signed_text, six.text_type):
signed_text = signed_text.encode('utf-8')
return utils.hash_signed_token(signed_text, **kwargs)
class Examples(fixtures.Fixture): class Examples(fixtures.Fixture):
"""Example tokens and certs loaded from the examples directory. """Example tokens and certs loaded from the examples directory.
@@ -58,10 +64,14 @@ class Examples(fixtures.Fixture):
with open(os.path.join(CMSDIR, 'auth_token_scoped.pem')) as f: with open(os.path.join(CMSDIR, 'auth_token_scoped.pem')) as f:
self.SIGNED_TOKEN_SCOPED = cms.cms_to_token(f.read()) self.SIGNED_TOKEN_SCOPED = cms.cms_to_token(f.read())
self.SIGNED_TOKEN_SCOPED_HASH = _hash_signed_token_safe(
self.SIGNED_TOKEN_SCOPED)
with open(os.path.join(CMSDIR, 'auth_token_unscoped.pem')) as f: with open(os.path.join(CMSDIR, 'auth_token_unscoped.pem')) as f:
self.SIGNED_TOKEN_UNSCOPED = cms.cms_to_token(f.read()) self.SIGNED_TOKEN_UNSCOPED = cms.cms_to_token(f.read())
with open(os.path.join(CMSDIR, 'auth_v3_token_scoped.pem')) as f: with open(os.path.join(CMSDIR, 'auth_v3_token_scoped.pem')) as f:
self.SIGNED_v3_TOKEN_SCOPED = cms.cms_to_token(f.read()) self.SIGNED_v3_TOKEN_SCOPED = cms.cms_to_token(f.read())
self.SIGNED_v3_TOKEN_SCOPED_HASH = _hash_signed_token_safe(
self.SIGNED_v3_TOKEN_SCOPED)
with open(os.path.join(CMSDIR, 'auth_token_revoked.pem')) as f: with open(os.path.join(CMSDIR, 'auth_token_revoked.pem')) as f:
self.REVOKED_TOKEN = cms.cms_to_token(f.read()) self.REVOKED_TOKEN = cms.cms_to_token(f.read())
with open(os.path.join(CMSDIR, 'auth_token_scoped_expired.pem')) as f: with open(os.path.join(CMSDIR, 'auth_token_scoped_expired.pem')) as f:

View File

@@ -664,27 +664,29 @@ class CommonAuthTokenMiddlewareTest(object):
self.middleware.token_revocation_list = jsonutils.dumps( self.middleware.token_revocation_list = jsonutils.dumps(
{"revoked": [], "extra": "success"}) {"revoked": [], "extra": "success"})
result = self.middleware.is_signed_token_revoked( result = self.middleware.is_signed_token_revoked(
self.token_dict['revoked_token']) self.token_dict['revoked_token_hash'])
self.assertFalse(result) self.assertFalse(result)
def test_is_signed_token_revoked_returns_true(self): def test_is_signed_token_revoked_returns_true(self):
self.middleware.token_revocation_list = self.get_revocation_list_json() self.middleware.token_revocation_list = self.get_revocation_list_json()
result = self.middleware.is_signed_token_revoked( result = self.middleware.is_signed_token_revoked(
self.token_dict['revoked_token']) self.token_dict['revoked_token_hash'])
self.assertTrue(result) self.assertTrue(result)
def test_verify_signed_token_raises_exception_for_revoked_token(self): def test_verify_signed_token_raises_exception_for_revoked_token(self):
self.middleware.token_revocation_list = self.get_revocation_list_json() self.middleware.token_revocation_list = self.get_revocation_list_json()
self.assertRaises(auth_token.InvalidUserToken, self.assertRaises(auth_token.InvalidUserToken,
self.middleware.verify_signed_token, self.middleware.verify_signed_token,
self.token_dict['revoked_token']) self.token_dict['revoked_token'],
self.token_dict['revoked_token_hash'])
def test_verify_signed_token_raises_exception_for_revoked_pkiz_token(self): def test_verify_signed_token_raises_exception_for_revoked_pkiz_token(self):
self.middleware.token_revocation_list = ( self.middleware.token_revocation_list = (
self.examples.REVOKED_TOKEN_PKIZ_LIST_JSON) self.examples.REVOKED_TOKEN_PKIZ_LIST_JSON)
self.assertRaises(auth_token.InvalidUserToken, self.assertRaises(auth_token.InvalidUserToken,
self.middleware.verify_pkiz_token, self.middleware.verify_pkiz_token,
self.token_dict['revoked_token_pkiz']) self.token_dict['revoked_token_pkiz'],
self.token_dict['revoked_token_pkiz_hash'])
def assertIsValidJSON(self, text): def assertIsValidJSON(self, text):
json.loads(text) json.loads(text)
@@ -692,13 +694,15 @@ class CommonAuthTokenMiddlewareTest(object):
def test_verify_signed_token_succeeds_for_unrevoked_token(self): def test_verify_signed_token_succeeds_for_unrevoked_token(self):
self.middleware.token_revocation_list = self.get_revocation_list_json() self.middleware.token_revocation_list = self.get_revocation_list_json()
text = self.middleware.verify_signed_token( text = self.middleware.verify_signed_token(
self.token_dict['signed_token_scoped']) self.token_dict['signed_token_scoped'],
self.token_dict['signed_token_scoped_hash'])
self.assertIsValidJSON(text) self.assertIsValidJSON(text)
def test_verify_signed_compressed_token_succeeds_for_unrevoked_token(self): def test_verify_signed_compressed_token_succeeds_for_unrevoked_token(self):
self.middleware.token_revocation_list = self.get_revocation_list_json() self.middleware.token_revocation_list = self.get_revocation_list_json()
text = self.middleware.verify_pkiz_token( text = self.middleware.verify_pkiz_token(
self.token_dict['signed_token_scoped_pkiz']) self.token_dict['signed_token_scoped_pkiz'],
self.token_dict['signed_token_scoped_hash'])
self.assertIsValidJSON(text) self.assertIsValidJSON(text)
def test_verify_signing_dir_create_while_missing(self): def test_verify_signing_dir_create_while_missing(self):
@@ -1164,7 +1168,8 @@ class V2CertDownloadMiddlewareTest(BaseAuthTokenMiddlewareTest,
status=404) status=404)
self.assertRaises(exceptions.CertificateConfigError, self.assertRaises(exceptions.CertificateConfigError,
self.middleware.verify_signed_token, self.middleware.verify_signed_token,
self.examples.SIGNED_TOKEN_SCOPED) self.examples.SIGNED_TOKEN_SCOPED,
self.examples.SIGNED_TOKEN_SCOPED_HASH)
def test_fetch_signing_cert(self): def test_fetch_signing_cert(self):
data = 'FAKE CERT' data = 'FAKE CERT'
@@ -1290,11 +1295,14 @@ class v2AuthTokenMiddlewareTest(BaseAuthTokenMiddlewareTest,
'uuid_token_unknown_bind': self.examples.UUID_TOKEN_UNKNOWN_BIND, 'uuid_token_unknown_bind': self.examples.UUID_TOKEN_UNKNOWN_BIND,
'signed_token_scoped': self.examples.SIGNED_TOKEN_SCOPED, 'signed_token_scoped': self.examples.SIGNED_TOKEN_SCOPED,
'signed_token_scoped_pkiz': self.examples.SIGNED_TOKEN_SCOPED_PKIZ, 'signed_token_scoped_pkiz': self.examples.SIGNED_TOKEN_SCOPED_PKIZ,
'signed_token_scoped_hash': self.examples.SIGNED_TOKEN_SCOPED_HASH,
'signed_token_scoped_expired': 'signed_token_scoped_expired':
self.examples.SIGNED_TOKEN_SCOPED_EXPIRED, self.examples.SIGNED_TOKEN_SCOPED_EXPIRED,
'revoked_token': self.examples.REVOKED_TOKEN, 'revoked_token': self.examples.REVOKED_TOKEN,
'revoked_token_pkiz': self.examples.REVOKED_TOKEN_PKIZ, 'revoked_token_pkiz': self.examples.REVOKED_TOKEN_PKIZ,
'revoked_token_hash': self.examples.REVOKED_TOKEN_HASH 'revoked_token_pkiz_hash':
self.examples.REVOKED_TOKEN_PKIZ_HASH,
'revoked_token_hash': self.examples.REVOKED_TOKEN_HASH,
} }
httpretty.reset() httpretty.reset()
@@ -1475,11 +1483,15 @@ class v3AuthTokenMiddlewareTest(BaseAuthTokenMiddlewareTest,
'signed_token_scoped': self.examples.SIGNED_v3_TOKEN_SCOPED, 'signed_token_scoped': self.examples.SIGNED_v3_TOKEN_SCOPED,
'signed_token_scoped_pkiz': 'signed_token_scoped_pkiz':
self.examples.SIGNED_v3_TOKEN_SCOPED_PKIZ, self.examples.SIGNED_v3_TOKEN_SCOPED_PKIZ,
'signed_token_scoped_hash':
self.examples.SIGNED_v3_TOKEN_SCOPED_HASH,
'signed_token_scoped_expired': 'signed_token_scoped_expired':
self.examples.SIGNED_TOKEN_SCOPED_EXPIRED, self.examples.SIGNED_TOKEN_SCOPED_EXPIRED,
'revoked_token': self.examples.REVOKED_v3_TOKEN, 'revoked_token': self.examples.REVOKED_v3_TOKEN,
'revoked_token_pkiz': self.examples.REVOKED_v3_TOKEN_PKIZ, 'revoked_token_pkiz': self.examples.REVOKED_v3_TOKEN_PKIZ,
'revoked_token_hash': self.examples.REVOKED_v3_TOKEN_HASH 'revoked_token_hash': self.examples.REVOKED_v3_TOKEN_HASH,
'revoked_token_pkiz_hash':
self.examples.REVOKED_v3_PKIZ_TOKEN_HASH,
} }
httpretty.reset() httpretty.reset()