summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorwanghong <w.wanghong@huawei.com>2014-10-27 15:12:05 +0800
committerwanghong <w.wanghong@huawei.com>2014-12-17 16:39:26 +0800
commit136f85c01ad4da01f9e073619f22eed5ca2378cc (patch)
tree0c1336d5dfe1d0858cff1fed62a0b1e4a38212c0
parent0bd661fcbb423b2225acc40131088da46969e574 (diff)
downloadkeystonemiddleware-136f85c01ad4da01f9e073619f22eed5ca2378cc.tar.gz
fallback to online validation if offline validation fails
Authmiddleware should fallback to purely online validation when fetching certificate config failed or fetching revocation list failed. Change-Id: I532e667cc26bbeb9bbd03605b9fb7ea7ebf14afa Closes-Bug: #1384898
-rw-r--r--keystonemiddleware/auth_token.py37
-rw-r--r--keystonemiddleware/tests/test_auth_token_middleware.py29
2 files changed, 52 insertions, 14 deletions
diff --git a/keystonemiddleware/auth_token.py b/keystonemiddleware/auth_token.py
index 5d407c8..eef430e 100644
--- a/keystonemiddleware/auth_token.py
+++ b/keystonemiddleware/auth_token.py
@@ -498,6 +498,10 @@ class ConfigurationError(Exception):
pass
+class RevocationListError(Exception):
+ pass
+
+
class _MiniResp(object):
def __init__(self, error_message, env, headers=[]):
# The HEAD method is unique: it must never return a body, even if
@@ -947,19 +951,26 @@ class AuthProtocol(object):
_('Token authorization failed'))
self._confirm_token_bind(data, env)
else:
+ verified = None
# Token wasn't cached. In this case, the token needs to be
# checked that it's not expired, and also put in the cache.
- if cms.is_pkiz(token):
- verified = self._verify_pkiz_token(token, token_ids)
- data = jsonutils.loads(verified)
- expires = _confirm_token_not_expired(data)
- elif cms.is_asn1_token(token):
- verified = self._verify_signed_token(token, token_ids)
+ try:
+ if cms.is_pkiz(token):
+ verified = self._verify_pkiz_token(token, token_ids)
+ elif cms.is_asn1_token(token):
+ verified = self._verify_signed_token(token, token_ids)
+ except exceptions.CertificateConfigError:
+ self._LOG.warn(_LW('Fetch certificate config failed, '
+ 'fallback to online validation.'))
+ except RevocationListError:
+ self._LOG.warn(_LW('Fetch revocation list failed, '
+ 'fallback to online validation.'))
+
+ if verified is not None:
data = jsonutils.loads(verified)
expires = _confirm_token_not_expired(data)
else:
- data = self._identity_server.verify_token(token,
- retry)
+ data = self._identity_server.verify_token(token, retry)
# No need to confirm token expiration here since
# verify_token fails for expired tokens.
expires = _get_token_expiration(data)
@@ -1549,12 +1560,14 @@ class _IdentityServer(object):
authenticated=True,
endpoint_filter={'version': (2, 0)})
except exceptions.HTTPError as e:
- raise ServiceError(_('Failed to fetch token revocation list: %d') %
- e.http_status)
+ raise RevocationListError(_('Failed to fetch token revocation '
+ 'list: %d') % e.http_status)
if response.status_code != 200:
- raise ServiceError(_('Unable to fetch token revocation list.'))
+ raise RevocationListError(_('Unable to fetch token revocation '
+ 'list.'))
if 'signed' not in data:
- raise ServiceError(_('Revocation list improperly formatted.'))
+ raise RevocationListError(_('Revocation list improperly '
+ 'formatted.'))
return data['signed']
def fetch_signing_cert(self):
diff --git a/keystonemiddleware/tests/test_auth_token_middleware.py b/keystonemiddleware/tests/test_auth_token_middleware.py
index f35af8a..c5240b5 100644
--- a/keystonemiddleware/tests/test_auth_token_middleware.py
+++ b/keystonemiddleware/tests/test_auth_token_middleware.py
@@ -938,10 +938,10 @@ class CommonAuthTokenMiddlewareTest(object):
self.assertEqual(self.middleware._token_revocation_list,
in_memory_list)
- def test_invalid_revocation_list_raises_service_error(self):
+ def test_invalid_revocation_list_raises_error(self):
self.requests.get('%s/v2.0/tokens/revoked' % BASE_URI, json={})
- self.assertRaises(auth_token.ServiceError,
+ self.assertRaises(auth_token.RevocationListError,
self.middleware._fetch_revocation_list)
def test_fetch_revocation_list(self):
@@ -1796,6 +1796,31 @@ class v3AuthTokenMiddlewareTest(BaseAuthTokenMiddlewareTest,
self.assertIn('publicURL', endpoint)
self.assertIn('adminURL', endpoint)
+ def test_fallback_to_online_validation_with_signing_error(self):
+ self.requests.register_uri(
+ 'GET',
+ '%s/v3/OS-SIMPLE-CERT/certificates' % BASE_URI,
+ status_code=404)
+ self.assert_valid_request_200(self.token_dict['signed_token_scoped'])
+ self.assert_valid_request_200(
+ self.token_dict['signed_token_scoped_pkiz'])
+
+ def test_fallback_to_online_validation_with_ca_error(self):
+ self.requests.register_uri('GET',
+ '%s/v3/OS-SIMPLE-CERT/ca' % BASE_URI,
+ status_code=404)
+ self.assert_valid_request_200(self.token_dict['signed_token_scoped'])
+ self.assert_valid_request_200(
+ self.token_dict['signed_token_scoped_pkiz'])
+
+ def test_fallback_to_online_validation_with_revocation_list_error(self):
+ self.requests.register_uri('GET',
+ '%s/v2.0/tokens/revoked' % BASE_URI,
+ status_code=404)
+ self.assert_valid_request_200(self.token_dict['signed_token_scoped'])
+ self.assert_valid_request_200(
+ self.token_dict['signed_token_scoped_pkiz'])
+
class TokenEncodingTest(testtools.TestCase):
def test_unquoted_token(self):