From 9a0ec99e2da07863cb4ea032a1b0c6b5d959a149 Mon Sep 17 00:00:00 2001 From: termie Date: Tue, 21 Jun 2011 02:08:15 +0000 Subject: rudimentary login working --- bin/keystone | 3 ++- keystonelight/backends/pam.py | 11 +++++++--- keystonelight/keystone_compat.py | 17 ++++++++++----- keystonelight/service.py | 47 +++++++++++++++++++++++++++++++++------- 4 files changed, 61 insertions(+), 17 deletions(-) diff --git a/bin/keystone b/bin/keystone index a3309f6d..fa75bc01 100755 --- a/bin/keystone +++ b/bin/keystone @@ -23,6 +23,7 @@ from keystonelight import wsgi FLAGS = flags.FLAGS flags.DEFINE_boolean('verbose', True, 'verbose logging') +flags.DEFINE_flag(flags.HelpFlag()) if __name__ == '__main__': args = FLAGS(sys.argv) @@ -32,7 +33,7 @@ if __name__ == '__main__': public = service.Router() admin = service.AdminRouter() - public = service.PostParamsMiddleware(public) + public = service.JsonBodyMiddleware(public) server = wsgi.Server() server.start(public, 8080) diff --git a/keystonelight/backends/pam.py b/keystonelight/backends/pam.py index cfac3ed5..f50e1abb 100644 --- a/keystonelight/backends/pam.py +++ b/keystonelight/backends/pam.py @@ -11,11 +11,16 @@ class PamIdentity(object): Tenant is always the same as User, root user has admin role. """ - def authenticate(self, username, password): + def authenticate(self, username, password, **kwargs): if pam.authenticate(username, password): extras = {} if username == 'root': extras['is_admin'] == True - # NOTE(termie): (tenant, user, extras) - return (username, username, extras) + + tenant = {'id': username, + 'name': username} + user = {'id': username, + 'name': username} + + return (tenant, user, extras) diff --git a/keystonelight/keystone_compat.py b/keystonelight/keystone_compat.py index 680c9d93..7fc56646 100644 --- a/keystonelight/keystone_compat.py +++ b/keystonelight/keystone_compat.py @@ -1,15 +1,22 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 # this is the web service frontend that emulates keystone +import logging + from keystonelight import service def _token_to_keystone(token): - return {'id': token['id'], - 'expires': token.get('expires', '') + return {'id': token, + 'expires': ''} + + +SERVICE_CATALOG = {"cdn": [{"adminURL": "http://cdn.admin-nets.local/v1.1/1234", "region": "RegionOne", "internalURL": "http://33.33.33.10:7777/v1.1/1234", "publicURL": "http://cdn.publicinternets.com/v1.1/1234"}], "nova_compat": [{"adminURL": "http://33.33.33.10:8774/v1.0", "region": "RegionOne", "internalURL": "http://33.33.33.10:8774/v1.0", "publicURL": "http://nova.publicinternets.com/v1.0/"}], "nova": [{"adminURL": "http://33.33.33.10:8774/v1.1", "region": "RegionOne", "internalURL": "http://33.33.33.10:8774/v1.1", "publicURL": "http://nova.publicinternets.com/v1.1/"}], "keystone": [{"adminURL": "http://33.33.33.10:8081/v2.0", "region": "RegionOne", "internalURL": "http://33.33.33.10:8080/v2.0", "publicURL": "http://keystone.publicinternets.com/v2.0"}], "glance": [{"adminURL": "http://nova.admin-nets.local/v1.1/1234", "region": "RegionOne", "internalURL": "http://33.33.33.10:9292/v1.1/1234", "publicURL": "http://glance.publicinternets.com/v1.1/1234"}], "swift": [{"adminURL": "http://swift.admin-nets.local:8080/", "region": "RegionOne", "internalURL": "http://33.33.33.10:8080/v1/AUTH_1234", "publicURL": "http://swift.publicinternets.com/v1/AUTH_1234"}]} + class KeystoneIdentityController(service.IdentityController): def authenticate(self, context, **kwargs): + kwargs = kwargs['passwordCredentials'] token = super(KeystoneIdentityController, self).authenticate( context, **kwargs) return {'auth': {'token': _token_to_keystone(token), @@ -27,12 +34,12 @@ class KeystoneTokenController(service.TokenController): roles = [] if token['extras'].get('is_admin'): roles.append({ - 'id': 1, - 'href': 'https://.openstack.org/identity/v2.0/roles/admin', + 'roleId': 'Admin', + 'href': 'https://www.openstack.org/identity/v2.0/roles/admin', 'tenantId': token['tenant']['id']}) return {'auth': {'token': _token_to_keystone(token), 'user': {'groups': {'group': tenants}, - 'roleRefs': {'roleRef': roles} + 'roleRefs': roles, 'username': token['user']['name'], 'tenantId': token['tenant']['id']}}} diff --git a/keystonelight/service.py b/keystonelight/service.py index a06f99cb..758b44c9 100644 --- a/keystonelight/service.py +++ b/keystonelight/service.py @@ -76,6 +76,38 @@ class PostParamsMiddleware(wsgi.Middleware): 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= 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 + 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.""" @@ -83,8 +115,8 @@ class TokenController(BaseApplication): self.token_api = token.Manager() def validate_token(self, context, token_id): - token = self.token_api.validate_token(context, token_id) - return token + token_info = self.token_api.validate_token(context, token_id) + return token_info class IdentityController(BaseApplication): @@ -108,16 +140,15 @@ class IdentityController(BaseApplication): return token - class Router(wsgi.Router): def __init__(self): token_controller = utils.import_object(FLAGS.token_controller) identity_controller = utils.import_object(FLAGS.identity_controller) mapper = routes.Mapper() - mapper.connect('/v2.0/token', controller=identity_controller, + mapper.connect('/v2.0/tokens', controller=identity_controller, action='authenticate') - mapper.connect('/v2.0/token/{token_id}', controller=token_controller, + mapper.connect('/v2.0/tokens/{token_id}', controller=token_controller, action='revoke_token', conditions=dict(method=['DELETE'])) super(Router, self).__init__(mapper) @@ -129,12 +160,12 @@ class AdminRouter(wsgi.Router): identity_controller = utils.import_object(FLAGS.identity_controller) mapper = routes.Mapper() - mapper.connect('/v2.0/token', controller=identity_controller, + mapper.connect('/v2.0/tokens', controller=identity_controller, action='authenticate') - mapper.connect('/v2.0/token/{token_id}', controller=token_controller, + mapper.connect('/v2.0/tokens/{token_id}', controller=token_controller, action='validate_token', conditions=dict(method=['GET'])) - mapper.connect('/v2.0/token/{token_id}', controller=token_controller, + mapper.connect('/v2.0/tokens/{token_id}', controller=token_controller, action='revoke_token', conditions=dict(method=['DELETE'])) super(AdminRouter, self).__init__(mapper) -- cgit