diff options
author | Jenkins <jenkins@review.openstack.org> | 2015-02-09 23:31:00 +0000 |
---|---|---|
committer | Gerrit Code Review <review@openstack.org> | 2015-02-09 23:31:00 +0000 |
commit | 2b98d531841da649ffc8dbf79495cf6942f98cad (patch) | |
tree | c7c41c5674a481c3235773bb1a49932fac87cf5a | |
parent | bf700779e12b5e6e47fd8e96362625bf909115e5 (diff) | |
parent | 136f85c01ad4da01f9e073619f22eed5ca2378cc (diff) | |
download | keystonemiddleware-2b98d531841da649ffc8dbf79495cf6942f98cad.tar.gz |
Merge "fallback to online validation if offline validation fails"
-rw-r--r-- | keystonemiddleware/auth_token.py | 37 | ||||
-rw-r--r-- | keystonemiddleware/tests/test_auth_token_middleware.py | 29 |
2 files changed, 52 insertions, 14 deletions
diff --git a/keystonemiddleware/auth_token.py b/keystonemiddleware/auth_token.py index 7aa7d6b..33476eb 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 @@ -940,19 +944,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) @@ -1563,12 +1574,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 a5bfbc4..b9bff1c 100644 --- a/keystonemiddleware/tests/test_auth_token_middleware.py +++ b/keystonemiddleware/tests/test_auth_token_middleware.py @@ -961,10 +961,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): @@ -1817,6 +1817,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): |