authenticate working, too
This commit is contained in:
parent
ba4913f463
commit
d920d8432a
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 []
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
|
@ -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'])
|
||||
|
|
Loading…
Reference in New Issue