move around middleware
This commit is contained in:
parent
716c450fbf
commit
d7f364e209
|
@ -0,0 +1,96 @@
|
|||
import json
|
||||
|
||||
from keystonelight import wsgi
|
||||
|
||||
|
||||
# Header used to transmit the auth token
|
||||
AUTH_TOKEN_HEADER = 'X-Auth-Token'
|
||||
|
||||
|
||||
# Environment variable used to pass the request context
|
||||
CONTEXT_ENV = 'openstack.context'
|
||||
|
||||
|
||||
# Environment variable used to pass the request params
|
||||
PARAMS_ENV = 'openstack.params'
|
||||
|
||||
|
||||
class TokenAuthMiddleware(wsgi.Middleware):
|
||||
def process_request(self, request):
|
||||
token = request.headers.get(AUTH_TOKEN_HEADER)
|
||||
context = request.environ.get(CONTEXT_ENV, {})
|
||||
context['token_id'] = token
|
||||
request.environ[CONTEXT_ENV] = context
|
||||
|
||||
|
||||
class AdminTokenAuthMiddleware(wsgi.Middleware):
|
||||
"""A trivial filter that checks for a pre-defined admin token.
|
||||
|
||||
Sets 'is_admin' to true in the context, expected to be checked by
|
||||
methods that are admin-only.
|
||||
|
||||
"""
|
||||
|
||||
def process_request(self, request):
|
||||
token = request.headers.get(AUTH_TOKEN_HEADER)
|
||||
context = request.environ.get(CONTEXT_ENV, {})
|
||||
context['is_admin'] = (token == self.options['admin_token'])
|
||||
request.environ[CONTEXT_ENV] = context
|
||||
|
||||
|
||||
class PostParamsMiddleware(wsgi.Middleware):
|
||||
"""Middleware to allow method arguments to be passed as POST parameters.
|
||||
|
||||
Filters out the parameters `self`, `context` and anything beginning with
|
||||
an underscore.
|
||||
|
||||
"""
|
||||
|
||||
def process_request(self, request):
|
||||
params_parsed = request.params
|
||||
params = {}
|
||||
for k, v in params_parsed.iteritems():
|
||||
if k in ('self', 'context'):
|
||||
continue
|
||||
if k.startswith('_'):
|
||||
continue
|
||||
params[k] = v
|
||||
|
||||
request.environ[PARAMS_ENV] = params
|
||||
|
||||
|
||||
class JsonBodyMiddleware(wsgi.Middleware):
|
||||
"""Middleware to allow method arguments to be passed as serialized JSON.
|
||||
|
||||
Accepting arguments as JSON is useful for accepting data that may be more
|
||||
complex than simple primitives.
|
||||
|
||||
In this case we accept it as urlencoded data under the key 'json' as in
|
||||
json=<urlencoded_json> but this could be extended to accept raw JSON
|
||||
in the POST body.
|
||||
|
||||
Filters out the parameters `self`, `context` and anything beginning with
|
||||
an underscore.
|
||||
|
||||
"""
|
||||
|
||||
def process_request(self, request):
|
||||
#if 'json' not in request.params:
|
||||
# return
|
||||
|
||||
params_json = request.body
|
||||
if not params_json:
|
||||
return
|
||||
|
||||
params_parsed = json.loads(params_json)
|
||||
params = {}
|
||||
for k, v in params_parsed.iteritems():
|
||||
if k in ('self', 'context'):
|
||||
continue
|
||||
if k.startswith('_'):
|
||||
continue
|
||||
params[k] = v
|
||||
|
||||
request.environ[PARAMS_ENV] = params
|
||||
|
||||
|
|
@ -44,84 +44,6 @@ class BaseApplication(wsgi.Application):
|
|||
return json.dumps(result)
|
||||
|
||||
|
||||
class TokenAuthMiddleware(wsgi.Middleware):
|
||||
def process_request(self, request):
|
||||
token = request.headers.get('X-Auth-Token')
|
||||
context = request.environ.get('openstack.context', {})
|
||||
context['token_id'] = token
|
||||
request.environ['openstack.context'] = context
|
||||
|
||||
|
||||
class AdminTokenAuthMiddleware(wsgi.Middleware):
|
||||
"""A trivial filter that checks for a pre-defined admin token.
|
||||
|
||||
Sets 'is_admin' to true in the context, expected to be checked by
|
||||
methods that are admin-only.
|
||||
|
||||
"""
|
||||
def process_request(self, request):
|
||||
token = request.headers.get('X-Auth-Token')
|
||||
context = request.environ.get('openstack.context', {})
|
||||
context['is_admin'] = (token == self.options['admin_token'])
|
||||
request.environ['openstack.context'] = context
|
||||
|
||||
|
||||
class PostParamsMiddleware(wsgi.Middleware):
|
||||
"""Middleware to allow method arguments to be passed as POST parameters.
|
||||
|
||||
Filters out the parameters `self`, `context` and anything beginning with
|
||||
an underscore.
|
||||
|
||||
"""
|
||||
|
||||
def process_request(self, request):
|
||||
params_parsed = request.params
|
||||
params = {}
|
||||
for k, v in params_parsed.iteritems():
|
||||
if k in ('self', 'context'):
|
||||
continue
|
||||
if k.startswith('_'):
|
||||
continue
|
||||
params[k] = v
|
||||
|
||||
request.environ['openstack.params'] = params
|
||||
|
||||
|
||||
class JsonBodyMiddleware(wsgi.Middleware):
|
||||
"""Middleware to allow method arguments to be passed as serialized JSON.
|
||||
|
||||
Accepting arguments as JSON is useful for accepting data that may be more
|
||||
complex than simple primitives.
|
||||
|
||||
In this case we accept it as urlencoded data under the key 'json' as in
|
||||
json=<urlencoded_json> but this could be extended to accept raw JSON
|
||||
in the POST body.
|
||||
|
||||
Filters out the parameters `self`, `context` and anything beginning with
|
||||
an underscore.
|
||||
|
||||
"""
|
||||
|
||||
def process_request(self, request):
|
||||
#if 'json' not in request.params:
|
||||
# return
|
||||
|
||||
params_json = request.body
|
||||
if not params_json:
|
||||
return
|
||||
|
||||
params_parsed = json.loads(params_json)
|
||||
params = {}
|
||||
for k, v in params_parsed.iteritems():
|
||||
if k in ('self', 'context'):
|
||||
continue
|
||||
if k.startswith('_'):
|
||||
continue
|
||||
params[k] = v
|
||||
|
||||
request.environ['openstack.params'] = params
|
||||
|
||||
|
||||
class TokenController(BaseApplication):
|
||||
"""Validate and pass through calls to TokenManager."""
|
||||
|
||||
|
@ -169,51 +91,23 @@ class IdentityController(BaseApplication):
|
|||
class Router(wsgi.Router):
|
||||
def __init__(self, options):
|
||||
self.options = options
|
||||
token_controller = utils.import_object(
|
||||
options['token_controller'],
|
||||
options=options)
|
||||
identity_controller = utils.import_object(
|
||||
options['identity_controller'],
|
||||
options=options)
|
||||
self.identity_controller = IdentityController(options)
|
||||
self.token_controller = TokenController(options)
|
||||
mapper = routes.Mapper()
|
||||
mapper.connect('/v2.0/tokens', controller=identity_controller,
|
||||
mapper.connect('/v2.0/tokens',
|
||||
controller=self.identity_controller,
|
||||
action='authenticate')
|
||||
mapper.connect('/v2.0/tokens/{token_id}', controller=token_controller,
|
||||
mapper.connect('/v2.0/tokens/{token_id}',
|
||||
controller=self.token_controller,
|
||||
action='revoke_token',
|
||||
conditions=dict(method=['DELETE']))
|
||||
mapper.connect("/v2.0/tenants", controller=identity_controller,
|
||||
action="get_tenants", conditions=dict(method=["GET"]))
|
||||
mapper.connect("/v2.0/tenants",
|
||||
controller=self.identity_controller,
|
||||
action="get_tenants",
|
||||
conditions=dict(method=["GET"]))
|
||||
super(Router, self).__init__(mapper)
|
||||
|
||||
|
||||
class AdminRouter(wsgi.Router):
|
||||
def __init__(self, options):
|
||||
self.options = options
|
||||
token_controller = utils.import_object(
|
||||
options['token_controller'],
|
||||
options=options)
|
||||
identity_controller = utils.import_object(
|
||||
options['identity_controller'],
|
||||
options=options)
|
||||
mapper = routes.Mapper()
|
||||
|
||||
mapper.connect('/v2.0/tokens', controller=identity_controller,
|
||||
action='authenticate')
|
||||
mapper.connect('/v2.0/tokens/{token_id}', controller=token_controller,
|
||||
action='validate_token',
|
||||
conditions=dict(method=['GET']))
|
||||
mapper.connect('/v2.0/tokens/{token_id}', controller=token_controller,
|
||||
action='revoke_token',
|
||||
conditions=dict(method=['DELETE']))
|
||||
super(AdminRouter, self).__init__(mapper)
|
||||
|
||||
|
||||
def identity_app_factory(global_conf, **local_conf):
|
||||
conf = global_conf.copy()
|
||||
conf.update(local_conf)
|
||||
return Router(conf)
|
||||
|
||||
|
||||
def app_factory(global_conf, **local_conf):
|
||||
conf = global_conf.copy()
|
||||
conf.update(local_conf)
|
||||
|
|
|
@ -24,13 +24,13 @@ catalog.RegionOne.compute.name = 'Compute Service'
|
|||
paste.filter_factory = keystonelight.wsgi:Debug.factory
|
||||
|
||||
[filter:token_auth]
|
||||
paste.filter_factory = keystonelight.service:TokenAuthMiddleware.factory
|
||||
paste.filter_factory = keystonelight.middleware:TokenAuthMiddleware.factory
|
||||
|
||||
[filter:admin_token_auth]
|
||||
paste.filter_factory = keystonelight.service:AdminTokenAuthMiddleware.factory
|
||||
paste.filter_factory = keystonelight.middleware:AdminTokenAuthMiddleware.factory
|
||||
|
||||
[filter:json_body]
|
||||
paste.filter_factory = keystonelight.service:JsonBodyMiddleware.factory
|
||||
paste.filter_factory = keystonelight.middleware:JsonBodyMiddleware.factory
|
||||
|
||||
[app:keystonelight]
|
||||
paste.app_factory = keystonelight.service:app_factory
|
||||
|
|
|
@ -0,0 +1,166 @@
|
|||
import uuid
|
||||
|
||||
from keystonelight import models
|
||||
from keystonelight import test
|
||||
from keystonelight import utils
|
||||
from keystonelight.backends import kvs
|
||||
|
||||
|
||||
class IdentityApi(test.TestCase):
|
||||
def setUp(self):
|
||||
super(IdentityApi, self).setUp()
|
||||
self.options = self.appconfig('default')
|
||||
app = self.loadapp('default')
|
||||
self.app = app
|
||||
|
||||
self.identity_backend = utils.import_object(
|
||||
self.options['identity_driver'], options=self.options)
|
||||
self.token_backend = utils.import_object(
|
||||
self.options['token_driver'], options=self.options)
|
||||
self.catalog_backend = utils.import_object(
|
||||
self.options['catalog_driver'], options=self.options)
|
||||
self._load_fixtures()
|
||||
|
||||
def _load_fixtures(self):
|
||||
self.tenant_bar = self.identity_backend._create_tenant(
|
||||
'bar',
|
||||
models.Tenant(id='bar', name='BAR'))
|
||||
self.user_foo = self.identity_backend._create_user(
|
||||
'foo',
|
||||
models.User(id='foo',
|
||||
name='FOO',
|
||||
password='foo2',
|
||||
tenants=[self.tenant_bar['id']]))
|
||||
self.extras_foobar = self.identity_backend._create_extras(
|
||||
'foo', 'bar',
|
||||
{'extra': 'extra'})
|
||||
|
||||
def test_authenticate_bad_user(self):
|
||||
self.assertRaises(AssertionError,
|
||||
self.identity_api.authenticate,
|
||||
user_id=self.user_foo['id'] + 'WRONG',
|
||||
tenant_id=self.tenant_bar['id'],
|
||||
password=self.user_foo['password'])
|
||||
|
||||
def test_authenticate_bad_password(self):
|
||||
self.assertRaises(AssertionError,
|
||||
self.identity_api.authenticate,
|
||||
user_id=self.user_foo['id'],
|
||||
tenant_id=self.tenant_bar['id'],
|
||||
password=self.user_foo['password'] + 'WRONG')
|
||||
|
||||
def test_authenticate_invalid_tenant(self):
|
||||
self.assertRaises(AssertionError,
|
||||
self.identity_api.authenticate,
|
||||
user_id=self.user_foo['id'],
|
||||
tenant_id=self.tenant_bar['id'] + 'WRONG',
|
||||
password=self.user_foo['password'])
|
||||
|
||||
def test_authenticate_no_tenant(self):
|
||||
user_ref, tenant_ref, extras_ref = self.identity_api.authenticate(
|
||||
user_id=self.user_foo['id'],
|
||||
password=self.user_foo['password'])
|
||||
self.assertDictEquals(user_ref, self.user_foo)
|
||||
self.assert_(tenant_ref is None)
|
||||
self.assert_(extras_ref is None)
|
||||
|
||||
def test_authenticate(self):
|
||||
user_ref, tenant_ref, extras_ref = self.identity_api.authenticate(
|
||||
user_id=self.user_foo['id'],
|
||||
tenant_id=self.tenant_bar['id'],
|
||||
password=self.user_foo['password'])
|
||||
self.assertDictEquals(user_ref, self.user_foo)
|
||||
self.assertDictEquals(tenant_ref, self.tenant_bar)
|
||||
self.assertDictEquals(extras_ref, self.extras_foobar)
|
||||
|
||||
def test_get_tenant_bad_tenant(self):
|
||||
tenant_ref = self.identity_api.get_tenant(
|
||||
tenant_id=self.tenant_bar['id'] + 'WRONG')
|
||||
self.assert_(tenant_ref is None)
|
||||
|
||||
def test_get_tenant(self):
|
||||
tenant_ref = self.identity_api.get_tenant(tenant_id=self.tenant_bar['id'])
|
||||
self.assertDictEquals(tenant_ref, self.tenant_bar)
|
||||
|
||||
def test_get_tenant_by_name_bad_tenant(self):
|
||||
tenant_ref = self.identity_api.get_tenant(
|
||||
tenant_id=self.tenant_bar['name'] + 'WRONG')
|
||||
self.assert_(tenant_ref is None)
|
||||
|
||||
def test_get_tenant_by_name(self):
|
||||
tenant_ref = self.identity_api.get_tenant_by_name(
|
||||
tenant_name=self.tenant_bar['name'])
|
||||
self.assertDictEquals(tenant_ref, self.tenant_bar)
|
||||
|
||||
def test_get_user_bad_user(self):
|
||||
user_ref = self.identity_api.get_user(
|
||||
user_id=self.user_foo['id'] + 'WRONG')
|
||||
self.assert_(user_ref is None)
|
||||
|
||||
def test_get_user(self):
|
||||
user_ref = self.identity_api.get_user(user_id=self.user_foo['id'])
|
||||
self.assertDictEquals(user_ref, self.user_foo)
|
||||
|
||||
def test_get_extras_bad_user(self):
|
||||
extras_ref = self.identity_api.get_extras(
|
||||
user_id=self.user_foo['id'] + 'WRONG',
|
||||
tenant_id=self.tenant_bar['id'])
|
||||
self.assert_(extras_ref is None)
|
||||
|
||||
def test_get_extras_bad_tenant(self):
|
||||
extras_ref = self.identity_api.get_extras(
|
||||
user_id=self.user_foo['id'],
|
||||
tenant_id=self.tenant_bar['id'] + 'WRONG')
|
||||
self.assert_(extras_ref is None)
|
||||
|
||||
def test_get_extras(self):
|
||||
extras_ref = self.identity_api.get_extras(
|
||||
user_id=self.user_foo['id'],
|
||||
tenant_id=self.tenant_bar['id'])
|
||||
self.assertDictEquals(extras_ref, self.extras_foobar)
|
||||
|
||||
|
||||
class KvsToken(test.TestCase):
|
||||
def setUp(self):
|
||||
super(KvsToken, self).setUp()
|
||||
options = self.appconfig('default')
|
||||
self.token_api = kvs.KvsToken(options=options, db={})
|
||||
|
||||
def test_token_crud(self):
|
||||
token_id = uuid.uuid4().hex
|
||||
data = {'id': token_id,
|
||||
'a': 'b'}
|
||||
data_ref = self.token_api.create_token(token_id, data)
|
||||
self.assertDictEquals(data_ref, data)
|
||||
|
||||
new_data_ref = self.token_api.get_token(token_id)
|
||||
self.assertEquals(new_data_ref, data)
|
||||
|
||||
self.token_api.delete_token(token_id)
|
||||
deleted_data_ref = self.token_api.get_token(token_id)
|
||||
self.assert_(deleted_data_ref is None)
|
||||
|
||||
|
||||
class KvsCatalog(test.TestCase):
|
||||
def setUp(self):
|
||||
super(KvsCatalog, self).setUp()
|
||||
options = self.appconfig('default')
|
||||
self.catalog_api = kvs.KvsCatalog(options=options, db={})
|
||||
self._load_fixtures()
|
||||
|
||||
def _load_fixtures(self):
|
||||
self.catalog_foobar = self.catalog_api._create_catalog(
|
||||
'foo', 'bar',
|
||||
{'RegionFoo': {'service_bar': {'foo': 'bar'}}})
|
||||
|
||||
def test_get_catalog_bad_user(self):
|
||||
catalog_ref = self.catalog_api.get_catalog('foo' + 'WRONG', 'bar')
|
||||
self.assert_(catalog_ref is None)
|
||||
|
||||
def test_get_catalog_bad_tenant(self):
|
||||
catalog_ref = self.catalog_api.get_catalog('foo', 'bar' + 'WRONG')
|
||||
self.assert_(catalog_ref is None)
|
||||
|
||||
def test_get_catalog(self):
|
||||
catalog_ref = self.catalog_api.get_catalog('foo', 'bar')
|
||||
self.assertDictEquals(catalog_ref, self.catalog_foobar)
|
Loading…
Reference in New Issue