diff options
| author | Yogeshwar Srikrishnan <yoga80@yahoo.com> | 2011-09-20 14:54:53 -0500 |
|---|---|---|
| committer | Dolph Mathews <dolph.mathews@gmail.com> | 2011-09-21 12:02:53 -0500 |
| commit | 64ce8c8a3b4a1e747c114ca50e3a05e65f36759d (patch) | |
| tree | f13a305b0e45d349ae10899f26698e9e88c65986 | |
| parent | 012b2125fb121f44a1786bbd21f60568c74be367 (diff) | |
Added support for HEAD /tokens/{token_id}
Changed POST /tokens response container from 'auth' to 'access'
Change-Id: Ibb8cf43948bce0de08cdbdb0619c4d640ced56cd
| -rw-r--r-- | keystone/content/admin/identityadminguide.pdf | bin | 269587 -> 269594 bytes | |||
| -rw-r--r-- | keystone/content/service/identitydevguide.pdf | bin | 269587 -> 269594 bytes | |||
| -rw-r--r-- | keystone/controllers/auth.py | 18 | ||||
| -rw-r--r-- | keystone/frontends/legacy_token_auth.py | 4 | ||||
| -rwxr-xr-x | keystone/logic/service.py | 10 | ||||
| -rwxr-xr-x | keystone/logic/types/auth.py | 8 | ||||
| -rwxr-xr-x | keystone/middleware/auth_token.py | 8 | ||||
| -rwxr-xr-x | keystone/middleware/swift_auth.py | 8 | ||||
| -rwxr-xr-x | keystone/routers/admin.py | 3 | ||||
| -rw-r--r-- | keystone/test/functional/common.py | 22 | ||||
| -rw-r--r-- | keystone/test/functional/test_auth.py | 8 | ||||
| -rwxr-xr-x | keystone/test/functional/test_authentication.py | 8 | ||||
| -rw-r--r-- | keystone/test/functional/test_issue_85.py | 2 | ||||
| -rwxr-xr-x | keystone/test/functional/test_tenants.py | 4 | ||||
| -rwxr-xr-x | keystone/test/functional/test_token.py | 31 | ||||
| -rwxr-xr-x | keystone/test/unit/test_ec2_authn.py | 2 | ||||
| -rwxr-xr-x | keystone/utils.py | 2 |
17 files changed, 97 insertions, 41 deletions
diff --git a/keystone/content/admin/identityadminguide.pdf b/keystone/content/admin/identityadminguide.pdf Binary files differindex 3a1c5b3d..5d412368 100644 --- a/keystone/content/admin/identityadminguide.pdf +++ b/keystone/content/admin/identityadminguide.pdf diff --git a/keystone/content/service/identitydevguide.pdf b/keystone/content/service/identitydevguide.pdf Binary files differindex 3a1c5b3d..5d412368 100644 --- a/keystone/content/service/identitydevguide.pdf +++ b/keystone/content/service/identitydevguide.pdf diff --git a/keystone/controllers/auth.py b/keystone/controllers/auth.py index bd30afb6..b8d3a8bb 100644 --- a/keystone/controllers/auth.py +++ b/keystone/controllers/auth.py @@ -24,14 +24,22 @@ class AuthController(wsgi.Controller): return utils.send_result(200, req, config.SERVICE.authenticate_ec2(creds)) + 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) + @utils.wrap_error def validate_token(self, req, token_id): - belongs_to = req.GET.get("belongsTo", None) + result = self._validate_token(req, token_id) + return utils.send_result(200, req, result) - rval = config.SERVICE.validate_token( - utils.get_auth_token(req), token_id, belongs_to) - - return utils.send_result(200, req, rval) + @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): diff --git a/keystone/frontends/legacy_token_auth.py b/keystone/frontends/legacy_token_auth.py index fb5f65f0..7fe83d79 100644 --- a/keystone/frontends/legacy_token_auth.py +++ b/keystone/frontends/legacy_token_auth.py @@ -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: diff --git a/keystone/logic/service.py b/keystone/logic/service.py index dba9c564..fce5b420 100755 --- a/keystone/logic/service.py +++ b/keystone/logic/service.py @@ -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) diff --git a/keystone/logic/types/auth.py b/keystone/logic/types/auth.py index 5fff98df..edc94200 100755 --- a/keystone/logic/types/auth.py +++ b/keystone/logic/types/auth.py @@ -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) diff --git a/keystone/middleware/auth_token.py b/keystone/middleware/auth_token.py index e0e993d8..b766966e 100755 --- a/keystone/middleware/auth_token.py +++ b/keystone/middleware/auth_token.py @@ -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 diff --git a/keystone/middleware/swift_auth.py b/keystone/middleware/swift_auth.py index f92b2d76..ff498b12 100755 --- a/keystone/middleware/swift_auth.py +++ b/keystone/middleware/swift_auth.py @@ -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} diff --git a/keystone/routers/admin.py b/keystone/routers/admin.py index bf804388..d63304f9 100755 --- a/keystone/routers/admin.py +++ b/keystone/routers/admin.py @@ -47,6 +47,9 @@ class AdminApi(wsgi.Router): 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"])) diff --git a/keystone/test/functional/common.py b/keystone/test/functional/common.py index 1cc1615a..c408905a 100644 --- a/keystone/test/functional/common.py +++ b/keystone/test/functional/common.py @@ -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 diff --git a/keystone/test/functional/test_auth.py b/keystone/test/functional/test_auth.py index d192959c..c2d70296 100644 --- a/keystone/test/functional/test_auth.py +++ b/keystone/test/functional/test_auth.py @@ -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 diff --git a/keystone/test/functional/test_authentication.py b/keystone/test/functional/test_authentication.py index 485477ea..d860db91 100755 --- a/keystone/test/functional/test_authentication.py +++ b/keystone/test/functional/test_authentication.py @@ -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): diff --git a/keystone/test/functional/test_issue_85.py b/keystone/test/functional/test_issue_85.py index d52aa892..0244a40a 100644 --- a/keystone/test/functional/test_issue_85.py +++ b/keystone/test/functional/test_issue_85.py @@ -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).\ diff --git a/keystone/test/functional/test_tenants.py b/keystone/test/functional/test_tenants.py index 8f51fe6d..d3d197d9 100755 --- a/keystone/test/functional/test_tenants.py +++ b/keystone/test/functional/test_tenants.py @@ -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', diff --git a/keystone/test/functional/test_token.py b/keystone/test/functional/test_token.py index 14000139..a96bd111 100755 --- a/keystone/test/functional/test_token.py +++ b/keystone/test/functional/test_token.py @@ -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() diff --git a/keystone/test/unit/test_ec2_authn.py b/keystone/test/unit/test_ec2_authn.py index 2593a38f..c85d274a 100755 --- a/keystone/test/unit/test_ec2_authn.py +++ b/keystone/test/unit/test_ec2_authn.py @@ -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"), diff --git a/keystone/utils.py b/keystone/utils.py index 1dbd3fc4..b9e95cd2 100755 --- a/keystone/utils.py +++ b/keystone/utils.py @@ -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() |
