authenticate working, too

This commit is contained in:
termie 2011-10-19 16:23:33 +03:00
parent ba4913f463
commit d920d8432a
8 changed files with 179 additions and 46 deletions

View File

@ -15,6 +15,18 @@ class KvsIdentity(object):
self.db = db
# Public interface
def authenticate(self, user_id=None, tenant_id=None, password=None):
user_ref = self.get_user(user_id)
tenant_ref = None
extras_ref = None
if user_ref['password'] != password:
raise AssertionError('Invalid user / password')
if tenant_id and tenant_id in user_ref['tenants']:
tenant_ref = self.get_tenant(tenant_id)
extras_ref = self.get_extras(user_id, tenant_id)
return (user_ref, tenant_ref, extras_ref)
def get_tenant(self, tenant_id):
tenant_ref = self.db.get('tenant-%s' % tenant_id)
return tenant_ref
@ -23,6 +35,9 @@ class KvsIdentity(object):
user_ref = self.db.get('user-%s' % user_id)
return user_ref
def get_extras(self, user_id, tenant_id):
return self.db.get('extras-%s-%s' % (user_id, tenant_id))
# Private CRUD for testing
def _create_user(self, id, user):
self.db.set('user-%s' % id, user)
@ -32,6 +47,12 @@ class KvsIdentity(object):
self.db.set('tenant-%s' % id, tenant)
return tenant
def _create_extras(self, user_id, tenant_id, extras):
self.db.set('extras-%s-%s' % (user_id, tenant_id), extras)
return extras
class KvsToken(object):
def __init__(self, options, db=None):
@ -58,5 +79,9 @@ class KvsCatalog(object):
self.db = db
# Public interface
def get_catalog(self, user, tenant, extras=None):
return self.db.get('catalog-%s' % tenant['id'])
def get_catalog(self, user_id, tenant_id, extras=None):
return self.db.get('catalog-%s' % tenant_id)
# Private interface
def _create_catalog(self, user_id, tenant_id, data):
self.db.set('catalog-%s' % tenant_id, data)

View File

@ -13,6 +13,6 @@ class Manager(object):
self.driver = utils.import_object(options['catalog_driver'],
options=options)
def get_catalog(self, user, tenant, extras=None):
def get_catalog(self, context, user_id, tenant_id, extras=None):
"""Return info for a catalog if it is valid."""
return self.driver.get_catalog(user, tenant, extras=extras)
return self.driver.get_catalog(user_id, tenant_id, extras=extras)

View File

@ -69,19 +69,21 @@ class KeystoneController(service.BaseApplication):
password = auth['passwordCredentials'].get('password', '')
tenant = auth.get('tenantName', None)
(user_ref, tenant_ref, extras) = \
(user_ref, tenant_ref, extras_ref) = \
self.identity_api.authenticate(context=context,
user_id=username,
password=password,
tenant_id=tenant)
token_ref = self.token_api.create_token(context=context,
user=user_ref,
tenant=tenant_ref,
extras=extras)
catalog_ref = self.catalog_api.get_catalog(context=context,
user=user_ref,
tenant=tenant_ref,
extras=extras)
token_ref = self.token_api.create_token(context,
dict(expires='',
user=user_ref,
tenant=tenant_ref,
extras=extras_ref))
catalog_ref = self.catalog_api.get_catalog(
context=context,
user_id=user_ref['id'],
tenant_id=tenant_ref['id'],
extras=extras_ref)
elif 'tokenCredentials' in auth:
token = auth['tokenCredentials'].get('token', None)
@ -95,23 +97,27 @@ class KeystoneController(service.BaseApplication):
tenant_ref = self.identity_api.get_tenant(context=context,
tenant_id=tenant)
extras = self.identity_api.get_extras(
extras_ref = self.identity_api.get_extras(
context=context,
user_id=user_ref['id'],
tenant_id=tenant_ref['tenant']['id'])
token_ref = self.token_api.create_token(context=context,
user=user_ref,
tenant=tenant_ref,
extras=extras)
catalog_ref = self.catalog_api.get_catalog(context=context,
user=user_ref,
tenant=tenant_ref,
extras=extras)
token_ref = self.token_api.create_token(context,
dict(expires='',
user=user_ref,
tenant=tenant_ref,
extras=extras_ref))
catalog_ref = self.catalog_api.get_catalog(
context=context,
user_id=user_ref['id'],
tenant_id=tenant_ref['id'],
extras=extras_ref)
return self._format_authenticate(token_ref, catalog_ref)
def _format_authenticate(sef, token_ref, catalog_ref):
return {}
def _format_authenticate(self, token_ref, catalog_ref):
o = self._format_token(token_ref)
o['access']['serviceCatalog'] = catalog_ref
return o
#admin-only
def validate_token(self, context, token_id, belongs_to=None):
@ -128,13 +134,14 @@ class KeystoneController(service.BaseApplication):
def _format_token(self, token_ref):
user_ref = token_ref['user']
extras_ref = token_ref['extras']
o = {'access': {'token': {'id': token_ref['id'],
'expires': token_ref['expires']
},
'user': {'id': user_ref['id'],
'name': user_ref['name'],
'roles': user_ref['roles'] or [],
'roles_links': user_ref['roles_links'] or []
'roles': extras_ref['roles'] or [],
'roles_links': extras_ref['roles_links'] or []
}
}
}

View File

@ -94,6 +94,7 @@ class JsonBodyMiddleware(wsgi.Middleware):
params_json = request.body
if not params_json:
print "ASDASDASDASD"
return
params_parsed = json.loads(params_json)

View File

@ -27,7 +27,7 @@ class TestClient(object):
req.method = method
for k, v in headers.iteritems():
req.headers[k] = v
if req.body:
if body:
req.body = body
return req.get_response(self.app)
@ -57,20 +57,20 @@ class TestCase(unittest.TestCase):
def assertListEquals(self, expected, actual):
copy = expected[:]
print expected, actual
#print expected, actual
self.assertEquals(len(expected), len(actual))
while copy:
item = copy.pop()
matched = False
for x in actual:
print 'COMPARE', item, x,
#print 'COMPARE', item, x,
try:
self.assertDeepEquals(item, x)
matched = True
print 'MATCHED'
#print 'MATCHED'
break
except AssertionError as e:
print e
#print e
pass
if not matched:
raise AssertionError('Expected: %s\n Got: %s' % (expected, actual))

View File

@ -228,6 +228,11 @@ class Debug(Middleware):
for key, value in req.environ.items():
logging.debug('%s = %s', key, value)
logging.debug('')
logging.debug('%s %s %s', ('*' * 20), 'REQUEST BODY', ('*' * 20))
for line in req.body_file:
logging.debug(line)
logging.debug('')
resp = req.get_response(self.application)
@ -243,10 +248,10 @@ class Debug(Middleware):
@staticmethod
def print_generator(app_iter):
"""Iterator that prints the contents of a wrapper string."""
print ('*' * 40) + ' BODY'
logging.debug('%s %s %s', ('*' * 20), 'RESPONSE BODY', ('*' * 20))
for part in app_iter:
sys.stdout.write(part)
sys.stdout.flush()
#sys.stdout.flush()
yield part
print

View File

@ -0,0 +1,53 @@
[{
"name":"Cloud Servers",
"type":"compute",
"endpoints":[{
"tenantId":"1",
"publicURL":"https://compute.north.host/v1/1234",
"internalURL":"https://compute.north.host/v1/1234",
"region":"North",
"versionId":"1.0",
"versionInfo":"https://compute.north.host/v1.0/",
"versionList":"https://compute.north.host/"
},
{
"tenantId":"2",
"publicURL":"https://compute.north.host/v1.1/3456",
"internalURL":"https://compute.north.host/v1.1/3456",
"region":"North",
"versionId":"1.1",
"versionInfo":"https://compute.north.host/v1.1/",
"versionList":"https://compute.north.host/"
}
],
"endpoints_links":[]
},
{
"name":"Cloud Files",
"type":"object-store",
"endpoints":[{
"tenantId":"11",
"publicURL":"https://compute.north.host/v1/blah-blah",
"internalURL":"https://compute.north.host/v1/blah-blah",
"region":"South",
"versionId":"1.0",
"versionInfo":"uri",
"versionList":"uri"
},
{
"tenantId":"2",
"publicURL":"https://compute.north.host/v1.1/blah-blah",
"internalURL":"https://compute.north.host/v1.1/blah-blah",
"region":"South",
"versionId":"1.1",
"versionInfo":"https://compute.north.host/v1.1/",
"versionList":"https://compute.north.host/"
}
],
"endpoints_links":[{
"rel":"next",
"href":"https://identity.north.host/v2.0/endpoints?marker=2"
}
]
}
]

View File

@ -2,6 +2,7 @@ import copy
import os
import json
from keystonelight import logging
from keystonelight import models
from keystonelight import test
from keystonelight import utils
@ -35,15 +36,16 @@ class CompatTestCase(test.TestCase):
def setUp(self):
super(CompatTestCase, self).setUp()
self.auth_creds = json.load(open(
os.path.join(self.sampledir, 'auth_credentials.json')))
self.auth_creds_notenant = copy.deepcopy(self.auth_creds)
self.auth_creds_notenant['auth'].pop('tenantName', None)
self.tenants_for_token = json.load(open(
os.path.join(self.sampledir, 'tenants.json')))
self.validate_token = json.load(open(
os.path.join(self.sampledir, 'validatetoken.json')))
# NOTE(termie): stupid hack to deal with the keystone samples being
# completely inconsistent
self.validate_token['access']['user']['roles'][1]['id'] = u'235'
self.auth_response = json.load(open(
os.path.join(self.sampledir, 'auth.json')))
# validate_token call
self.tenant_345 = self.identity_backend._create_tenant(
@ -51,19 +53,36 @@ class CompatTestCase(test.TestCase):
models.Tenant(id='345', name='My Project'))
self.user_123 = self.identity_backend._create_user(
'123',
models.User(id='123', name='jqsmith', tenants=[self.tenant_345['id']],
roles=[{'id': '234',
'name': 'compute:admin'},
{'id': '234',
'name': 'object-store:admin',
'tenantId': '1'}],
roles_links=[]))
models.User(id='123',
name='jqsmith',
tenants=[self.tenant_345['id']],
password='password'))
self.extras_123 = self.identity_backend._create_extras(
self.user_123['id'], self.tenant_345['id'],
dict(roles=[{'id': '234',
'name': 'compute:admin'},
{'id': '235',
'name': 'object-store:admin',
'tenantId': '1'}],
roles_links=[]))
self.token_123 = self.token_backend.create_token(
'ab48a9efdfedb23ty3494',
models.Token(id='ab48a9efdfedb23ty3494',
expires='2010-11-01T03:32:15-05:00',
user=self.user_123,
tenant=self.tenant_345))
tenant=self.tenant_345,
extras=self.extras_123))
# auth call
# NOTE(termie): the service catalog in the sample doesn't really have
# anything to do with the auth being returned, so just load
# it fully from a fixture and add it to our db
catalog = json.load(open(
os.path.join(os.path.dirname(__file__),
'keystone_compat_diablo_sample_catalog.json')))
self.catalog_backend._create_catalog(self.user_123['id'],
self.tenant_345['id'],
catalog)
# tenants_for_token call
self.user_foo = self.identity_backend._create_user(
@ -109,6 +128,29 @@ class DiabloCompatTestCase(CompatTestCase):
super(DiabloCompatTestCase, self).setUp()
def test_authenticate_scoped(self):
client = self.client(self.app)
post_data = json.dumps(
{'auth': {'passwordCredentials': {'username': self.user_123['id'],
'password': self.user_123['password'],
},
'tenantName': self.tenant_345['id']}})
resp = client.post('/v2.0/tokens', body=post_data)
data = json.loads(resp.body)
logging.debug('KEYS: %s', data['access'].keys())
self.assert_('expires' in data['access']['token'])
self.assertDeepEquals(self.auth_response['access']['user'],
data['access']['user'])
self.assertDeepEquals(self.auth_response['access']['serviceCatalog'],
data['access']['serviceCatalog'])
def test_validate_token_scoped(self):
client = self.client(self.app, token=self.token_123['id'])
resp = client.get('/v2.0/tokens/%s' % self.token_123['id'])
data = json.loads(resp.body)
self.assertDeepEquals(self.validate_token, data)
def test_validate_token_scoped(self):
client = self.client(self.app, token=self.token_123['id'])
resp = client.get('/v2.0/tokens/%s' % self.token_123['id'])