Added support for HEAD /tokens/{token_id}
Changed POST /tokens response container from 'auth' to 'access' Change-Id: Ibb8cf43948bce0de08cdbdb0619c4d640ced56cd
This commit is contained in:
parent
012b2125fb
commit
64ce8c8a3b
Binary file not shown.
Binary file not shown.
|
@ -24,14 +24,22 @@ class AuthController(wsgi.Controller):
|
|||
return utils.send_result(200, req,
|
||||
config.SERVICE.authenticate_ec2(creds))
|
||||
|
||||
@utils.wrap_error
|
||||
def validate_token(self, req, token_id):
|
||||
belongs_to = req.GET.get("belongsTo", None)
|
||||
|
||||
rval = config.SERVICE.validate_token(
|
||||
def _validate_token(self, req, token_id):
|
||||
"""Validates the token, and that it belongs to the specified tenant"""
|
||||
belongs_to = req.GET.get('belongsTo')
|
||||
return config.SERVICE.validate_token(
|
||||
utils.get_auth_token(req), token_id, belongs_to)
|
||||
|
||||
return utils.send_result(200, req, rval)
|
||||
@utils.wrap_error
|
||||
def validate_token(self, req, token_id):
|
||||
result = self._validate_token(req, token_id)
|
||||
return utils.send_result(200, req, result)
|
||||
|
||||
@utils.wrap_error
|
||||
def check_token(self, req, token_id):
|
||||
"""Validates the token, but only returns a status code (HEAD)"""
|
||||
self._validate_token(req, token_id)
|
||||
return utils.send_result(200, req)
|
||||
|
||||
@utils.wrap_error
|
||||
def delete_token(self, req, token_id):
|
||||
|
|
|
@ -85,8 +85,8 @@ class AuthProtocol(object):
|
|||
def __transform_headers(self, content):
|
||||
"""Transform Keystone auth to legacy headers"""
|
||||
headers = {}
|
||||
if "auth" in content:
|
||||
auth = content["auth"]
|
||||
if "access" in content:
|
||||
auth = content["access"]
|
||||
if "token" in auth:
|
||||
headers["X-Auth-Token"] = auth["token"]["id"]
|
||||
if "serviceCatalog" in auth:
|
||||
|
|
|
@ -123,11 +123,17 @@ class IdentityService(object):
|
|||
|
||||
if not api.TOKEN.get(token_id):
|
||||
raise fault.UnauthorizedFault("Bad token, please reauthenticate")
|
||||
|
||||
(token, user) = self.__validate_token(token_id, belongs_to)
|
||||
|
||||
return self.__get_validate_data(token, user)
|
||||
|
||||
def check_token(self, admin_token, token_id, belongs_to=None):
|
||||
self.__validate_service_or_keystone_admin_token(admin_token)
|
||||
|
||||
if not api.TOKEN.get(token_id):
|
||||
raise fault.UnauthorizedFault("Bad token, please reauthenticate")
|
||||
|
||||
self.__validate_token(token_id, belongs_to)
|
||||
|
||||
def revoke_token(self, admin_token, token_id):
|
||||
self.__validate_admin_token(admin_token)
|
||||
|
||||
|
|
|
@ -226,7 +226,7 @@ class AuthData(object):
|
|||
self.__convert_baseurls_to_dict()
|
||||
|
||||
def to_xml(self):
|
||||
dom = etree.Element("auth",
|
||||
dom = etree.Element("access",
|
||||
xmlns="http://docs.openstack.org/identity/api/v2.0")
|
||||
token = etree.Element("token",
|
||||
expires=self.token.expires.isoformat())
|
||||
|
@ -245,8 +245,8 @@ class AuthData(object):
|
|||
base_url_item = getattr(base_url, url_kind + "_url")
|
||||
if base_url_item:
|
||||
endpoint.set(url_kind + "URL", base_url_item.\
|
||||
replace('%tenant_id%', self.token.tenant_id)
|
||||
if self.token.tenant_id else base_url_item)
|
||||
replace('%tenant_id%', str(self.token.tenant_id))
|
||||
if self.token.tenant_id else base_url_item)
|
||||
service.append(endpoint)
|
||||
service_catalog.append(service)
|
||||
dom.append(service_catalog)
|
||||
|
@ -283,7 +283,7 @@ class AuthData(object):
|
|||
service_catalog[key] = endpoints
|
||||
auth["serviceCatalog"] = service_catalog
|
||||
ret = {}
|
||||
ret["auth"] = auth
|
||||
ret["access"] = auth
|
||||
return json.dumps(ret)
|
||||
|
||||
|
||||
|
|
|
@ -279,18 +279,18 @@ class AuthProtocol(object):
|
|||
|
||||
token_info = json.loads(data)
|
||||
roles = []
|
||||
role_refs = token_info["auth"]["user"]["roleRefs"]
|
||||
role_refs = token_info["access"]["user"]["roleRefs"]
|
||||
if role_refs != None:
|
||||
for role_ref in role_refs:
|
||||
roles.append(role_ref["roleId"])
|
||||
|
||||
try:
|
||||
tenant = token_info['auth']['token']['tenantId']
|
||||
tenant = token_info['access']['token']['tenantId']
|
||||
except:
|
||||
tenant = None
|
||||
if not tenant:
|
||||
tenant = token_info['auth']['user']['tenantId']
|
||||
verified_claims = {'user': token_info['auth']['user']['username'],
|
||||
tenant = token_info['access']['user']['tenantId']
|
||||
verified_claims = {'user': token_info['access']['user']['username'],
|
||||
'tenant': tenant,
|
||||
'roles': roles}
|
||||
return verified_claims
|
||||
|
|
|
@ -212,19 +212,19 @@ class AuthProtocol(object):
|
|||
|
||||
identity_info = json.loads(data)
|
||||
roles = []
|
||||
role_refs = identity_info["auth"]["user"]["roleRefs"]
|
||||
role_refs = identity_info["access"]["user"]["roleRefs"]
|
||||
if role_refs is not None:
|
||||
for role_ref in role_refs:
|
||||
roles.append(role_ref["roleId"])
|
||||
|
||||
try:
|
||||
tenant = identity_info['auth']['token']['tenantId']
|
||||
tenant = identity_info['access']['token']['tenantId']
|
||||
except:
|
||||
tenant = None
|
||||
if not tenant:
|
||||
tenant = identity_info['auth']['user']['tenantId']
|
||||
tenant = identity_info['access']['user']['tenantId']
|
||||
# TODO(Ziad): add groups back in
|
||||
identity = {'user': identity_info['auth']['user']['username'],
|
||||
identity = {'user': identity_info['access']['user']['username'],
|
||||
'tenant': tenant,
|
||||
'roles': roles}
|
||||
|
||||
|
|
|
@ -46,6 +46,9 @@ class AdminApi(wsgi.Router):
|
|||
mapper.connect("/tokens/{token_id}", controller=auth_controller,
|
||||
action="validate_token",
|
||||
conditions=dict(method=["GET"]))
|
||||
mapper.connect("/tokens/{token_id}", controller=auth_controller,
|
||||
action="check_token",
|
||||
conditions=dict(method=["HEAD"]))
|
||||
mapper.connect("/tokens/{token_id}", controller=auth_controller,
|
||||
action="delete_token",
|
||||
conditions=dict(method=["DELETE"]))
|
||||
|
|
|
@ -107,10 +107,11 @@ class RestfulTestCase(HttpTestCase):
|
|||
|
||||
def _decode_response_body(self, response):
|
||||
"""Detects response body type, and attempts to decode it"""
|
||||
if 'application/json' in response.getheader('Content-Type', ''):
|
||||
response.json = self._decode_json(response.body)
|
||||
elif 'application/xml' in response.getheader('Content-Type', ''):
|
||||
response.xml = self._decode_xml(response.body)
|
||||
if response.body != None and response.body.strip():
|
||||
if 'application/json' in response.getheader('Content-Type', ''):
|
||||
response.json = self._decode_json(response.body)
|
||||
elif 'application/xml' in response.getheader('Content-Type', ''):
|
||||
response.xml = self._decode_xml(response.body)
|
||||
return response
|
||||
|
||||
@staticmethod
|
||||
|
@ -186,6 +187,16 @@ class ApiTestCase(RestfulTestCase):
|
|||
return self.admin_request(method='GET',
|
||||
path='/tokens/%s?belongsTo=%s' % (token_id, tenant_id), **kwargs)
|
||||
|
||||
def check_token(self, token_id, **kwargs):
|
||||
"""HEAD /tokens/{token_id}"""
|
||||
return self.admin_request(method='HEAD',
|
||||
path='/tokens/%s' % (token_id,), **kwargs)
|
||||
|
||||
def check_token_belongs_to(self, token_id, tenant_id, **kwargs):
|
||||
"""HEAD /tokens/{token_id}?belongsTo={tenant_id}"""
|
||||
return self.admin_request(method='HEAD',
|
||||
path='/tokens/%s?belongsTo=%s' % (token_id, tenant_id), **kwargs)
|
||||
|
||||
def delete_token(self, token_id, **kwargs):
|
||||
"""DELETE /tokens/{token_id}"""
|
||||
return self.admin_request(method='DELETE',
|
||||
|
@ -453,7 +464,7 @@ class FunctionalTestCase(ApiTestCase):
|
|||
"""Prepare keystone for system tests"""
|
||||
# Authenticate as admin user to establish admin_token
|
||||
self.admin_token = self.authenticate(self.admin_username,
|
||||
self.admin_password).json['auth']['token']['id']
|
||||
self.admin_password).json['access']['token']['id']
|
||||
self.admin_user_id = self.fetch_user_by_name('admin').\
|
||||
json['users']['values'][0]['id']
|
||||
|
||||
|
@ -467,7 +478,6 @@ class FunctionalTestCase(ApiTestCase):
|
|||
"passwordCredentials": {
|
||||
"username": user_name,
|
||||
"password": user_password}}}
|
||||
|
||||
if tenant_id:
|
||||
data["auth"]["tenantId"] = tenant_id
|
||||
|
||||
|
|
|
@ -15,8 +15,8 @@ class TestAdminAuthentication(common.FunctionalTestCase):
|
|||
r = self.authenticate(self.admin_username, self.admin_password)
|
||||
|
||||
# Assert we get back a token with an expiration date
|
||||
self.assertTrue(r.json['auth']['token']['id'])
|
||||
self.assertTrue(r.json['auth']['token']['expires'])
|
||||
self.assertTrue(r.json['access']['token']['id'])
|
||||
self.assertTrue(r.json['access']['token']['expires'])
|
||||
|
||||
|
||||
class TestAdminAuthenticationNegative(common.FunctionalTestCase):
|
||||
|
@ -32,7 +32,7 @@ class TestAdminAuthenticationNegative(common.FunctionalTestCase):
|
|||
|
||||
# Replace our admin_token with a mere service token
|
||||
self.admin_token = self.authenticate(user['name'], user['password']).\
|
||||
json['auth']['token']['id']
|
||||
json['access']['token']['id']
|
||||
|
||||
# Try creating another user using the wrong token
|
||||
self.create_user(assert_status=401)
|
||||
|
@ -57,7 +57,7 @@ class TestServiceAuthentication(common.FunctionalTestCase):
|
|||
'passwordCredentials': {
|
||||
'username': self.user['name'],
|
||||
'password': self.user['password']}}}).\
|
||||
json['auth']['token']['id']
|
||||
json['access']['token']['id']
|
||||
|
||||
# In the real world, the service user would then pass his/her token
|
||||
# to some service that depends on keystone, which would then need to
|
||||
|
|
|
@ -43,8 +43,8 @@ class AuthenticationTest(common.FunctionalTestCase):
|
|||
r = self.authenticate(self.user['name'], self.user['password'],
|
||||
self.tenant['id'], assert_status=200)
|
||||
|
||||
self.assertIsNotNone(r.json['auth']['token'])
|
||||
self.assertIsNotNone(r.json['auth']['serviceCatalog'])
|
||||
self.assertIsNotNone(r.json['access']['token'])
|
||||
self.assertIsNotNone(r.json['access']['serviceCatalog'])
|
||||
|
||||
def test_authorize_xml(self):
|
||||
data = ('<?xml version="1.0" encoding="UTF-8"?> '
|
||||
|
@ -55,7 +55,7 @@ class AuthenticationTest(common.FunctionalTestCase):
|
|||
self.user['name'], self.user['password'])
|
||||
r = self.post_token(as_xml=data, assert_status=200)
|
||||
|
||||
self.assertEquals(r.xml.tag, '{%s}auth' % self.xmlns)
|
||||
self.assertEquals(r.xml.tag, '{%s}access' % self.xmlns)
|
||||
serviceCatalog = r.xml.find('{%s}serviceCatalog' % self.xmlns)
|
||||
self.assertIsNotNone(serviceCatalog)
|
||||
|
||||
|
@ -79,7 +79,7 @@ class AuthenticationTest(common.FunctionalTestCase):
|
|||
"passwordCredentials": {
|
||||
"username-field-completely-wrong": self.user['name'],
|
||||
"password": self.user['password']},
|
||||
"tenantId": self.tenant['id']}}
|
||||
"tenantId": self.tenant['id']}}
|
||||
self.post_token(as_json=data, assert_status=400)
|
||||
|
||||
def test_authorize_user_wrong_xml(self):
|
||||
|
|
|
@ -16,7 +16,7 @@ class TestIssue85(common.FunctionalTestCase):
|
|||
|
||||
# Authenticate as user to get a token *for a specific tenant*
|
||||
user_token = self.authenticate(user['name'], user['password'],
|
||||
tenant['id']).json['auth']['token']['id']
|
||||
tenant['id']).json['access']['token']['id']
|
||||
|
||||
# Validate and check that token belongs to tenant
|
||||
tenantid = self.get_token(user_token).\
|
||||
|
|
|
@ -128,7 +128,7 @@ class GetTenantsTest(TenantTest):
|
|||
user = self.create_user_with_known_password(tenant_id=tenant['id']).\
|
||||
json['user']
|
||||
token = self.authenticate(user['name'], user['password'],
|
||||
tenant['id']).json['auth']['token']
|
||||
tenant['id']).json['access']['token']
|
||||
self.service_token = token['id']
|
||||
tenants = self.service_request(method='GET', path='/tenants',
|
||||
assert_status=200).json['tenants']['values']
|
||||
|
@ -140,7 +140,7 @@ class GetTenantsTest(TenantTest):
|
|||
user = self.create_user_with_known_password(tenant_id=tenant['id']).\
|
||||
json['user']
|
||||
token = self.authenticate(user['name'], user['password'],
|
||||
tenant['id']).json['auth']['token']
|
||||
tenant['id']).json['access']['token']
|
||||
self.service_token = token['id']
|
||||
|
||||
r = self.service_request(method='GET', path='/tenants',
|
||||
|
|
|
@ -30,7 +30,7 @@ class ValidateToken(common.FunctionalTestCase):
|
|||
self.role_ref = self.grant_role_to_user(self.user['id'],
|
||||
self.role['id'], self.tenant['id']).json['role']
|
||||
self.token = self.authenticate(self.user['name'],
|
||||
self.user['password'], self.tenant['id']).json['auth']['token']
|
||||
self.user['password'], self.tenant['id']).json['access']['token']
|
||||
|
||||
def test_validate_token_true(self):
|
||||
r = self.get_token_belongsto(self.token['id'], self.tenant['id'],
|
||||
|
@ -85,5 +85,34 @@ class ValidateToken(common.FunctionalTestCase):
|
|||
'Accept': 'application/xml'})
|
||||
|
||||
|
||||
class CheckToken(common.FunctionalTestCase):
|
||||
def setUp(self, *args, **kwargs):
|
||||
super(CheckToken, self).setUp(*args, **kwargs)
|
||||
self.tenant = self.create_tenant().json['tenant']
|
||||
self.user = self.create_user_with_known_password(
|
||||
tenant_id=self.tenant['id']).json['user']
|
||||
self.token = self.authenticate(self.user['name'],
|
||||
self.user['password'], self.tenant['id']).json['access']['token']
|
||||
|
||||
def test_validate_token_true(self):
|
||||
self.check_token_belongs_to(self.token['id'], self.tenant['id'],
|
||||
assert_status=200)
|
||||
|
||||
def test_validate_token_true_using_service_token(self):
|
||||
self.admin_token = self.service_admin_token
|
||||
self.check_token_belongs_to(self.token['id'], self.tenant['id'],
|
||||
assert_status=200)
|
||||
|
||||
def test_validate_token_expired(self):
|
||||
self.check_token(self.expired_admin_token, assert_status=403)
|
||||
|
||||
def test_validate_token_expired_xml(self):
|
||||
self.check_token(self.expired_admin_token, assert_status=403, headers={
|
||||
'Accept': 'application/xml'})
|
||||
|
||||
def test_validate_token_invalid(self):
|
||||
self.check_token(common.unique_str(), assert_status=401)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
|
|
@ -68,7 +68,7 @@ class EC2AuthnMethods(base.ServiceAPITest):
|
|||
self.get_response()
|
||||
|
||||
expected = {
|
||||
u'auth': {
|
||||
u'access': {
|
||||
u'serviceCatalog': {},
|
||||
u'token': {
|
||||
u'expires': self.expires.strftime("%Y-%m-%dT%H:%M:%S.%f"),
|
||||
|
|
|
@ -106,7 +106,7 @@ def send_error(code, req, result):
|
|||
return resp
|
||||
|
||||
|
||||
def send_result(code, req, result):
|
||||
def send_result(code, req, result=None):
|
||||
content = None
|
||||
|
||||
resp = Response()
|
||||
|
|
Loading…
Reference in New Issue