Merge "Fix auth_token middleware to fetch revocation list as admin."

This commit is contained in:
Jenkins 2012-08-23 17:10:21 +00:00 committed by Gerrit Code Review
commit 84da6be591
6 changed files with 51 additions and 9 deletions

View File

@ -99,6 +99,7 @@
#key_size = 1024 #key_size = 1024
#valid_days = 3650 #valid_days = 3650
#ca_password = None #ca_password = None
#token_format = PKI
[ldap] [ldap]
# url = ldap://localhost # url = ldap://localhost

View File

@ -772,10 +772,14 @@ class AuthProtocol(object):
f.write(value) f.write(value)
def fetch_revocation_list(self): def fetch_revocation_list(self):
response, data = self._http_request('GET', '/v2.0/tokens/revoked') headers = {'X-Auth-Token': self.get_admin_token()}
response, data = self._json_request('GET', '/v2.0/tokens/revoked',
additional_headers=headers)
if response.status != 200: if response.status != 200:
raise ServiceError('Unable to fetch token revocation list.') raise ServiceError('Unable to fetch token revocation list.')
return self.cms_verify(data) if (not 'signed' in data):
raise ServiceError('Revocation list inmproperly formatted.')
return self.cms_verify(data['signed'])
def fetch_signing_cert(self): def fetch_signing_cert(self):
response, data = self._http_request('GET', response, data = self._http_request('GET',

View File

@ -551,7 +551,7 @@ class TokenController(wsgi.Application):
config.CONF.signing.certfile, config.CONF.signing.certfile,
config.CONF.signing.keyfile) config.CONF.signing.keyfile)
return signed_text return {'signed': signed_text}
def endpoints(self, context, token_id): def endpoints(self, context, token_id):
"""Return a list of endpoints available to the token.""" """Return a list of endpoints available to the token."""

View File

@ -32,8 +32,8 @@ from keystone import config
from keystone import test from keystone import test
#The data for these tests are signed using openssl and are stored in files # The data for these tests are signed using openssl and are stored in files
# in the signing subdirectory. IN order to keep the values consistent between # in the signing subdirectory. In order to keep the values consistent between
# the tests and the signed documents, we read them in for use in the tests. # the tests and the signed documents, we read them in for use in the tests.
def setUpModule(self): def setUpModule(self):
signing_path = os.path.join(os.path.dirname(__file__), 'signing') signing_path = os.path.join(os.path.dirname(__file__), 'signing')
@ -47,7 +47,8 @@ def setUpModule(self):
with open(os.path.join(signing_path, 'revocation_list.json')) as f: with open(os.path.join(signing_path, 'revocation_list.json')) as f:
self.REVOCATION_LIST = jsonutils.loads(f.read()) self.REVOCATION_LIST = jsonutils.loads(f.read())
with open(os.path.join(signing_path, 'revocation_list.pem')) as f: with open(os.path.join(signing_path, 'revocation_list.pem')) as f:
self.SIGNED_REVOCATION_LIST = f.read() self.VALID_SIGNED_REVOCATION_LIST =\
jsonutils.dumps({'signed': f.read()})
self.TOKEN_RESPONSES[self.SIGNED_TOKEN_SCOPED] = { self.TOKEN_RESPONSES[self.SIGNED_TOKEN_SCOPED] = {
'access': { 'access': {
@ -225,7 +226,7 @@ class FakeHTTPConnection(object):
last_requested_url = '' last_requested_url = ''
def __init__(self, *args): def __init__(self, *args):
pass self.send_valid_revocation_list = True
def request(self, method, path, **kwargs): def request(self, method, path, **kwargs):
"""Fakes out several http responses. """Fakes out several http responses.
@ -319,6 +320,9 @@ class BaseAuthTokenMiddlewareTest(test.TestCase):
self.middleware.token_revocation_list = jsonutils.dumps( self.middleware.token_revocation_list = jsonutils.dumps(
{"revoked": [], "extra": "success"}) {"revoked": [], "extra": "success"})
globals()['SIGNED_REVOCATION_LIST'] =\
globals()['VALID_SIGNED_REVOCATION_LIST']
super(BaseAuthTokenMiddlewareTest, self).setUp() super(BaseAuthTokenMiddlewareTest, self).setUp()
def tearDown(self): def tearDown(self):
@ -478,6 +482,11 @@ class AuthTokenMiddlewareTest(BaseAuthTokenMiddlewareTest):
self.middleware._token_revocation_list = None self.middleware._token_revocation_list = None
self.assertEqual(self.middleware.token_revocation_list, in_memory_list) self.assertEqual(self.middleware.token_revocation_list, in_memory_list)
def test_invalid_revocation_list_raises_service_error(self):
globals()['SIGNED_REVOCATION_LIST'] = "{}"
with self.assertRaises(auth_token.ServiceError):
self.middleware.fetch_revocation_list()
def test_fetch_revocation_list(self): def test_fetch_revocation_list(self):
fetched_list = jsonutils.loads(self.middleware.fetch_revocation_list()) fetched_list = jsonutils.loads(self.middleware.fetch_revocation_list())
self.assertEqual(fetched_list, REVOCATION_LIST) self.assertEqual(fetched_list, REVOCATION_LIST)

View File

@ -220,11 +220,15 @@ class RestfulTestCase(test.TestCase):
def public_request(self, port=None, **kwargs): def public_request(self, port=None, **kwargs):
kwargs['port'] = port or self._public_port() kwargs['port'] = port or self._public_port()
return self.restful_request(**kwargs) response = self.restful_request(**kwargs)
self.assertValidResponseHeaders(response)
return response
def admin_request(self, port=None, **kwargs): def admin_request(self, port=None, **kwargs):
kwargs['port'] = port or self._admin_port() kwargs['port'] = port or self._admin_port()
return self.restful_request(**kwargs) response = self.restful_request(**kwargs)
self.assertValidResponseHeaders(response)
return response
def get_scoped_token(self): def get_scoped_token(self):
"""Convenience method so that we can test authenticated requests.""" """Convenience method so that we can test authenticated requests."""
@ -621,6 +625,25 @@ class JsonTestCase(RestfulTestCase, CoreApiTests):
r = self.admin_request(path=path, expected_status=401) r = self.admin_request(path=path, expected_status=401)
self.assertValidErrorResponse(r) self.assertValidErrorResponse(r)
def test_fetch_revocation_list_nonadmin_fails(self):
r = self.admin_request(
method='GET',
path='/v2.0/tokens/revoked',
expected_status=401)
def test_fetch_revocation_list_admin_200(self):
token = self.get_scoped_token()
r = self.restful_request(
method='GET',
path='/v2.0/tokens/revoked',
token=token,
expected_status=200,
port=self._admin_port())
self.assertValidRevocationListResponse(r)
def assertValidRevocationListResponse(self, response):
self.assertIsNotNone(response.body['signed'])
class XmlTestCase(RestfulTestCase, CoreApiTests): class XmlTestCase(RestfulTestCase, CoreApiTests):
xmlns = 'http://docs.openstack.org/identity/api/v2.0' xmlns = 'http://docs.openstack.org/identity/api/v2.0'

View File

@ -7,3 +7,8 @@ driver = keystone.identity.backends.kvs.Identity
[catalog] [catalog]
driver = keystone.catalog.backends.templated.TemplatedCatalog driver = keystone.catalog.backends.templated.TemplatedCatalog
template_file = default_catalog.templates template_file = default_catalog.templates
[signing]
certfile = signing/signing_cert.pem
keyfile = signing/private_key.pem
ca_certs = signing/cacert.pem